Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Merge branch 'mirroring' into artifacts-mode | 1 | import assert from "node:assert/strict"; |
| 2 | import { test } from "node:test"; | |
| 3 | ||
| 4 | import type { HandbackPlan, RepoMirror } from "@g1t/contracts"; | |
| 5 | ||
| A desktop release goes out with what can be built. Linux is built on g1t's machines in every release; Windows and macOS each wait on a repository variable: a machine registered for them, or for Windows a cross build on Linux once aka.ms and download.visualstudio.microsoft.com are workflow-only domains, which is where the first release stopped. A platform with no machine is skipped and the download page says it is coming, with a word for the visitor whose platform this release lacks. The guide and CONTRIBUTING say so. | 6 | import { |
| 7 | DEFAULT_MIRROR_SETTINGS, | |
| 8 | type RepoArea, | |
| 9 | TAKE_OVER_AFTER_MINUTES, | |
| 10 | mirrorOffers, | |
| 11 | mirrorUpdatesWait, | |
| 12 | mirrorWritable, | |
| 13 | } from "../../../../packages/contracts/src/mirrors.ts"; | |
| Merge branch 'mirroring' into artifacts-mode | 14 | |
| 15 | import { | |
| 16 | clampMinutes, | |
| 17 | decisionsFrom, | |
| 18 | handBackReady, | |
| 19 | mirrorBadge, | |
| 20 | mirrorBanner, | |
| 21 | mirrorReason, | |
| 22 | mirrorSettingsFrom, | |
| A desktop release goes out with what can be built. Linux is built on g1t's machines in every release; Windows and macOS each wait on a repository variable: a machine registered for them, or for Windows a cross build on Linux once aka.ms and download.visualstudio.microsoft.com are workflow-only domains, which is where the first release stopped. A platform with no machine is skipped and the download page says it is coming, with a word for the visitor whose platform this release lacks. The guide and CONTRIBUTING say so. | 23 | offers, |
| Merge branch 'mirroring' into artifacts-mode | 24 | shortSha, |
| 25 | TAKE_OVER_MINUTES, | |
| A desktop release goes out with what can be built. Linux is built on g1t's machines in every release; Windows and macOS each wait on a repository variable: a machine registered for them, or for Windows a cross build on Linux once aka.ms and download.visualstudio.microsoft.com are workflow-only domains, which is where the first release stopped. A platform with no machine is skipped and the download page says it is coming, with a word for the visitor whose platform this release lacks. The guide and CONTRIBUTING say so. | 26 | updatesWaitReason, |
| Merge branch 'mirroring' into artifacts-mode | 27 | workflowReason, |
| 28 | writable, | |
| 29 | } from "./mirror.ts"; | |
| 30 | ||
| 31 | const mirror = (state: RepoMirror["state"]): RepoMirror => ({ | |
| 32 | state, | |
| 33 | remote: "github.com/acme/web", | |
| 34 | url: "https://github.com/acme/web", | |
| 35 | since: "2026-10-08T10:00:00Z", | |
| 36 | }); | |
| 37 | const repo = (state: RepoMirror["state"] | null) => ({ namespace: "acme", name: "web", mirror: state ? mirror(state) : null }); | |
| 38 | const leader = (reachable: boolean) => ({ repoId: "r", role: "leader" as const, name: "github.com/acme/web", state: "standby" as const, reachable }); | |
| 39 | const follower = (name: string) => ({ repoId: "r", role: "follower" as const, name, state: "following" as const, reachable: true }); | |
| 40 | ||
| A desktop release goes out with what can be built. Linux is built on g1t's machines in every release; Windows and macOS each wait on a repository variable: a machine registered for them, or for Windows a cross build on Linux once aka.ms and download.visualstudio.microsoft.com are workflow-only domains, which is where the first release stopped. A platform with no machine is skipped and the download page says it is coming, with a word for the visitor whose platform this release lacks. The guide and CONTRIBUTING say so. | 41 | const AREAS: RepoArea[] = ["code", "issues", "pulls", "agents", "workflows", "deployments", "security", "insights", "settings", "updates"]; |
| 42 | ||
| Merge branch 'mirroring' into artifacts-mode | 43 | test("the copies agree with the contracts", () => { |
| 44 | for (const state of [null, "standby", "ci", "takeover", "handing_back"] as const) { | |
| A desktop release goes out with what can be built. Linux is built on g1t's machines in every release; Windows and macOS each wait on a repository variable: a machine registered for them, or for Windows a cross build on Linux once aka.ms and download.visualstudio.microsoft.com are workflow-only domains, which is where the first release stopped. A platform with no machine is skipped and the download page says it is coming, with a word for the visitor whose platform this release lacks. The guide and CONTRIBUTING say so. | 45 | const of = state ? mirror(state) : null; |
| 46 | assert.equal(writable(of), mirrorWritable(of)); | |
| 47 | for (const area of AREAS) { | |
| 48 | assert.equal(offers(of, area), mirrorOffers(of, area), `${state} ${area}`); | |
| 49 | if (of) assert.equal(offers({ ...of, warm: true }, area), mirrorOffers({ ...of, warm: true }, area), `${state} warm ${area}`); | |
| 50 | } | |
| 51 | if (state) assert.equal(updatesWaitReason(repo(state)), mirrorOffers(mirror(state), "updates") ? null : mirrorUpdatesWait("acme", "web", mirror(state))); | |
| Merge branch 'mirroring' into artifacts-mode | 52 | } |
| 53 | assert.deepEqual([...TAKE_OVER_MINUTES], [...TAKE_OVER_AFTER_MINUTES]); | |
| 54 | }); | |
| 55 | ||
| A desktop release goes out with what can be built. Linux is built on g1t's machines in every release; Windows and macOS each wait on a repository variable: a machine registered for them, or for Windows a cross build on Linux once aka.ms and download.visualstudio.microsoft.com are workflow-only domains, which is where the first release stopped. A platform with no machine is skipped and the download page says it is coming, with a word for the visitor whose platform this release lacks. The guide and CONTRIBUTING say so. | 56 | test("a mirror offers a read-only copy until it is taken over", () => { |
| 57 | for (const state of ["standby", "ci", "handing_back"] as const) { | |
| 58 | for (const area of ["code", "security", "insights", "settings"] as const) assert.ok(offers(mirror(state), area), `${state} ${area}`); | |
| 59 | for (const area of ["issues", "pulls", "agents", "deployments", "updates"] as const) assert.ok(!offers(mirror(state), area), `${state} ${area}`); | |
| 60 | } | |
| 61 | for (const area of AREAS) { | |
| 62 | assert.ok(offers(mirror("takeover"), area), area); | |
| 63 | assert.ok(offers(null, area), area); | |
| 64 | } | |
| 65 | assert.ok(!offers(mirror("standby"), "workflows")); | |
| 66 | assert.ok(offers({ ...mirror("standby"), warm: true }, "workflows"), "a standby kept warm runs .g1t/workflows"); | |
| 67 | assert.ok(offers(mirror("ci"), "workflows")); | |
| 68 | assert.ok(!offers({ ...mirror("handing_back"), warm: true }, "workflows")); | |
| 69 | assert.match(updatesWaitReason(repo("standby"))!, /^Security updates wait until acme\/web is taken over or moved to g1t\./); | |
| 70 | assert.equal(updatesWaitReason(repo("takeover")), null); | |
| 71 | assert.equal(updatesWaitReason(repo(null)), null); | |
| 72 | }); | |
| 73 | ||
| Merge branch 'mirroring' into artifacts-mode | 74 | test("a read-only mirror says why its buttons are off, and where to take over", () => { |
| 75 | assert.equal( | |
| 76 | mirrorReason(repo("standby")), | |
| 77 | "acme/web is a mirror of github.com/acme/web. Work happens there until someone takes over in Settings → Mirroring.", | |
| 78 | ); | |
| 79 | assert.equal(mirrorReason(repo("ci")), mirrorReason(repo("standby"))); | |
| 80 | assert.equal(mirrorReason(repo("handing_back")), "acme/web is handing back to github.com/acme/web; it takes changes again when that is done."); | |
| 81 | assert.equal(mirrorReason(repo("takeover")), null); | |
| 82 | assert.equal(mirrorReason(repo(null)), null); | |
| 83 | assert.equal(mirrorReason(null), null); | |
| 84 | }); | |
| 85 | ||
| 86 | test("workflows run in CI failover and takeovers, not while standing by or handing back", () => { | |
| 87 | assert.equal(workflowReason(repo("ci")), null); | |
| 88 | assert.equal(workflowReason(repo("takeover")), null); | |
| 89 | assert.ok(workflowReason(repo("standby"))); | |
| 90 | assert.ok(workflowReason(repo("handing_back"))); | |
| 91 | assert.equal(workflowReason(repo(null)), null); | |
| 92 | }); | |
| 93 | ||
| 94 | test("the badge says what the repository is to its remotes", () => { | |
| 95 | assert.deepEqual(mirrorBadge(mirror("standby"), []), { label: "Mirror of github.com/acme/web", tone: "neutral", more: 0 }); | |
| 96 | assert.equal(mirrorBadge(mirror("ci"), [])?.tone, "info"); | |
| 97 | assert.equal(mirrorBadge(mirror("takeover"), [])?.label, "Taken over from github.com/acme/web"); | |
| 98 | assert.equal(mirrorBadge(mirror("handing_back"), [])?.label, "Handing back to github.com/acme/web"); | |
| 99 | assert.deepEqual(mirrorBadge(null, [follower("github.com/acme/web"), follower("git.example.com/web")]), { | |
| 100 | label: "Mirrored to github.com/acme/web", | |
| 101 | tone: "accent", | |
| 102 | more: 1, | |
| 103 | }); | |
| 104 | assert.equal(mirrorBadge(null, []), null); | |
| 105 | }); | |
| 106 | ||
| 107 | test("a mirror standing by whose remote answers needs no banner", () => { | |
| 108 | assert.equal(mirrorBanner(mirror("standby"), [leader(true)]), null); | |
| 109 | assert.equal(mirrorBanner(mirror("standby"), []), null); | |
| 110 | assert.equal(mirrorBanner(mirror("standby"), [leader(false)]), "unreachable"); | |
| 111 | assert.equal(mirrorBanner(mirror("ci"), [leader(false)]), "unreachable"); | |
| 112 | assert.equal(mirrorBanner(mirror("ci"), [leader(true)]), "ci"); | |
| 113 | assert.equal(mirrorBanner(mirror("takeover"), [leader(false)]), "takeover"); | |
| 114 | assert.equal(mirrorBanner(mirror("handing_back"), []), "handing_back"); | |
| 115 | assert.equal(mirrorBanner(null, [follower("x")]), null); | |
| 116 | }); | |
| 117 | ||
| 118 | test("hand-back decisions are read from their fields, and only known ones", () => { | |
| 119 | const form = new FormData(); | |
| 120 | form.set("intent", "hand-back"); | |
| 121 | form.set("decision:main", "keep_ours"); | |
| 122 | form.set("decision:release/1.x", "pull_request"); | |
| 123 | form.set("decision:dev", "delete_everything"); | |
| 124 | assert.deepEqual(decisionsFrom(form.entries()), { main: "keep_ours", "release/1.x": "pull_request" }); | |
| 125 | }); | |
| 126 | ||
| 127 | test("a hand-back is ready once the remote answers and every diverged branch has a decision", () => { | |
| 128 | const plan: HandbackPlan = { | |
| 129 | reachable: true, | |
| 130 | ready: false, | |
| 131 | refs: [ | |
| 132 | { ref: "main", base: "a", ours: "b", theirs: "c", action: "diverged", decision: null }, | |
| 133 | { ref: "dev", base: "a", ours: "b", theirs: "a", action: "push", decision: null }, | |
| 134 | ], | |
| 135 | }; | |
| 136 | assert.equal(handBackReady(plan, {}), false); | |
| 137 | assert.equal(handBackReady(plan, { main: "keep_theirs" }), true); | |
| 138 | assert.equal(handBackReady({ ...plan, reachable: false }, { main: "keep_theirs" }), false); | |
| 139 | }); | |
| 140 | ||
| 141 | test("settings come back from the form, keeping what it did not carry", () => { | |
| 142 | const leaderForm = new FormData(); | |
| 143 | leaderForm.set("kind", "leader"); | |
| 144 | leaderForm.set("notify", "inbox"); | |
| 145 | leaderForm.set("autoTakeOver", "on"); | |
| 146 | leaderForm.set("takeOverAfter", "2"); | |
| 147 | leaderForm.set("githubWorkflows", "on"); | |
| 148 | const current = { ...DEFAULT_MIRROR_SETTINGS, remotePushes: "overwrite" as const }; | |
| 149 | assert.deepEqual(mirrorSettingsFrom(leaderForm, current), { | |
| 150 | notify: "inbox", | |
| 151 | takeOverAfter: 5, | |
| 152 | handBack: "ask", | |
| 153 | keepCiWarm: false, | |
| 154 | githubWorkflows: true, | |
| 155 | holdDeploys: false, | |
| Merge branch 'claude/cool-newton-7nm8r9' (#36): real GitHub Actions on g1t, managed deploy workflows, g1t/deploy and the Sysbox runner 0.2.0. The merge keeps both sides' webhook events and API operations, says agent images need tar, guards the job engine's stop to Unix so the runner builds on Windows again, and keeps the moves tests' previews from going idle as the calendar passes their fixture's date. | 156 | reportChecks: true, |
| Merge branch 'mirroring' into artifacts-mode | 157 | remotePushes: "overwrite", |
| 158 | }); | |
| Merge branch 'claude/cool-newton-7nm8r9' (#36): real GitHub Actions on g1t, managed deploy workflows, g1t/deploy and the Sysbox runner 0.2.0. The merge keeps both sides' webhook events and API operations, says agent images need tar, guards the job engine's stop to Unix so the runner builds on Windows again, and keeps the moves tests' previews from going idle as the calendar passes their fixture's date. | 159 | const githubForm = new FormData(); |
| 160 | githubForm.set("kind", "leader"); | |
| 161 | githubForm.set("provider", "github"); | |
| 162 | assert.equal(mirrorSettingsFrom(githubForm, DEFAULT_MIRROR_SETTINGS).reportChecks, false, "a GitHub mirror's box left clear turns it off"); | |
| 163 | githubForm.set("reportChecks", "on"); | |
| 164 | assert.equal(mirrorSettingsFrom(githubForm, { ...DEFAULT_MIRROR_SETTINGS, reportChecks: false }).reportChecks, true); | |
| Merge branch 'mirroring' into artifacts-mode | 165 | const followerForm = new FormData(); |
| 166 | followerForm.set("kind", "follower"); | |
| 167 | followerForm.set("remotePushes", "overwrite"); | |
| 168 | assert.deepEqual(mirrorSettingsFrom(followerForm, DEFAULT_MIRROR_SETTINGS), { ...DEFAULT_MIRROR_SETTINGS, remotePushes: "overwrite" }); | |
| 169 | }); | |
| 170 | ||
| 171 | test("minutes and commits are shown within bounds", () => { | |
| 172 | assert.equal(clampMinutes(3), 5); | |
| 173 | assert.equal(clampMinutes(90.4), 90); | |
| 174 | assert.equal(clampMinutes(99999), 1440); | |
| 175 | assert.equal(clampMinutes(Number.NaN), 5); | |
| 176 | assert.equal(shortSha("0123456789abcdef"), "0123456"); | |
| 177 | assert.equal(shortSha(null), "—"); | |
| 178 | }); |
This file's history is long; its oldest lines are credited to the oldest commit read.