flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/apps/status/src/model.test.ts

259 lines12,606 bytesCodeBlame
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import { components } from "./components.ts";
5import {
6 type DayRow,
7 barFor,
8 buildPage,
9 classify,
10 dayState,
11 effectiveState,
12 lastDays,
13 maintenanceState,
14 openOn,
15 percent,
16 recentIncidents,
17 summarize,
18 uptimeOf,
19 uptimeOver,
20} from "./model.ts";
21
22const VARS = {
23 SITE_URL: "https://g1t.sh",
24 API_URL: "https://api.g1t.sh",
25 MCP_URL: "https://mcp.g1t.sh",
26 DOCS_URL: "https://docs.g1t.sh",
27 PAGES_URL: "https://g1t.page",
28 MODELS_URL: "https://models.g1t.sh",
29 PROBE_REPO: "flagon-io/g1t",
30};
31
32const row = (component: string, day: string, up: number, degraded = 0, down = 0): DayRow => ({
33 component,
34 day,
35 checks: up + degraded + down,
36 up,
37 degraded,
38 down,
39 latency_total: (up + degraded) * 100,
40 latency_count: up + degraded,
41});
42
43test("classify: fast is up, slow is degraded, failed is down, none is unmonitored", () => {
44 assert.equal(classify({ ok: true, ms: 84.4 }).state, "up");
45 assert.equal(classify({ ok: true, ms: 84.4 }).detail, "Answered in 84 ms");
46 assert.equal(classify({ ok: true, ms: 2000 }).state, "degraded");
47 assert.deepEqual(classify({ ok: false, ms: 5000, error: "timed out" }), { state: "down", detail: "Failed: timed out" });
48 assert.equal(classify(null).state, "unmonitored");
49});
50
51test("uptime rounds down, so one failure never reads as 100%", () => {
52 assert.equal(uptimeOf(1439, 1440), 99.93);
53 assert.equal(uptimeOf(99999, 100000), 99.99);
54 assert.equal(uptimeOf(10, 10), 100);
55 assert.equal(uptimeOf(0, 0), null);
56 assert.equal(percent(100), "100%");
57 assert.equal(percent(99.5), "99.50%");
58 assert.equal(percent(null), "No data");
59});
60
61test("a day's colour: a blip stays green, a bad hour is degraded, worse is down", () => {
62 assert.equal(dayState(null), "none");
63 assert.equal(dayState({ checks: 1440, up: 1439, degraded: 0, down: 1 }), "up");
64 assert.equal(dayState({ checks: 1440, up: 1380, degraded: 0, down: 60 }), "degraded");
65 assert.equal(dayState({ checks: 1440, up: 1000, degraded: 0, down: 440 }), "down");
66 // Answering, but slow much of the day.
67 assert.equal(dayState({ checks: 100, up: 60, degraded: 40, down: 0 }), "degraded");
68 // An incident colours the day at least as badly as its impact.
69 assert.equal(dayState({ checks: 1440, up: 1440, degraded: 0, down: 0 }, "down"), "down");
70 assert.equal(dayState(null, "degraded"), "degraded");
71});
72
73test("lastDays ends today, oldest first", () => {
74 const days = lastDays(new Date("2026-10-05T12:00:00Z"));
75 assert.equal(days.length, 90);
76 assert.equal(days.at(-1), "2026-10-05");
77 assert.equal(days[0], "2026-07-08");
78});
79
80test("an incident is on every day it was open", () => {
81 const incident = { started_at: "2026-10-03T23:30:00Z", resolved_at: "2026-10-04T00:10:00Z" };
82 assert.equal(openOn(incident, "2026-10-02"), false);
83 assert.equal(openOn(incident, "2026-10-03"), true);
84 assert.equal(openOn(incident, "2026-10-04"), true);
85 assert.equal(openOn(incident, "2026-10-05"), false);
86 assert.equal(openOn({ started_at: "2026-10-01T00:00:00Z", resolved_at: null }, "2026-10-05"), true);
87});
88
89test("bars and 90-day uptime come from the daily tally", () => {
90 const days = ["2026-10-03", "2026-10-04", "2026-10-05"];
91 const rows = [row("api", "2026-10-04", 1439, 0, 1), row("api", "2026-10-05", 600), row("git", "2026-10-05", 10)];
92 const bar = barFor("api", rows, [], days);
93 assert.deepEqual(
94 bar.map((d) => d.state),
95 ["none", "up", "up"],
96 );
97 assert.equal(bar[1]!.failed, 1);
98 assert.equal(bar[1]!.avg_ms, 100);
99 assert.equal(uptimeOver("api", rows), uptimeOf(2039, 2040));
100 assert.equal(uptimeOver("docs", rows), null);
101});
102
103test("a bar marks the days an incident on its part was open", () => {
104 const incident = {
105 id: "1",
106 title: "Clones failing",
107 impact: "down" as const,
108 status: "resolved" as const,
109 components: ["git"],
110 component_impacts: [{ key: "git", impact: "major_outage" as const }],
111 started_at: "2026-10-04T10:00:00Z",
112 resolved_at: "2026-10-04T11:00:00Z",
113 url: "https://status.g1t.sh/incidents/1",
114 postmortem_published_at: null,
115 updates: [],
116 };
117 const days = ["2026-10-04", "2026-10-05"];
118 const git = barFor("git", [row("git", "2026-10-04", 1440)], [incident], days);
119 assert.equal(git[0]!.state, "down");
120 assert.deepEqual(git[0]!.incidents, ["Clones failing"]);
121 assert.equal(barFor("api", [row("api", "2026-10-04", 1440)], [incident], days)[0]!.state, "up");
122});
123
124test("summarize: core down is a major outage, others partial, slow is degraded performance", () => {
125 const core = new Set(["site", "api"]);
126 const up = { key: "api", name: "API", state: "up" as const };
127 assert.equal(summarize([up], core).title, "All systems normal");
128 assert.equal(summarize([{ ...up, state: "down" }], core).title, "Major outage");
129 assert.equal(summarize([up, { key: "docs", name: "Documentation", state: "down" }], core).title, "Partial outage");
130 const slow = summarize([up, { key: "docs", name: "Documentation", state: "degraded" }], core);
131 assert.equal(slow.title, "Degraded performance");
132 assert.match(slow.line, /Documentation/);
133 assert.equal(summarize([{ key: "sandboxes", name: "Sandboxes", state: "unmonitored" }], core).state, "unknown");
134 const incident = summarize([up], core, [{ title: "Pushes failing", impact: "degraded", status: "identified" }]);
135 assert.equal(incident.title, "Partial outage");
136 assert.equal(incident.line, "Identified: Pushes failing.");
137});
138
139test("recent incidents: open ones and those resolved in 90 days, newest first", () => {
140 const now = new Date("2026-10-05T00:00:00Z");
141 const list = recentIncidents(
142 [
143 { id: "old", started_at: "2026-01-01T00:00:00Z", resolved_at: "2026-01-01T01:00:00Z" },
144 { id: "open", started_at: "2026-01-02T00:00:00Z", resolved_at: null },
145 { id: "new", started_at: "2026-10-01T00:00:00Z", resolved_at: "2026-10-01T01:00:00Z" },
146 ],
147 now,
148 );
149 assert.deepEqual(
150 list.map((i) => i.id),
151 ["new", "open"],
152 );
153});
154
155test("buildPage: parts with no check are unmonitored and have no uptime; staleness is noticed", () => {
156 const now = new Date("2026-10-05T12:00:00Z");
157 const parts = components(VARS, true);
158 const current = new Map(parts.map((p) => [p.key, { state: "up" as const, detail: "Answered in 80 ms", latency_ms: 80 }]));
159 const page = buildPage({
160 parts,
161 current,
162 checkedAt: "2026-10-05T11:59:30Z",
163 days: [row("api", "2026-10-05", 700)],
164 incidents: [],
165 now,
166 });
167 const sandboxes = page.report.components.find((c) => c.key === "sandboxes")!;
168 assert.equal(sandboxes.state, "unmonitored");
169 assert.equal(sandboxes.uptime_90d, null);
170 assert.equal(page.report.components.find((c) => c.key === "api")!.uptime_90d, 100);
171 assert.equal(page.report.overall.title, "All systems normal");
172 assert.equal(page.stale, false);
173 assert.equal(page.bars.api!.length, 90);
174 assert.equal(buildPage({ parts, current, checkedAt: "2026-10-05T11:00:00Z", days: [], incidents: [], now }).stale, true);
175});
176
177test("components: an installation without a host leaves that part off", () => {
178 const keys = components({ SITE_URL: "http://localhost:8787", API_URL: "http://localhost:8787/api", PROBE_REPO: "me/demo" }, false).map(
179 (c) => c.key,
180 );
181 assert.deepEqual(keys, ["site", "api", "git", "speed"]);
182 const bare = components({ SITE_URL: "http://g1t:8787" }, false);
183 assert.deepEqual(
184 bare.map((c) => c.key),
185 ["site"],
186 );
187 assert.equal(bare[0]!.check.kind === "http" && bare[0]!.check.steps.length, 1);
188 const all = components(VARS, true);
189 assert.deepEqual(
190 all.map((c) => c.key),
191 ["site", "api", "git", "speed", "mcp", "docs", "deployments", "agents", "sandboxes", "billing"],
192 );
193 const speed = all.find((c) => c.key === "speed")!;
194 assert.deepEqual(speed.check, { kind: "http", steps: [{ url: "https://g1t.sh/flagon-io/g1t" }, { url: "https://g1t.sh/explore" }] });
195 assert.equal(classify({ ok: true, ms: 900 }, speed.slowMs).state, "degraded");
196 assert.equal(classify({ ok: true, ms: 300 }, speed.slowMs).state, "up");
197 const git = all.find((c) => c.key === "git")!;
198 assert.deepEqual(git.check, { kind: "http", steps: [{ url: "https://g1t.sh/flagon-io/g1t.git/info/refs?service=git-upload-pack" }] });
199});
200
201test("a part's state: the worse of its check and open incidents; maintenance unless an incident says worse", () => {
202 assert.equal(effectiveState("up", [], false), "up");
203 assert.equal(effectiveState("up", ["partial_outage"], false), "partial");
204 assert.equal(effectiveState("down", ["degraded"], false), "down", "a failing check beats a milder report");
205 assert.equal(effectiveState("degraded", ["major_outage", "degraded"], false), "down", "the worst impact wins");
206 assert.equal(effectiveState("up", ["operational"], false), "up");
207 assert.equal(effectiveState("unmonitored", ["degraded"], false), "degraded", "an incident speaks for a part with no check");
208 assert.equal(effectiveState("down", [], true), "maintenance", "failing checks in a window are expected");
209 assert.equal(effectiveState("up", ["major_outage"], true), "down", "an incident during maintenance still shows");
210});
211
212test("maintenance moves with its window, and cancelled or completed stays put", () => {
213 const m = { state: "scheduled" as const, starts_at: "2026-10-05T12:00:00Z", ends_at: "2026-10-05T13:00:00Z" };
214 assert.equal(maintenanceState(m, new Date("2026-10-05T11:59:00Z")), "scheduled");
215 assert.equal(maintenanceState(m, new Date("2026-10-05T12:00:00Z")), "in_progress");
216 assert.equal(maintenanceState(m, new Date("2026-10-05T13:00:00Z")), "completed");
217 assert.equal(maintenanceState({ ...m, state: "in_progress" }, new Date("2026-10-05T11:00:00Z")), "in_progress", "started early by hand");
218 assert.equal(maintenanceState({ ...m, state: "cancelled" }, new Date("2026-10-05T12:30:00Z")), "cancelled");
219 assert.equal(maintenanceState({ ...m, state: "completed" }, new Date("2026-10-05T12:30:00Z")), "completed", "finished early by hand");
220});
221
222test("buildPage: incident impacts and maintenance reach the parts and the banner", () => {
223 const now = new Date("2026-10-05T12:30:00Z");
224 const parts = components(VARS, false);
225 const current = new Map(parts.map((p) => [p.key, { state: "up" as const, detail: "Answered in 80 ms", latency_ms: 80 }]));
226 current.set("docs", { state: "down", detail: "Failed: HTTP 502", latency_ms: null });
227 const maintenance = [
228 { id: "m1", title: "Docs move", message: "Moving docs.", components: ["docs"], starts_at: "2026-10-05T12:00:00Z", ends_at: "2026-10-05T13:00:00Z", state: "scheduled" as const, url: "", updates: [] },
229 { id: "m2", title: "Later", message: "Later.", components: ["api"], starts_at: "2026-10-06T12:00:00Z", ends_at: "2026-10-06T13:00:00Z", state: "scheduled" as const, url: "", updates: [] },
230 { id: "m3", title: "Called off", message: "No.", components: ["api"], starts_at: "2026-10-05T12:00:00Z", ends_at: "2026-10-05T13:00:00Z", state: "cancelled" as const, url: "", updates: [] },
231 ];
232 const quiet = buildPage({ parts, current, checkedAt: "2026-10-05T12:29:30Z", days: [], incidents: [], maintenance, now });
233 const docs = quiet.report.components.find((c) => c.key === "docs")!;
234 assert.equal(docs.state, "maintenance");
235 assert.equal(docs.check_state, "down");
236 assert.equal(quiet.report.overall.state, "maintenance");
237 assert.equal(quiet.report.overall.title, "Under maintenance");
238 assert.deepEqual(quiet.report.maintenance.map((m) => [m.id, m.state]), [["m1", "in_progress"], ["m2", "scheduled"]]);
239
240 const incident = {
241 id: "i1",
242 title: "API errors",
243 impact: "degraded" as const,
244 status: "identified" as const,
245 components: ["api"],
246 component_impacts: [{ key: "api", impact: "partial_outage" as const }],
247 started_at: "2026-10-05T12:10:00Z",
248 resolved_at: null,
249 url: "",
250 postmortem_published_at: null,
251 updates: [],
252 };
253 const busy = buildPage({ parts, current, checkedAt: "2026-10-05T12:29:30Z", days: [], incidents: [incident], maintenance, now });
254 assert.equal(busy.report.components.find((c) => c.key === "api")!.state, "partial");
255 assert.equal(busy.report.overall.title, "Partial outage");
256 assert.equal(busy.report.overall.line, "Identified: API errors.");
257 const resolved = buildPage({ parts, current, checkedAt: "2026-10-05T12:29:30Z", days: [], incidents: [{ ...incident, resolved_at: "2026-10-05T12:20:00Z" }], now });
258 assert.equal(resolved.report.components.find((c) => c.key === "api")!.state, "up", "a resolved incident no longer colours its part");
259});