Fixes merge-queue submissions where merge-pr.sh reported a PR as submitted but GitHub never created a queue entry, leaving PRs in limbo with no merge_group runs. After submitting, the script now polls GitHub until the PR is confirmed in the queue, and refuses (with auto-merge disarmed) if it never appears.
Waits (bounded) for GitHub to compute mergeability before submitting, refusing instead of submitting while it stays UNKNOWN.
Polls one GraphQL read for up to 60s until the PR is in the queue or merged; while required checks are pending, an armed auto-merge also counts as confirmation, with the pending state re-read at confirmation time.
Admission gates re-run before every submission, so review threads or findings arriving during a wait cannot ride an earlier gate result.
Resubmits once when the entry is missing and mergeability is UNKNOWN; otherwise, or if the resubmission also fails to appear, disarms auto-merge and refuses, quoting the reported state and the gh enqueue responses.
land-pr.sh inherits the refusal immediately instead of waiting out its 4h timeout.
Timeouts and poll rates are configurable via AFT_MERGE_PR_MERGEABLE_* and AFT_MERGE_PR_QUEUE_CONFIRM_*.
The fake gh in test_pr_landing.py now rejects unknown PullRequest fields with GitHub's error text and gains ghost-enqueue, enqueue-on-merge, and UNKNOWN-mergeable modes.
Confidence Score: 5/5
The latest changes appear safe to merge; no new actionable issues were found.
Summary
merge-pr.sh now checks that GitHub accepted a queue submission and disarms auto-merge if confirmation fails.
Queue submissions wait until GitHub computes whether a PR can merge.
Merge requests wait for GitHub to confirm the PR's queue state.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Read admission gates] --> B{Mergeability known?}
B -- No --> C[Wait and refresh gates]
C --> B
B -- Yes --> D[Submit]
D --> E{Queued or merged?}
E -- Yes --> F[Success]
E -- No --> G{Armed with fresh pending checks?}
G -- Yes --> F
G -- No --> H[Poll until timeout]
H --> I{Mergeability unknown and no retry yet?}
I -- Yes --> J[Disarm and repeat admission]
J --> A
I -- No --> K[Disarm and refuse]