ci: exempt only push from concurrency cancellation

The two self-hosted standby drills each run their complete unsharded
aggregate with one gate worker, which takes longer than the interval
between master merges, so unconditional cancel-in-progress supersedes a
drill before it reaches a verdict and the lane yields no readiness
evidence for the failover runbook to point a responder at.

Exempt push and nothing else. This has to be decided at workflow level:
cancellation applies to the whole superseded run, so a job-level
concurrency group cannot exempt its job. The negated form is
load-bearing — naming pull_request alone would also stop cancelling
workflow_dispatch, and each runner benchmark fans out to twelve larger
runners for up to fifteen minutes in this same group on master, so a
re-dispatch would queue ahead of a drill instead of replacing a stale
measurement. It does not promise every push run finishes: a newer
pending run still displaces an older one, only that the lanes
periodically reach a verdict.

A master push carries only wine-apt-cache and the two drills; every other
job is pull-request-gated, workflow_dispatch-gated, or if: false. The
spec pins that set and classifies by exact condition, since a negated
event test mentions the event it excludes.
This commit is contained in:
Chinesezjc
2026-08-12 16:37:11 +08:00
parent 15c84cdc4b
commit ba1b0e15fc
5 changed files with 88 additions and 3 deletions
@@ -12,6 +12,10 @@ The three required Linux worker jobs in [CI](../../../../.github/workflows/ci.ym
Each of the three required Linux worker jobs, the independent native Windows job, and the `all checks passed` verdict job — which would otherwise stay queued on the failed pool even after every worker passed — resolves its runner pool through the `DSH_CI_FAILOVER` repository variable. Unset (normal), they run on the hosted enterprise pools. Set to `selfhosted` by any repository writer, all five retarget onto the in-house self-hosted pools: the Linux jobs and verdict onto the `vm-backup` pool, coverage and snapshot concurrency drop to shared-VM bounds, and the hosted-path pnpm cache restores are skipped; the native Windows job onto the `dsh-win-ci` pool. The switch is writer-manageable repository state, not a merge, so it works while every check is red. The in-house pools' readiness is continuously re-proven by the `serial / linux (self-hosted standby)` and `serial / windows (self-hosted standby)` lanes, which run the complete unsharded aggregates on every master push.
`ci.yml` exempts exactly one event from `cancel-in-progress` (`${{ github.event_name != 'push' }}`), so a superseded pull-request run is still cancelled while a push run is left to run. Each drill runs its complete unsharded aggregate with one gate worker, which takes longer than the interval between master merges; under unconditional cancellation a drill is superseded before reaching a verdict and the lane yields no readiness evidence for a responder to check. This is not a guarantee that every push run finishes: GitHub keeps a single pending entry per group, so a newer pending run displaces an older one, and during busy periods intermediate push runs still end as `cancelled`. What the carve-out buys is that the lane periodically reaches a verdict at all, which is what makes it usable as evidence.
The decision belongs at workflow level because cancellation applies to the whole superseded run: a job-level `concurrency` group does not exempt its job. The negated form is load-bearing rather than cosmetic: naming `pull_request` alone would also stop cancelling `workflow_dispatch`, and each runner benchmark fans out to twelve larger runners for up to fifteen minutes inside this same group on master, so a re-dispatch would queue ahead of a drill instead of replacing a stale measurement. What bounds the cost is that a master push carries only `wine-apt-cache` and these two drills; every other job is pull-request-gated, `workflow_dispatch`-gated, or `if: false`, and `scripts/ci-workflow.spec.ts` pins that set — classifying by exact condition, since a negated event test mentions the event it excludes — so a new push-reachable job cannot quietly start accumulating uncancelled runs.
### What the in-house pool is
`vm-backup`: one 64-core VM, six always-on systemd-managed runner instances. Its image must preinstall Playwright Chromium's Linux system packages; CI downloads the lockfile-selected browser but never runs `apt` on this persistent shared host. Check the latest `serial / linux (self-hosted standby)` run before switching: its aggregate includes browser replay, so a green standby verifies both ordinary capacity and this browser prerequisite.