Skip to content

ci: cancel superseded PR gate runs (PR-only), keep main/schedule/dispatch runs - #225

Merged
luisleo526 merged 2 commits into
mainfrom
ci/prtier-codegen-oss
Oct 19, 2026
Merged

luisleo526 merged 2 commits into
mainfrom
ci/prtier-codegen-oss

Conversation

@luisleo526

Copy link
Copy Markdown
Contributor

Cancel superseded PR gate runs while allowing main, scheduled and manually dispatched runs to finish. Both existing workflows group by PR number with a unique github.run_id fallback. Pyodide Gate cancels on pull_request or pull_request_target, covering its actual trusted PR trigger; Test cancels only on pull_request, retaining its main-push and dispatch triggers.

The independent tests/test_pr_workflows.py pins those exact concurrency blocks, rejects the old gate's pull_request-only rule, unconditional cancellation and cancellation including push, and preserves the guard against a pull_request job ID or display name of gate. The guard reads the workflow files that exist; the module has no dependency on the D4-held workflow and no missing-file skip.

This PR contains only the concurrency changes in .github/workflows/gate.yml and .github/workflows/test.yml, plus tests/test_pr_workflows.py. Existing triggers, runners, job names, documentation handling, differential commands, pytest coverage, release workflows and the trusted gate status reporter are retained. The additional fork-feedback workflow, its tests and the corresponding contributing-guide wording remain HELD under D4. Tests and Actions execution are not verified in this authoring lane.

Before/after JOB LIST

PR below means the pull_request event. target means the separate trusted pull_request_target event. “Pool/fallback” is the existing runner expression: the self-hosted,pf-ci,pf-ci-x64 pool for eligible non-bot events and ubuntu-24.04 otherwise. Every row describes before -> after; existing matrix legs are listed together where their routing is identical.

Workflow Job/check Runner before -> after PR before -> after Push before -> after Schedule before -> after Other triggers before -> after
Test preflight-docs pool/fallback -> same absent -> absent main -> same absent -> absent dispatch -> same
Test pytest (3.11), pytest (3.12), pytest (3.13), pytest (3.14) pool/fallback -> same absent -> absent main, unless docs-only -> same absent -> absent dispatch, unless docs-only -> same
Pyodide Gate preflight-docs target: ubuntu-24.04; schedule/dispatch: pool/fallback -> same absent -> absent absent -> absent enabled -> same target and dispatch -> same
Pyodide Gate differential target: ubuntu-24.04; schedule/dispatch: pool/fallback -> same absent -> absent absent -> absent enabled -> same same-repo target, unless docs-only; dispatch -> same; fork target remains skipped
Pyodide Gate pytest (3.11), pytest (3.12), pytest (3.13), pytest (3.14) target: ubuntu-24.04; schedule/dispatch: pool/fallback -> same absent -> absent absent -> absent enabled -> same same-repo target, unless docs-only; dispatch -> same; fork target remains skipped
Pyodide Gate gate target: ubuntu-24.04; schedule/dispatch: pool/fallback -> same absent -> absent absent -> absent enabled -> same target and dispatch -> same
Release release ubuntu-latest -> same absent -> absent absent -> absent absent -> absent dispatch, non-placeholder -> same
Release claim-name ubuntu-24.04 -> same absent -> absent absent -> absent absent -> absent dispatch, placeholder -> same
Publish codegen-pyodide publish ubuntu-latest -> same absent -> absent v* tags -> same absent -> absent dispatch, non-placeholder -> same
Publish codegen-pyodide claim-npm ubuntu-24.04 -> same absent -> absent skipped without placeholder input -> same absent -> absent dispatch, placeholder -> same
promote-baseline promote ubuntu-latest -> same absent -> absent absent -> absent absent -> absent merged target close and dispatch -> same

