[bug] BEHIND and UNSTABLE merge states are treated as ready
Summary
DeployBot treats MergeStateStatus.BEHIND and MergeStateStatus.UNSTABLE as ready as long as mergeable == MERGEABLE. GitHub's schema defines BEHIND as an out-of-date head ref and UNSTABLE as mergeable with non-passing commit status.
Those states are not equivalent to CLEAN or HAS_HOOKS, and DeployBot should not place such pull requests into the ready-to-merge path.
Evidence
Impact
DeployBot can report a PR as ready even when GitHub has already computed that the branch is stale or that commit status is non-passing. This creates queue churn and confusing merge failures, and it can hide the real blocker from the user-facing queue state.
The safer interpretation is:
CLEAN: ready if DeployBot's other policy checks pass.
HAS_HOOKS: ready if DeployBot's other policy checks pass, while recognizing GitHub-side hooks may still reject.
BEHIND: waiting or blocked with an explicit "head ref is out of date" reason.
UNSTABLE: waiting or blocked with an explicit "GitHub reports non-passing commit status" reason.
Proposed fix
- Update
QueueEntry.classify() to classify BEHIND and UNSTABLE as non-ready states with precise reasons.
- Keep
HAS_HOOKS separate from CLEAN in tests so future changes do not accidentally equate all mergeable states.
- Replace the current test expectation in
test_github_blocked_state_fails_closed_but_mergeable_states_do_not.
Verification
python3 -m pytest tests/test_cli.py -q
python3 -m pytest -q
[bug] BEHIND and UNSTABLE merge states are treated as ready
Summary
DeployBot treats
MergeStateStatus.BEHINDandMergeStateStatus.UNSTABLEas ready as long asmergeable == MERGEABLE. GitHub's schema definesBEHINDas an out-of-date head ref andUNSTABLEas mergeable with non-passing commit status.Those states are not equivalent to
CLEANorHAS_HOOKS, and DeployBot should not place such pull requests into the ready-to-merge path.Evidence
QueueEntry.classify()blocksDIRTY,BLOCKED, andDRAFT, waits onUNKNOWNor non-MERGEABLE, and otherwise allows the PR to become ready insrc/agent_merge_queue/cli.pylines 637-644.BEHIND,HAS_HOOKS, andUNSTABLEall classify as ready intests/test_cli.pylines 209-222.MergeStateStatusvalues in https://github.com/github/docs/blob/main/src/graphql/data/fpt/schema.docs.graphql:BEHIND: "The head ref is out of date".CLEAN: "Mergeable and passing commit status" in lines 25567-25570.HAS_HOOKS: "Mergeable with passing commit status and pre-receive hooks" in lines 25585-25588.UNSTABLE: "Mergeable with non-passing commit status" in lines 25595-25598.Impact
DeployBot can report a PR as ready even when GitHub has already computed that the branch is stale or that commit status is non-passing. This creates queue churn and confusing merge failures, and it can hide the real blocker from the user-facing queue state.
The safer interpretation is:
CLEAN: ready if DeployBot's other policy checks pass.HAS_HOOKS: ready if DeployBot's other policy checks pass, while recognizing GitHub-side hooks may still reject.BEHIND: waiting or blocked with an explicit "head ref is out of date" reason.UNSTABLE: waiting or blocked with an explicit "GitHub reports non-passing commit status" reason.Proposed fix
QueueEntry.classify()to classifyBEHINDandUNSTABLEas non-ready states with precise reasons.HAS_HOOKSseparate fromCLEANin tests so future changes do not accidentally equate all mergeable states.test_github_blocked_state_fails_closed_but_mergeable_states_do_not.Verification
python3 -m pytest tests/test_cli.py -qpython3 -m pytest -q