What happened?
Backport Approvals is a required status check on main (.asf.yaml), and GitHub evaluates the latest check run with that name on the head commit. The workflow's concurrency group uses cancel-in-progress: true (.github/workflows/backport-approval-check.yml), so when two pull-request events land seconds apart, the newer run cancels the older one. The job itself finishes in 6-9 seconds, so the older run's "cancelled" terminal state can be recorded after the newer run's success — the cancelled run is then the latest check run, the required check reads as not passing, and the merge button is blocked even though a sibling run of the same commit already passed.
This cannot bite the long build workflows (their new run finishes minutes after the old one's cancellation, so the success is always the latest state); it is specific to second-scale required checks. The check's own verdict was never wrong — a PR with no release/* label passes trivially — the block comes only from the cancelled duplicate.
How to reproduce?
Seen on #8516, head d5bf9af59:
- A push fired a
pull_request run at 14:59:24 (run 34700864066).
- A review-comment reply fired a
pull_request_review run at 14:59:31 (run 34700870759), which cancelled the first.
- The second run passed in 8s; the first run's cancelled state landed after that success. The PR showed
Backport Approvals as its one non-green required check and mergeStateStatus: BLOCKED.
- Re-running the cancelled run (6s, success) unblocked the merge.
Any pair of close-together events on one commit reproduces it: push + review request, push + label, label + label.
Version/Branch
main
Commit Hash (Optional)
d5bf9af (the blocked head; the workflow itself is at main's tip)
Relevant log output
run 34700864066 event=pull_request created=14:59:24 conclusion=cancelled
run 34700870759 event=pull_request_review created=14:59:31 conclusion=success (8s)
gh pr view 8516 --json mergeStateStatus -> "BLOCKED"
Fix: queue instead of cancel (cancel-in-progress: false) — every run ends with a real conclusion, FIFO order keeps the newest evaluation reporting last, and the job runs in seconds so queuing costs nothing.
What happened?
Backport Approvalsis a required status check onmain(.asf.yaml), and GitHub evaluates the latest check run with that name on the head commit. The workflow's concurrency group usescancel-in-progress: true(.github/workflows/backport-approval-check.yml), so when two pull-request events land seconds apart, the newer run cancels the older one. The job itself finishes in 6-9 seconds, so the older run's "cancelled" terminal state can be recorded after the newer run's success — the cancelled run is then the latest check run, the required check reads as not passing, and the merge button is blocked even though a sibling run of the same commit already passed.This cannot bite the long build workflows (their new run finishes minutes after the old one's cancellation, so the success is always the latest state); it is specific to second-scale required checks. The check's own verdict was never wrong — a PR with no
release/*label passes trivially — the block comes only from the cancelled duplicate.How to reproduce?
Seen on #8516, head
d5bf9af59:pull_requestrun at 14:59:24 (run 34700864066).pull_request_reviewrun at 14:59:31 (run 34700870759), which cancelled the first.Backport Approvalsas its one non-green required check andmergeStateStatus: BLOCKED.Any pair of close-together events on one commit reproduces it: push + review request, push + label, label + label.
Version/Branch
main
Commit Hash (Optional)
d5bf9af (the blocked head; the workflow itself is at main's tip)
Relevant log output
Fix: queue instead of cancel (
cancel-in-progress: false) — every run ends with a real conclusion, FIFO order keeps the newest evaluation reporting last, and the job runs in seconds so queuing costs nothing.