Repository navigation
ci: queue the dev push runs instead of cancelling the waiting one - #734
Merged
Pedro Henrique Penna (ppenna) merged 1 commit intoOct 21, 2026
Merged
Pedro Henrique Penna (ppenna) merged 1 commit into
Pedro Henrique Penna (ppenna) merged 1 commit into
Conversation
Pushes to dev share one concurrency group, which keeps one running and one waiting run, and a newer push cancels the run that waits. When merges land faster than a run finishes, each merge but the last loses its run: 12 of the 199 dev pushes from October 4 to 21 were cancelled before any job started, 9 of them on October 20 and 21, and five merged within four minutes on October 20 left a single run. Those commits got no development release and no performance results, and because the detector compares a push with its previous commit, the run that followed classified only its own changes and could skip a suite that a cancelled merge needed. Let up to 100 runs of the group wait and start in turn with queue: max for every event but pull_request. GitHub rejects queue: max together with cancel-in-progress: true, so the workflow derives both settings from the event, and pull requests keep the single waiting run and cancel the run of an older head as before. Scheduled and manually dispatched full runs keep a group of their own. GitHub orders the waiting runs by when they began to wait, without guaranteeing it, and neither the development release, which is tagged by its commit, nor performance persistence, which appends to the latest dev and retries a rejected push, depends on that order. A queued run waits for those ahead of it. Replaying the dev pushes of October 4 to 21 one at a time, half would have started at once, one in ten would have waited at least 50 minutes, and the longest wait, on October 20, would have been about three hours. The runners still carry one dev run at a time; the only added load is the runs that the group used to cancel, about 6% of the dev pushes in that period. The workflow schema accepts an expression for each concurrency property, and public workflows already queue their default branch's pushes while cancelling superseded pull-request runs the same way. A CI configuration test pins both settings and rejects a static queue: max, which would keep every pull-request run from starting. doc/ci.md describes run concurrency, and the Copilot instructions and the CI investigation skill no longer treat a cancelled dev push run as an expected supersession. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The focused configuration change preserves pull-request behavior, has consistent tests and documentation, and has no identified blocking issues.
No open issues 🎉
What changed in this PR
Preserves CI coverage for successive dev merges by queueing push runs instead of replacing waiting runs, while retaining pull-request cancellation.
Changes:
- Selects queue mode by event without changing concurrency groups.
- Adds regression assertions for queue and cancellation settings.
- Updates concurrency documentation and cancellation-triage guidance.
| File | Description |
|---|---|
scripts/test_nvx_tools.py |
Tests event-dependent concurrency settings. |
doc/ci.md |
Documents queue behavior and expected delays. |
.github/workflows/ci.yml |
Enables queued pushes while preserving PR cancellation. |
.github/skills/nvx-ci-investigation/SKILL.md |
Distinguishes push cancellations from expected supersession. |
.github/copilot-instructions.md |
Updates repository concurrency guidance. |
Review effort: Balanced
Pedro Henrique Penna (ppenna)
deleted the
agents/investigate-multiple-merges-velocity
branch
October 21, 2026 20:56
This was referenced Oct 21, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #430.
Summary
Pushes to
devshare one concurrency group (ci-CI-refs/heads/dev). With the default queue mode, a group keeps one running and one waiting run, and each newer push cancels the run that waits. When merges land faster than a run finishes, every merge but the last loses its run. This PR letsdevpush runs queue in order (queue: max, up to 100 waiting) while pull requests keep cancelling superseded runs exactly as before.Why
From October 4 to 21, 12 of the 199
devpush runs were cancelled before any job started, 9 of them on October 20 and 21. In the worst burst, #637, #635, #636, #633, and #634 merged within four minutes on October 20 and only #650's run executed. Each lost run means:nvx.py downloadfalls back to an earlier first-parent release).github.event.before, so the surviving run classifies only its own merge, and can skip a suite that only a cancelled merge's files selected.The 12 cancelled
devpush runs (UTC)None of them started a job, so every one was a waiting run replaced by a newer push.
Merging itself is not blocked:
devhas no merge queue and no up-to-date requirement. Development release publication and performance persistence already tolerate runs finishing in any order: each release is tagged by its commit, and persistence appends to the latestdevand retries a rejected push.Options
Both options were replayed against the 199 observed
devpushes, using their measured durations and the median duration for the cancelled ones.devruns cancelleddevrundevpushes (this PR)devrun at a time; +6% runs (those that used to be cancelled)devpushdevruns at peak, competing with pull-request runs and the single benchmark runner per backendA keeps pull-request turnaround, which gates merges, where it is. The lag only defers the post-merge release and baseline update.
Why the queue mode is an expression
ci.ymlsetscancel-in-progress: ${{ github.event_name == 'pull_request' }}. GitHub rejectsqueue: maxtogether withcancel-in-progress: true(docs), and Add concurrency queue support actions/languageservices#355 notes the combination is "also blocked at runtime". A staticqueue: maxwould therefore be rejected for every pull-request run.queueassingle|max. Likecancel-in-progress, a concurrency property whose value is an expression is checked when the run is created, after the server evaluates it.reactive/data-client(benchmark.yml) uses the same pair:cancel-in-progress: ${{ github.event_name == 'pull_request' }}withqueue: ${{ github.event_name == 'push' && 'max' || 'single' }}.SonarSource/sonar-scanner-msbuildandchrisbanes/hazemake the same split by branch.chrisbanes/hazeon October 17, threemainpushes queued and ran in order: 39071141458, then 39073679265, then 39073955706. The third was created while the second was still waiting, which the default mode would have cancelled. Its pull-request runs still cancel superseded heads.Changes
.github/workflows/ci.yml: addsqueue: ${{ github.event_name == 'pull_request' && 'single' || 'max' }}next to the existingcancel-in-progress, with a comment on why it is an expression. Scheduled and manually dispatched full runs keep their own per-run group.scripts/test_nvx_tools.py: addstest_ci_dev_pushes_queue_while_pull_requests_cancel. It pins both settings and rejects a staticqueue: max.doc/ci.md: adds a Run concurrency section covering the groups, what the single waiting run lost, the constraint, and the replayed waits..github/copilot-instructions.md,.github/skills/nvx-ci-investigation/SKILL.md: a cancelleddevpush run is no longer treated as an expected supersession.Validation
python -m unittest scripts.test_nvx_tools.CiConfigurationTests: 67 tests OK (3 skipped) on the rebased head.queueis a staticmax, a quoted'max', or missing.ruff check,ruff format --check,pyright(Linux and Windows platforms), andscripts/check_markdown_links.pypass.validate-nvxunittest set ran locally on Windows (1,090 tests). The only failures are 18test_setup_azuresubtests, which fail identically on the unmodified base on that machine.Post-merge verification
singlebranch together withcancel-in-progress: true.devpush run exercises themaxbranch. It must start its jobs rather than fail workflow validation.devruns pending instead of cancelled.queueline.