Skip to content

ci(workflows): do not cancel master push runs by concurrency - #2066

Merged
lusoris merged 3 commits into
masterfrom
ci/master-runs-not-cancelled-by-concurrency
Oct 5, 2026
Merged

lusoris merged 3 commits into
masterfrom
ci/master-runs-not-cancelled-by-concurrency

Conversation

@lusoris

@lusoris lusoris commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

BLUF: a push to master no longer cancels the workflow runs of the previous master commit. The merge train keeps one sentinel commit's runs alive and cancels other superseded master runs itself.

Measured on a60b7a9: Tests, Rust, Lint, FFmpeg, Docker Image Build, Dev Container, CI, Builds and Build all ended cancelled because 18 push-to-master workflows used a per-ref concurrency group with cancel-in-progress: true.

Change

  • 18 workflows: group carries github.sha on master, cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}. PR refs keep one group per ref and still cancel.
  • Kept serialised, listed with reasons in the contract test: dev-container-publish.yml (registry publish), release-please.yml (duplicate release PR), scorecard.yml (attestation publish), docs.yml deploy job (one Pages deployment). docker-publish-tester.yml and windows-tester-bundle.yml already had the SHA in the group on a push. Scheduled, dispatch, release and PR-only workflows are out of scope.
  • Required Checks Aggregator: same form. Re-running an old master head no longer cancels the newest aggregator. On a PR ref an older head's re-run still cancels the current one.
  • New contract test scripts/ci/tests/test_master_concurrency_contract.py (21 cases: positive, negative, boundary, stale list entries). On the old workflows it reports 18 findings; on this branch it passes. test_security_workflow_contract.py and test_ffmpeg_patch_workflow_contract.py updated for the new group.
  • docker-image.yml: two || true on diagnostic cat lines replaced by an explicit file check (touched-file HISS-07 rule).
  • Docs: docs/development/ci.md "Master push runs". ADR-1673, state row opened and closed, rebase note, changelog fragment.

Reproducer