Job-list sources: .github/workflows/test.yml:3, .github/workflows/test.yml:16, .github/workflows/test.yml:74; .github/workflows/gate.yml:3, .github/workflows/gate.yml:17, .github/workflows/gate.yml:74, .github/workflows/gate.yml:119, .github/workflows/gate.yml:153; .github/workflows/release.yml:10, .github/workflows/release.yml:44, .github/workflows/release.yml:195; .github/workflows/publish-pyodide.yml:8, .github/workflows/publish-pyodide.yml:25, .github/workflows/publish-pyodide.yml:37, .github/workflows/publish-pyodide.yml:107; .github/workflows/promote-baseline.yml:74, .github/workflows/promote-baseline.yml:108. Existing-file before/after evidence is git diff; their job definitions and runner expressions are unchanged.

Measured current PR wall time

Historical current baseline: median 1.8 min, p90 2.3 min, maximum 2.5 min, over 45 code-PR heads. Method: successful attempt-1 runs, queue included, last 100 completed PR runs, optimistic.

Source: /Users/haoliangwen/.local/state/pineforge/runner/ORG-CX/proof/CI-SLIM/pr-wall/README.md:12; method and exclusions at that file's lines 5 and 7. These historical measurements include earlier Test PR runs; the checked-out Test trigger is now main push/dispatch only. They do not measure the concurrency change or the held PR Test workflow.

That source's line 18 gives workflow-level Test median 103 s and p90 140 s, and Pyodide Gate median 10 s. It gives no per-job hosted timing or queue/run split. The gate median is not evidence for the duration of a complete differential sweep.

ESTIMATE, not verified: the scoped concurrency PR keeps the existing job graph: preflight-docs + max(differential, pytest matrix) + gate for a full trusted PR gate, and preflight-docs + pytest matrix for Test. The changed wall time is not measurable from the tree; superseded-run cancellation is the intended improvement. No job is moved to a later trigger, so this set introduces no detection delay.

Status-check compatibility and validation

Existing workflow and job names are preserved. The required gate context is documented in .github/workflows/promote-baseline.yml:16 and emitted by .github/workflows/gate.yml:201; /Users/haoliangwen/.local/state/pineforge-top-core/runs/core-org-r33/review-prtier-out.md:8 records the live required context as gate. No live ruleset query was run in this lane and no ruleset change is proposed. The held workflow has distinct job IDs, no job-level display-name overrides, no status-writing step, read-only permissions, no secrets and no reusable workflow calls.

The independent policy tests reject a pull_request workflow job ID or display name of gate, including quoted forms, while allowing the trusted target workflow. They pin the exact existing-workflow concurrency rules and include must-fail cancellation and grouping mutations. The held tests retain the new runner, trigger, documentation and Python-version contracts, plus tests that execute the actual aggregate shell with successful, failed, cancelled, missing and skipped dependency results. No tests were executed here; their results are not verified.

The D4 hold applies to the workflow/test pair and the contributing-guide wording listed above. The independent policy file has no module-level workflow read, no import of the held test file and no skip-if-missing rule. Its guard scans existing workflow paths and its concurrency checks require only gate.yml and test.yml. A green pr-tests must not satisfy the required gate context. The existing fork-code gate refusal remains in force.

🤖 Generated with Claude Code

…/test_pr_workflows.py

Part of the org PR-tier order (bulletin #729). Existing workflows only.

- gate.yml: concurrency group keyed on the PR number (run id otherwise);
  cancel-in-progress only for pull_request and pull_request_target (the events
  gate.yml runs on for PRs). Push and dispatch runs are never cancelled. The
  required `gate` check name and its pinned integration are unchanged.
- test.yml: group keyed on the PR number (run id otherwise); cancel only for
  pull_request. Runs on main are never cancelled.
- tests/test_pr_workflows.py: pins both expressions with must-fail forms (the
  old pull_request-only text, an unconditional true, a push event included) and
  the rule that no pull_request workflow defines a job named `gate`. It reads
  only workflows that exist, so it passes with or without pr-test.yml.

The fork-PR test workflow (pr-test.yml) and the test that reads it are NOT part
of this change (decision D4: they go live after the fork-PR proof).

Not run on this machine; the PR's own CI is the proof.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@luisleo526
luisleo526 merged commit aebad8c into main Oct 19, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant