Skip to content

fix(pr-merge): refuse to merge a PR whose forge checks are red or unreadable - #2423

Open
Nikita-Guzenko wants to merge 1 commit into
kunchenguid:mainfrom
Nikita-Guzenko:fm/fm-merge-gate
Open

fix(pr-merge): refuse to merge a PR whose forge checks are red or unreadable#2423
Nikita-Guzenko wants to merge 1 commit into
kunchenguid:mainfrom
Nikita-Guzenko:fm/fm-merge-gate

Conversation

@Nikita-Guzenko

Copy link
Copy Markdown

Intent

Make bin/fm-pr-merge.sh refuse to merge a pull request whose forge reports a failing or unreadable check verdict, so "never merge a red PR" is enforced by the one merge path instead of by session attention.

Why

On 2026-08-10 the merge-queue run for a production repo's pull request failed at 17:54 UTC and the pull request was merged at 17:59 UTC by the same account; the defect in that commit then blocked every production deploy until 2026-08-12. The merge path never read the forge's check state, so the "never merge a red PR" rule lived only in AGENTS.md and depended on attention rather than enforcement.

What changed

The merge path now reads the verdict itself through the new bin/fm-pr-checks-lib.sh and refuses before recording any state:

  • failing — at least one check the forge reports as failed
  • unreadable — the state could not be established; never treated as a pass

Two sources are read, because either can be red on its own:

  1. the pull request head's status check rollup, and
  2. the newest merge-queue attempt, whose checks run again on a combined commit published as gh-readonly-queue/<base>/pr-<n>-<sha>.

Only the newest queue attempt is judged, so a superseded red attempt cannot block a re-queued green one. gh pr checks is deliberately unused: it exits non-zero both when a check failed and when one is still running, so its exit status cannot classify a result.

--allow-failing-checks is the single deliberate override, and it announces itself; AGENTS.md records that using it is a red merge and needs the same explicit captain instruction any red merge needs.

Testing

  • tests/fm-pr-merge.test.sh — all cases pass, including the new red-branch, red-merge-queue-with-green-branch, superseded-attempt, unreadable, wrong-payload, override, and unknown-flag cases; both guards were mutation-checked.
  • tests/fm-pr-check-security.test.sh — passes.
  • bin/fm-lint.sh (pinned ShellCheck 0.11.0) — clean.
  • bin/fm-test-run.sh --check-coverage — partition intact.

Supersedes

This PR replaces #2299, which was built from a base ~125 commits behind current main. This branch is the same change (commit 49d3ab1) cherry-picked cleanly onto current upstream main with no conflicts. #2299 will be closed with a cross-link to this PR.

…eadable

bin/fm-pr-merge.sh called gh-axi pr merge without ever reading the forge's
check state, so "never merge a red PR" lived only in AGENTS.md and depended on
session attention. On 2026-08-10 that gap shipped a broken commit: the
merge-queue run for nguzen/aln pull request 182 failed at 17:54 UTC, the pull
request was merged at 17:59 UTC, and the defect in it blocked every production
deploy until 2026-08-12.

The merge path now reads the verdict itself through the new
bin/fm-pr-checks-lib.sh and refuses before recording any state:

  * failing    at least one check the forge reports as failed
  * unreadable the state could not be established - never treated as a pass

Two sources are read, because either can be red alone: the pull request head's
status check rollup, and the newest merge-queue attempt, whose checks run again
on a combined commit published as gh-readonly-queue/<base>/pr-<n>-<sha>. Only
the newest queue attempt is judged, so a superseded red attempt cannot block a
re-queued green one. `gh pr checks` is deliberately unused: it exits non-zero
both when a check failed and when one is still running, so its exit status
cannot classify a result.

--allow-failing-checks is the single deliberate override, and it announces
itself; AGENTS.md records that using it is a red merge and needs the same
explicit captain instruction any red merge needs.

Verified against the live incident: the library classifies nguzen/aln#182 as
failing (branch and merge-queue) and kunchenguid#183 as green.

Tests: tests/fm-pr-merge.test.sh gains the red-branch, red-merge-queue-with-
green-branch, superseded-attempt, unreadable, wrong-payload, override and
unknown-flag cases; both guards were mutation-checked (blinding the queue read
fails only the queue case, accepting an unreadable verdict fails only the
unreadable case).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant