Skip to content

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

219 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import {
5 PER_PAGE,
6 SOURCE_LABEL,
7 STATE_WORD,
8 buildError,
9 choices,
10 environmentLabel,
11 environmentUrl,
12 groupBuilds,
13 hasPayload,
14 isFiltered,
15 isNewestStatus,
16 isPageBuild,
17 orderEnvironments,
18 pageRange,
19 parseFilter,
20 productionEnvironment,
21 nativeProduction,
22 shortSha,
23 withFilter,
24} from "./deployments.ts";
25
26const GIT = "the commit could not be checked out: git -c failed: fatal: reference is not a tree: d2ca224ba0fea430dcc9933cda14d8aa9fa94b4b";
27
28type Build = Parameters<typeof groupBuilds>[0][number] & { id: string };
29
30let hour = 0;
31const build = (over: Partial<Build>): Build => ({
32 id: `dep_${hour}`,
33 kind: "preview",
34 branch: "v2",
35 number: 1,
36 status: "failed",
37 error: GIT,
38 createdAt: new Date(Date.parse("2026-10-07T12:00:00Z") - hour++ * 3_600_000).toISOString(),
39 ...over,
40});
41
42test("a commit that is gone is said plainly, naming the pull request", () => {
43 assert.equal(buildError({ kind: "preview", number: 1, error: GIT }), "This pull request's commit no longer exists. Push again, or close pull request #1.");
44 assert.match(buildError({ kind: "production", number: null, error: GIT })!, /default branch/);
45 assert.equal(buildError({ kind: "preview", number: 1, error: "npm run build exited 1." }), "npm run build exited 1.");
46 assert.equal(buildError({ kind: "preview", number: 1, error: null }), null);
47});
48
49test("a run of the same failure of one app is one row, counted, linking to the newest", () => {
50 hour = 0;
51 const builds = [build({}), build({}), build({}), build({ status: "ready", error: null }), build({})];
52 const groups = groupBuilds(builds);
53 assert.deepEqual(
54 groups.map((g) => [g.build.id, g.count]),
55 [
56 ["dep_0", 3],
57 ["dep_3", 1],
58 ["dep_4", 1],
59 ],
60 );
61 assert.equal(groups[0]!.firstAt, builds[2]!.createdAt);
62});
63
64test("other apps' builds in between do not break a run; a different error does", () => {
65 hour = 0;
66 const groups = groupBuilds([
67 build({}),
68 build({ kind: "production", branch: null, number: null, status: "ready", error: null }),
69 build({}),
70 build({ branch: "add-ci", number: 2, error: "fatal: reference is not a tree: 213e9095" }),
71 build({}),
72 build({ error: "npm run build exited 1." }),
73 build({ error: "npm run build exited 1." }),
74 ]);
75 assert.deepEqual(
76 groups.map((g) => [g.build.id, g.count]),
77 [
78 ["dep_0", 3],
79 ["dep_1", 1],
80 ["dep_3", 1],
81 ["dep_5", 2],
82 ],
83 );
84});
85
86test("builds that did not fail are never folded", () => {
87 hour = 0;
88 const ready = groupBuilds([build({ status: "ready", error: null }), build({ status: "ready", error: null })]);
89 assert.deepEqual(
90 ready.map((g) => g.count),
91 [1, 1],
92 );
93 assert.deepEqual(groupBuilds([]), []);
94});
95
96// --- A repository's deployments ------------------------------------------------
97
98type Env = Parameters<typeof productionEnvironment>[0][number];
99const env = (name: string, over: Partial<Env> = {}): Env => ({
100 name,
101 production_environment: false,
102 transient_environment: false,
103 updated_at: "2026-10-07T12:00:00Z",
104 latest: null,
105 ...over,
106});
107const deployed = { id: "dep_1" } as unknown as Env["latest"];
108
109test("environments list production first, then lasting ones, then previews, newest first in each", () => {
110 const ordered = orderEnvironments([
111 env("preview", { transient_environment: true, updated_at: "2026-10-07T11:00:00Z" }),
112 env("staging", { updated_at: "2026-10-01T00:00:00Z" }),
113 env("qa", { updated_at: "2026-10-06T00:00:00Z" }),
114 env("production-eu", { production_environment: true, updated_at: "2026-10-07T11:59:00Z" }),
115 env("production", { production_environment: true, updated_at: "2026-10-01T00:00:00Z" }),
116 ]);
117 assert.deepEqual(
118 ordered.map((e) => e.name),
119 ["production", "production-eu", "qa", "staging", "preview"],
120 );
121});
122
123test("production is the production environment that has had a deployment, named production first", () => {
124 assert.equal(productionEnvironment([env("staging", { latest: deployed })]), null);
125 assert.equal(productionEnvironment([env("production", { production_environment: true })]), null);
126 assert.equal(
127 productionEnvironment([
128 env("live", { production_environment: true, latest: deployed }),
129 env("production", { production_environment: true, latest: deployed }),
130 ])?.name,
131 "production",
132 );
133 assert.equal(
134 productionEnvironment([env("production", { production_environment: true }), env("live", { production_environment: true, latest: deployed })])?.name,
135 "live",
136 );
137});
138
139test("an environment is served at its own address, else its current deployment's", () => {
140 const at = (environment_url: string | null, state = "success") => ({ environment_url, state }) as never;
141 assert.equal(environmentUrl({ url: "https://g1t.sh", current: null, latest: null }), "https://g1t.sh");
142 assert.equal(environmentUrl({ url: null, current: at("https://a.g1t.page"), latest: at("https://b.g1t.page", "failure") }), "https://a.g1t.page");
143 assert.equal(environmentUrl({ url: null, current: null, latest: at("https://b.g1t.page", "failure") }), null);
144});
145
146test("the list's filter is read from the address, ignoring what it cannot be", () => {
147 const filter = parseFilter(new URLSearchParams("environment=production&state=failure&source=actions&creator=syntaqx&ref=main&page=3"));
148 assert.deepEqual(filter, {
149 environment: "production",
150 state: "failure",
151 source: "actions",
152 creator: "syntaqx",
153 ref: "main",
154 page: 3,
155 per_page: PER_PAGE,
156 });
157 const junk = parseFilter(new URLSearchParams("state=exploded&source=ftp&page=-2&per_page=1000&environment=%20"));
158 assert.equal(junk.state, null);
159 assert.equal(junk.source, null);
160 assert.equal(junk.environment, null);
161 assert.equal(junk.page, 1);
162 assert.equal(junk.per_page, 100);
163 assert.equal(isFiltered(junk), false);
164 assert.equal(isFiltered(filter), true);
165});
166
167test("changing a filter keeps the others and starts again from the first page", () => {
168 const filter = parseFilter(new URLSearchParams("environment=production&state=failure&page=2"));
169 assert.equal(withFilter("/a/b/deployments", filter, "state", "success"), "/a/b/deployments?environment=production&state=success#history");
170 assert.equal(withFilter("/a/b/deployments", filter, "environment", null), "/a/b/deployments?state=failure#history");
171 assert.equal(withFilter("/a/b/deployments", filter, "page", 3), "/a/b/deployments?environment=production&state=failure&page=3#history");
172 assert.equal(withFilter("/a/b/deployments", parseFilter(new URLSearchParams()), "page", 1), "/a/b/deployments#history");
173});
174
175test("a filter's choices are each value once, sorted, keeping the chosen one", () => {
176 const list = [{ creator: "g1t", ref: "main" }, { creator: "syntaqx", ref: "main" }, null, { creator: "g1t", ref: "v2" }];
177 assert.deepEqual(choices(list, "creator"), ["g1t", "syntaqx"]);
178 assert.deepEqual(choices(list, "ref", "release"), ["main", "release", "v2"]);
179});
180
181test("words for states, sources, environments and pages", () => {
182 assert.equal(STATE_WORD.in_progress, "Deploying");
183 assert.equal(SOURCE_LABEL.g1t_page, "g1t.page");
184 assert.equal(environmentLabel("production"), "Production");
185 assert.equal(shortSha("d2ca224ba0fea430"), "d2ca224");
186 assert.equal(isPageBuild("dpl_123"), true);
187 assert.equal(isPageBuild("dep_123"), false);
188 assert.equal(pageRange(2, 30, 304), "31–60 of 304");
189 assert.equal(pageRange(11, 30, 304), "301–304 of 304");
190 assert.equal(pageRange(1, 30, 0), "0 of 0");
191 assert.equal(hasPayload({}), false);
192 assert.equal(hasPayload({ region: "wnam" }), true);
193 assert.equal(hasPayload(null), false);
194});
195
196test("only a deployment's newest status can still be under way", () => {
197 const statuses = [
198 { created_at: "2026-10-08T10:00:00.000Z" }, // Deploying, building
199 { created_at: "2026-10-08T10:02:00.000Z" }, // Deployed
200 ];
201 assert.equal(isNewestStatus(statuses, 0), false);
202 assert.equal(isNewestStatus(statuses, 1), true);
203 // Listed out of order: the newest is still the latest written.
204 assert.equal(isNewestStatus([...statuses].reverse(), 0), true);
205 // Written in the same moment: the last listed is the newest.
206 const tied = [{ created_at: "2026-10-08T10:00:00.000Z" }, { created_at: "2026-10-08T10:00:00.000Z" }];
207 assert.equal(isNewestStatus(tied, 0), false);
208 assert.equal(isNewestStatus(tied, 1), true);
209 assert.equal(isNewestStatus([], 0), false);
210});
211
212test("native screenshots use the serving app, not a newer attempt or custom domain", () => {
213 const current = { source: "g1t_page", state: "success", environment_url: "https://app-acme.g1t.page", sha: "abcdef1", updated_at: "2026-10-15T01:00:00Z" };
214 const production = { ...env("production", { production_environment: true, latest: deployed }), current, url: "https://custom.example" };
215 assert.deepEqual(nativeProduction([production as never]), { url: current.environment_url, commit: current.sha, deployedAt: current.updated_at });
216 assert.equal(nativeProduction([{ ...production, current: null } as never]), null);
217 assert.equal(nativeProduction([{ ...production, current: { ...current, state: "inactive" } } as never]), null);
218 assert.equal(nativeProduction([{ ...production, current: { ...current, source: "actions" } } as never]), null);
219});