Skip to content

test: pin the concurrency and cancel-in-progress contract on the PR lane - #1002

Merged
mrbobbytables merged 1 commit into
mainfrom
quality/test-workflow-concurrency
Oct 3, 2026
Merged

mrbobbytables merged 1 commit into
mainfrom
quality/test-workflow-concurrency

Conversation

@hivecommons-hive

Copy link
Copy Markdown
Contributor

Test Improvement

Adds tests/ci-concurrency.test.mjs, pinning the concurrency contract that
keeps the pull_request lane from racing itself. No production code and no
workflow file is touched — the test reads .github/workflows/*.yml and writes
nothing there.

Both PR-triggered workflows already satisfy the contract; nothing asserted it:

  • .github/workflows/ci.yml:14-18 — per-PR group, cancel-in-progress: true
  • .github/workflows/codeql.yml:39-41 — same

Six guards over the parsed workflows:

  1. the pull_request detection is not vacuous (an empty set would pass everything below)
  2. every PR-triggered workflow declares a concurrency group
  3. that group sets cancel-in-progress: true
  4. that group's key varies per PR — github.event.pull_request.number, github.head_ref or github.ref inside a ${{ ... }} expression
  5. any workflow with a constant group is recorded in SERIALISED_WORKFLOWS with its reason
  6. an allowlist entry retires itself once its workflow satisfies both halves of the contract

deploy-gh-pages.yml is the single allowlist entry: it uses the constant
pages group with cancel-in-progress: false on purpose, because cancelling a
deploy halfway can leave Pages serving a partially uploaded artifact. The
allowlist follows the retiring-baseline convention already established by
KNOWN_PERSISTING_CHECKOUTS and KNOWN_UNBOUNDED_JOBS in
tests/ci-supply-chain.test.mjs.

Why a constant group is treated as a violation

concurrency: ci is one key for the whole repository. Paired with
cancel-in-progress: true it stops superseding this PR's stale run and
starts cancelling other people's PRs. The per-PR keying is what makes the
cancellation safe, so both are asserted.

Verification

Each scanner takes the parsed workflows as an argument rather than closing over
the repository's own, so its failure branch is driven by a fixture — a guard
whose failure path never runs is a guard nobody has checked.

Also mutation-tested against the real .github/workflows/ci.yml (reverted
after; the committed diff is the test file only):

mutation result
cancel-in-progress: true → false fails "every PR-triggered concurrency group cancels the superseded run"
concurrency: block deleted fails "every PR-triggered workflow declares a concurrency group"

Coverage, npm run test:unit:coverage:check (TZ=UTC) at this head, exit 0:

tests/ci-concurrency.test.mjs | 100.00 | 100.00 |  |
src files                     | 100.00 | 100.00 | 8351/8351 lines | 2395/2395 regions
all files                     |  99.37 |  95.07 | 43086/43359 lines | 7289/7667 regions

npx prettier --check passes on the new file.

Disjointness

Claims tests/ci-concurrency.test.mjs only — a new file touched by no other
open PR. #1000 pins continue-on-error on ci.yml's gating jobs; #991 and #989
are in tests/tools/e2e-coverage-report.mjs and its CLI; #996 is the unit
reporter's source-file set; #998 is the adr/ contract; #994 is SECURITY.md.
No overlap in files or assertions.

Related Issue

Closes #1001


Filed by quality agent (hold-gated mode). Human review required.

— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88

Both pull_request-triggered workflows (ci.yml, codeql.yml) declare a
per-PR concurrency group with cancel-in-progress: true, and nothing in
the suite requires either property.

Without the block, every superseded push runs to completion and reports
onto the same commit status as the run that matters. Without per-PR
keying, a constant group turns cancel-in-progress from superseding this
PR's own stale run into cancelling somebody else's PR.

tests/ci-concurrency.test.mjs asserts the group exists, cancels, and is
keyed on github.event.pull_request.number, github.head_ref or
github.ref. deploy-gh-pages.yml's deliberate constant "pages" group is
recorded in SERIALISED_WORKFLOWS with its reason, following the
retiring-baseline convention of KNOWN_PERSISTING_CHECKOUTS and
KNOWN_UNBOUNDED_JOBS in tests/ci-supply-chain.test.mjs; a companion
test deletes the entry once the workflow satisfies both halves.

Every guard takes the parsed workflows as an argument so its failure
branch runs against a fixture.

Closes #1001

Signed-off-by: quality <quality@hive.kubestellar.io>
@hivecommons-hive hivecommons-hive Bot added the hold label Oct 3, 2026
@hivecommons-hive

Copy link
Copy Markdown
Contributor Author

Important

Held for human review by the hive's ACMM level gate.

This PR was opened by the "quality" agent while Hive policy required a human checkpoint for that agent. Non-outreach agents are held at ACMM L3–L5; the outreach agent is always held because it publishes project-facing communication.

Hive will automatically remove the hold label once current policy no longer requires a level hold for "quality". If this is an outreach PR, a human must review it and remove the label.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hold quality Approved by a Hive merger/owner for auto-merge on green CI testing Approved by a Hive merger/owner for auto-merge on green CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[quality] no test pins the concurrency/cancel-in-progress contract on PR-triggered workflows

1 participant