python3 -B -m unittest scripts/ci/tests/test_master_concurrency_contract.py
actionlint .github/workflows/*.yml
bash scripts/ci/check-aggregator-names.sh

Live effect on runs is not verified here; it needs the next master pushes.

Deep-dive deliverables

  • Research digest — no digest needed: trivial
  • Decision matrix: in ADR-1673 Alternatives considered
  • AGENTS.md invariant note: scripts/ci/AGENTS.d/workflow-contract-tests.md and .github/AGENTS.d/security-scans.md
  • Reproducer / smoke-test command — see the Reproducer section above
  • CHANGELOG fragment: changelog.d/changed/master-runs-not-cancelled-by-concurrency.md
  • Rebase note — docs/rebase-notes.md, ADR-1673 entry

@github-actions github-actions Bot added the type:ci CI and infrastructure label Oct 5, 2026
@lusoris
lusoris force-pushed the ci/master-runs-not-cancelled-by-concurrency branch 3 times, most recently from 58bc4cc to 063a8f7 Compare October 5, 2026 20:37
xxxxxxxxxxxxx and others added 3 commits October 5, 2026 23:08
…t INT64_MAX scores (#2190)

* fix(adm): sum the scale-0 contrast-masking rows unsigned so a row past INT64_MAX scores

The integer ADM masking reduction adds, per row, the non-negative cubes of
the CSF-weighted coefficients above their threshold, and the CPU, its
AVX2 / AVX-512 rows and the CUDA, HIP and SYCL twins summed a scale-0 row
in int64. Compared with itself, a 31-32 or 63-64 pixel wide picture with
full-range reference detail (core/test/adm_cm_row_overflow_frame.h) takes
one row to 1.044 / 1.021 INT64_MAX at the default weights: the sum
wrapped, the numerator was NaN and the frame failed with "invalid ADM
reduction". A horizontal or vertical CSF weight above 38,400 does the
same at 16K. Scale 0 now sums its rows and its frame unsigned
(adm_cm_round_row_total_s0(), adm_cm_fold_s0(), uint64_t rows in every
backend; the GPU hosts read the scale-0 slots as uint64_t), which holds
every row at the default weights (0.52 of 2^64 at worst) and up to an h/v
weight of about 45,200. Below 2^63 the values keep their bits. Scales 1-3
keep their signed sums. The weights between 45,200 and the ADR-1472 limit
of 46,603 are left open as T-ADM-CM-SCALE0-ROW-UINT64-WEIGHT-BUDGET.

The CUDA and HIP scale 1-3 decouple also narrowed the gain product
(|o| up to 1.45e9 times the limit of 100) to int32 before bounding it by
t, an undefined conversion the devices' saturation hid; they now bound
the double product with fmin / fmax and narrow once, as the CPU does.

test_integer_adm_cm_row_unsigned (8, 10, 16 bit; SIMD == scalar) and the
new row case of test_gpu_adm_tiny_frames fail on master and pass on the
CPU, CUDA, HIP and SYCL; the fold and gain contracts pin both forms; the
Netflix golden gate passes.

Closes T-ADM-CM-SCALE0-ROW-INT64-OVERFLOW-2026-10-05.
Closes T-GPU-ADM-S123-GAIN-PRODUCT-NARROWING-2026-10-05.
…filters after a mid-run error (#2115)

* fix(ffmpeg): print no pooled score from the libvmaf and libvmaf_cuda filters after a mid-run error

Upstream FFmpeg's libvmaf and libvmaf_cuda filters share one uninit().
After a failed picture copy or vmaf_read_pictures(), the run exited
non-zero, but uninit() still pooled the frames read before the error and
printed a VMAF score line. frame_cnt had already counted the failed
frame, so the pooling usually failed and the line showed an uninitialised
value: "VMAF score: 0.000000" for both filters in the dev container. The
error line named neither the frame nor the error.

As the maintainer decided, new series patch 0021 makes these filters
follow the rule libvmaf_sycl and libvmaf_metal follow since ADR-1761
(ADR-1768):
- one error names the filter, the step, the frame and the error;
- the frame is freed and the filter records the stop;
- frame_cnt advances only after a successful read;
- uninit() prints no pooled score and writes no report after a stop, a
  failed flush or a failed pooled score.
The divergence from upstream is deliberate and is kept on every series
refresh.

ffmpeg-patches/test/check-libvmaf-no-score-after-error.sh injects the
errors through the LD_PRELOAD shim. The shim is renamed
fault_inject_libvmaf.c and now injects vmaf_read_pictures() failures too.
The script runs the CPU filter, and libvmaf_cuda on the RTX 4090. With
this branch's series, 17 of 17 checks pass; the previous FFmpeg fails 6.
core/test/test_ffmpeg_libvmaf_stop_contract.py checks the series without
a device.

* docs: regenerate the indexes and the citation map after rebasing
* ci(workflows): do not cancel master push runs by concurrency

A push to master no longer cancels the runs of the previous master commit.
The concurrency group of every push-to-master workflow carries github.sha on
master and cancel-in-progress stays on for pull request refs. Publish,
release-please, Scorecard and the Pages deploy job stay serialised and are
listed with reasons in a new contract test. The Required Checks Aggregator
takes the same form, so re-running an old master head cannot cancel the
newest one.

* ci(workflows): type the master concurrency contract test

* test(ffmpeg): update workflow concurrency group expectation for master push

* docs: regenerate the indexes and the citation map after rebasing
@lusoris
lusoris force-pushed the ci/master-runs-not-cancelled-by-concurrency branch from 063a8f7 to 4184ef4 Compare October 5, 2026 21:42
@lusoris
lusoris merged commit 4184ef4 into master Oct 5, 2026
5 of 48 checks passed
@lusoris
lusoris deleted the ci/master-runs-not-cancelled-by-concurrency branch October 5, 2026 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:ci CI and infrastructure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants