Public: anyone can read this; the crew can change it.
"apps: production, previews, data, gates > require_checks holds the merge until the head's deploy is green" passes every time on a loaded check machine #5254
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/5204-apps-production-previews-data-gates-requ → main 2 commits fork 1 thread · 1 unresolved
1 file
changed +43
−13
test/apps.test.ts +43 −13
| @@ -407,19 +407,49 @@ describe("apps: production, previews, data, gates", () => { | ||
| 407 | 407 | expect(status?.state).toBe("running"); |
| 408 | 408 | expect(status?.error).toContain("tests failed"); |
| 409 | 409 | |
| 410 | const fixed = await commitToBranch(app, alice, repo, { | |
| 411 | branch: "broken", | |
| 412 | message: "Fix the test", | |
| 413 | files: [ | |
| 414 | { | |
| 415 | path: "src/server.test.ts", | |
| 416 | content: | |
| 417 | 'import { expect, test } from "bun:test";\ntest("passes", () => { expect(1).toBe(1); });\n', | |
| 418 | }, | |
| 419 | ], | |
| 420 | }); | |
| 421 | expect(fixed.ok).toBe(true); | |
| 422 | if (!fixed.ok) return; | |
| 410 | // Hold every deploy permit, so the fixed head's deploy cannot finish | |
| 411 | // between this push and the merge attempt: the hold is asserted while the | |
| 412 | // deploy is provably unfinished, then the deploy is let go. | |
| 413 | const permits = await Promise.all( | |
| 414 | Array.from({ length: runtime.lane.limit }, () => runtime.lane.acquire()), | |
| 415 | ); | |
| 416 | const release = () => permits.forEach((r) => r()); | |
| 417 | let fixed: Awaited<ReturnType<typeof commitToBranch>>; | |
| 418 | try { | |
| 419 | fixed = await commitToBranch(app, alice, repo, { | |
| 420 | branch: "broken", | |
| 421 | message: "Fix the test", | |
| 422 | files: [ | |
| 423 | { | |
| 424 | path: "src/server.test.ts", | |
| 425 | content: | |
| 426 | 'import { expect, test } from "bun:test";\ntest("passes", () => { expect(1).toBe(1); });\n', | |
| 427 | }, | |
| 428 | ], | |
| 429 | }); | |
| 430 | expect(fixed.ok).toBe(true); | |
| 431 | if (!fixed.ok) return; | |
| 432 | const fixedOid = fixed.value.commitOid; | |
| 433 | const queuedFor = () => | |
| 434 | listRuns(app.db, repo.id, { kind: "deploy", limit: 50 }).find( | |
| 435 | (r) => | |
| 436 | r.env === `pull-${opened.value.number}` && | |
| 437 | r.commitOid === fixedOid, | |
| 438 | ); | |
| 439 | while (queuedFor() === undefined) await Bun.sleep(20); | |
| 440 | expect(queuedFor()?.state).not.toBe("ok"); | |
| 441 | const held = await mergePull( | |
| 442 | app, | |
| 443 | alice, | |
| 444 | repo, | |
| 445 | getPull(app.db, repo.id, opened.value.number)!, | |
| 446 | "merge", | |
| 447 | ); | |
| 448 | expect(held.ok).toBe(false); | |
| 449 | if (!held.ok) expect(held.error).toBe("checks_required"); | |
| 450 | } finally { | |
| 451 | release(); | |
| 452 | } | |
| 423 | 453 | const green = await settled( |
| 424 | 454 | (r) => |
| 425 | 455 | r.env === `pull-${opened.value.number}` && |
new above
offline
This loop has no deadline. If the deploy run is never queued, the test hangs until the global timeout with no message. Bound it (e.g. 5s) and fail with a clear message.