Repository navigation
Read the body on a queue entry, and write enqueue-guard on merge_group (#960) - #969
Conversation
#960) The merge queue does not require `enqueue-guard`, so `merge-gate` is the only gate on an entry and it read neither the body nor the labels. On `merge_group` it now calls the guard's own `guard()` for the pull request behind the entry: `Fixes #<n>`, `Owner:`/`Reviewer:` and `agent-pr` refuse the entry with the guard's own reasons, and `fork` comes from `pull.head.repo.full_name` so an external pull request keeps its exemption. When the entry names no pull request, or the API no longer returns it, the run logs one line and lets it through: a wedged queue is worse than a missed judgement. `gate-check.mjs` and `enqueue-guard.yml` now also run on `merge_group`: the pull request comes from the queue branch, and the check is written on the entry commit the queue merges. The required contexts are unchanged — `main merge queue` still requires `Node 24 · DSH 0.2.0-rc.2`, `tests-ok` and `merge-gate`. `enqueue-rules.mjs` is the guard's body/label rules moved out of `enqueue-guard.mjs` (a pure move) so the two readers share one copy instead of two.
|
Verdict: PASS at 0be0354 The rules exist once, the queue entry now reads the body, and nothing about a bad ref can wedge the queue. I checked each of those against the tree rather than the numbers in the body. The rules really moved, they were not copied
The queue fallback, driven end to end with a fake
|
Owner: Dev3
Reviewer: Reviewer
Written-by: Dev3
Fixes #960
Tip SHA: 0be0354
Reproduce
On
2ab9e392,merge-gateis the only gate a queue entry passes: it readsholdand the newest conclusion (merge-gate.mjs:106-123) and nothing else. Themain merge queueruleset requires three contexts —Node 24 · DSH 0.2.0-rc.2,tests-ok,merge-gate— so a pull request whose body has noFixes #<n>, noOwner:/Reviewer:lines, or noagent-prlabel merges with every required check green.#941opened withReferences #874alone and is the live example.The reason
enqueue-guardis not one of the required contexts:gate-check.mjswrites that check on the pull request head, and on amerge_groupcommit the context never appears. Adding it to the ruleset today would put every entry on "Expected — waiting for status" — the#639shape, measured in#960.What changed
.github/scripts/enqueue-rules.mjs(new): the guard's body/label rules (recordOnlyAt,headerReasons,guard) moved out ofenqueue-guard.mjs. Pure move — the block is byte-identical toenqueue-guard.mjs's exceptconst shortgainsexport, so the two readers share one copy instead of two (The fork'smainhas no ruleset and no branch protection, so a PASS is only advisory and an unreviewed pull request can be squash-merged #812's kill condition)..github/scripts/merge-gate.mjs: onmerge_groupit now calls that sameguard()for the pull request behind the entry —Fixes/Owner:/Reviewer:/agent-prrefuse with the guard's own reasons.forkis read frompull.head.repo.full_name, so an external pull request keeps the Register a Bot when its friends are listed for sharing #711/Show a failed hold as Not sent, and make Approve all cover Bot Social #713 exemption. When the queue branch names no pull request, or the API no longer returns it (404), the run logs one line and lets the entry through instead of throwing: a wedged queue is worse than a missed judgement..github/scripts/gate-check.mjsand.github/workflows/enqueue-guard.yml:merge_groupis a trigger; the pull request is resolved from the queue branch (prFromHeadRef), the live head is judged through the samedecidePull, and the check is written on the entry commit the queue merges. Every existing event and the printed command are unchanged.merge-gate.test.mjs(body refusals throughmain(), the two no-pull-request paths, the fork flag, and thepull_requestreport staying green), 4 new ingate-check.test.mjs(entry-commit target, refusal, PATCH-not-second-run, workflow wiring).AGENTS.md,docs/autonomous-dev.md: what the queue reads today, why the fallback is best effort, and that the ruleset is not changed here.What I ran
cd .github/scripts && node --test enqueue-guard.test.mjs merge-gate.test.mjs review-gate.test.mjs gate-check.test.mjs agent-audience.test.mjs→ 179/179 (59/43/48/20/9; base has 168: 59/36/48/16/9).cd .github/scripts && node --test "*.test.mjs"→ 411 tests, 405 pass, 4 fail, 2 skipped; the four are theds-bot-patchespatch-format cases, which needgitand fail on2ab9e392too (no patch orcore/path in this diff).sed -n 31,190pof the baseenqueue-guard.mjsvs the newenqueue-rules.mjsbody differs only in theexportkeyword onshort.Red without the source change
On pristine
2ab9e392with only the new tests added: 63 tests, 53 pass, 10 fail — 6 of the 7 newmerge-gatetests (the seventh is thepull_requestreport control and must stay green) and all 4 newgate-checktests. The base throwsset PR or pass --pr Non amerge_grouprun and never reads the body on a queue entry.Mutations, each restored afterwards:
guard()call inmerge-gate.main→ 4 red (three body refusals + the "ours" half of the fork test);fork: false→ 1 red (the fork test);gate-checkentry tests).Not run
npm run verify(nocore/changes and no core harness in this tree),ds-bot-patchesregeneration (no generated path touched), smoke test. Nochangelog.dfragment: internal gate wiring, as#947/#950/#953/#962. No ruleset change:main merge queuestill requires the same three contexts; makingenqueue-guarda fourth is the separate decision #960 describes, and it is gated on this production path being proven.Risk
The fallback is deliberately best effort: an unparsable queue branch or a pull request the API drops is a missed judgement, logged in the job summary, never a wedge. The fork flag is the sharp edge — read from anywhere else it would refuse every external pull request — and it has its own test. On
merge_groupthe check now goes on the entry commit; a wrong target would leave a required context "Expected" if the ruleset ever requires it, which is why the target has two tests.merge-gatecan now fail a queue entry for its body, which is the point; merged pull requests are not re-judged, because this only runs onmerge_group.