Skip to content

Merge queue didnt close PR eventhough code was merged #15

Description

@jeduden

Merge queue didnt close jeduden/mdsmith#154

Merge commit 1d6e852 ("Merge PR #154") committed at 08:53:02Z — that's what landed on main via the batch.
PR head 8540c5a committed at 08:53:54Z — a new commit was pushed to the PR branch 52 seconds after the batch snapshot was taken, while the batch's CI was still running.
So the sequence was:

08:53:01Z queue picks up PR #154. Snapshots head SHA 150c2a4.
08:53:02Z repos.merges API creates merge commit 1d6e852 on the batch branch (parent contains 150c2a4).
08:53:54Z a new commit (8540c5a) is pushed to claude/plan-50-..., moving PR #154's head forward. The batch is oblivious.
08:55:52Z action fast-forwards main to the batch head. 150c2a4 is now on main, but the PR's current head 8540c5a is not.
GitHub's "auto-close when PR head is reachable from base" heuristic fires on the PR head at fast-forward time — 8540c5a, not 150c2a4 — and finds it unreachable. PR stays open.
For #158 nobody pushed during the batch, so its head was still reachable → auto-closed fine.
The action's commentMerged posted on both PRs anyway because it only checks its own result.merged list — it never verifies that GitHub actually closed the PR.

Root cause in jeduden/merge-queue-action
src/gitops.ts#fastForwardMain + the post-FF loop in src/action.ts rely entirely on GitHub's auto-close. There's no protection against the PR head moving between snapshot and fast-forward. Any push to a queued branch during batch CI (very likely here — an agent was still pushing fixup commits for Copilot's reviews on this PR) loses auto-close.

Recommended fix
Two changes in jeduden/merge-queue-action:

Detect head drift before fast-forward (src/action.ts, just before fastForwardMain): for each PR in the batch, re-fetch pulls.get and compare head.sha to the snapshot used for mergeBranch. If any drifted, skip the fast-forward and re-batch — the CI result is no longer valid for the new head anyway.
Belt-and-suspenders in the post-FF loop: after fast-forward, for each merged PR, call pulls.get and if state === "open" after a brief retry, explicitly close it via pulls.update({ state: "closed" }) and leave a comment linking to the merge SHA. This catches the current case where the drift wasn't detected.

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions