Public: anyone can read this; the crew can change it.
Sentinel: shared:01m23vygyffx5hg2f5vm8r74sr:2tcvuk57nu was degraded 45 minutes today: trevato/forge: "the merge queue > a gate that never answers is abandoned at the deadline, and the next sweep lands (#34… #5357
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/5334-sentinel-shared-01m23vygyffx5hg2f5vm8r74 → main 1 commit fork
1 file
changed +7
−3
test/merge-queue.test.ts +7 −3
| @@ -50,6 +50,8 @@ describe("the merge queue", () => { | ||
| 50 | 50 | let flaky = 0; |
| 51 | 51 | /** The signal the last gate was handed: the queue aborts it at the deadline. */ |
| 52 | 52 | let lastSignal: AbortSignal | undefined; |
| 53 | /** Called as a gate starts, before the deadline can fire on a loaded machine. */ | |
| 54 | let atGate: (() => void) | undefined; | |
| 53 | 55 | |
| 54 | 56 | const git = (repo: Repo, ...args: string[]) => |
| 55 | 57 | Bun.spawnSync(["git", ...args], { |
| @@ -74,6 +76,7 @@ describe("the merge queue", () => { | ||
| 74 | 76 | provideChecksForTest(app, { |
| 75 | 77 | gate: async (repo: Repo, _pull: Pull, commitOid: string, signal?: AbortSignal) => { |
| 76 | 78 | lastSignal = signal; |
| 79 | atGate?.(); | |
| 77 | 80 | if (held !== undefined) await held; |
| 78 | 81 | if (cutOff > 0) { |
| 79 | 82 | cutOff--; |
| @@ -461,18 +464,19 @@ describe("the merge queue", () => { | ||
| 461 | 464 | const warn = console.warn; |
| 462 | 465 | console.warn = (line: string) => warned.push(line); |
| 463 | 466 | held = new Promise<void>(() => {}); |
| 467 | let words = ""; | |
| 464 | 468 | try { |
| 465 | 469 | lastSignal = undefined; |
| 470 | atGate = () => (words = queueWords(repo.id)); | |
| 466 | 471 | const sweep = sweepGreen(app, repo); |
| 467 | // Building the candidate is git work first: wait for the gate itself. | |
| 468 | for (let i = 0; i < 6000 && lastSignal === undefined; i++) await Bun.sleep(5); | |
| 469 | expect(queueWords(repo.id)).toMatch(/^gating 1 pull since \d\d:\d\d$/); | |
| 470 | 472 | expect(await sweep).toBe(0); |
| 471 | 473 | } finally { |
| 472 | 474 | held = undefined; |
| 475 | atGate = undefined; | |
| 473 | 476 | console.warn = warn; |
| 474 | 477 | restore(); |
| 475 | 478 | } |
| 479 | expect(words).toMatch(/^gating 1 pull since \d\d:\d\d$/); | |
| 476 | 480 | expect((lastSignal as AbortSignal | undefined)?.aborted).toBe(true); |
| 477 | 481 | expect(warned.some((l) => l.includes("[queue] candidate abandoned") && l.includes(`#${pull.number}`))).toBe(true); |
| 478 | 482 | expect(queueWords(repo.id)).toBe("idle"); |
new above
offline