Skip to content

Commit 1880b0d

Browse files
Keep late draft CI runs from cancelling real ones (#1708)
An agent pushes a commit and runs `gh pr ready` seconds later. GitHub can deliver that push's `synchronize` event (payload still draft: true) after `ready_for_review`. Both runs shared one concurrency group with cancel-in-progress, so the late draft run cancelled the real run, skipped every job on the draft gate, and reported ci-ok green on a head nothing had tested. Seen on #1706 and #1707 today; both needed a manual re-run to get a real verdict. Give draft PR runs their own group so they can never cancel a ready-state run. Draft pushes still supersede each other, as do ready pushes. Add a scheduling test that pins the split. Claude-Session: https://claude.ai/code/session_01EtzNTGaPfJK39cMX68F1qw Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3db3cdf commit 1880b0d

2 files changed

Lines changed: 13 additions & 2 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,13 @@ permissions:
3939
# queued push but the newest during a merge burst, and most main commits never
4040
# got a verdict. Merge-group refs (gh-readonly-queue/...) are unique per queue
4141
# entry already. The nightly keeps its own group so it never queues behind (or
42-
# cancels) a push.
42+
# cancels) a push. Draft PR runs get their own group too: a push followed at
43+
# once by `gh pr ready` can deliver the push's `synchronize` (payload still
44+
# draft) after `ready_for_review`. In a shared group that late draft run
45+
# cancelled the real run, skipped every job, and left ci-ok green on a head
46+
# nothing had tested.
4347
concurrency:
44-
group: ci-${{ github.event.pull_request.number || (github.event_name == 'push' && github.sha) || github.ref }}${{ github.event_name == 'schedule' && '-nightly' || '' }}
48+
group: ci-${{ github.event.pull_request.number || (github.event_name == 'push' && github.sha) || github.ref }}${{ github.event_name == 'schedule' && '-nightly' || '' }}${{ github.event.pull_request.draft && '-draft' || '' }}
4549
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
4650

4751
# Linux jobs run on Depot's runners (depot-ubuntu-*-4: 4 vCPU, like GitHub's

‎scripts/tests/test_ci_scheduling.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,13 @@ def test_unchanged_pr_merge_skips_only_what_the_queue_re_tests(self):
203203
self.assertIn("if: github.event_name == 'pull_request' && github.base_ref == 'main'"
204204
" && github.head_ref != 'release/v5-prerelease'", owner)
205205

206+
def test_late_draft_run_cannot_cancel_the_ready_run(self):
207+
# A push's draft-payload `synchronize` can land after `ready_for_review`
208+
# on the same head; sharing a group, it cancelled the real run and left
209+
# ci-ok green with every job skipped.
210+
group = re.search(r"^concurrency:\n group: (.*)$", TEXT, re.M)[1]
211+
self.assertIn("github.event.pull_request.draft && '-draft'", group)
212+
206213
def test_row_reader_preserves_both_os_siblings(self):
207214
jobs = reader.jobs("""jobs:
208215
example:

0 commit comments

Comments
 (0)