From ae605c2d2320be9416e95116e8bb883e733347dc Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Fri, 18 Sep 2026 10:03:12 +0000 Subject: [PATCH] ci: run pull-request checks only when ci-full is applied GitHub creates and queues a workflow run before it evaluates job-level `if`. After agents marked a swarm ready, 80 CI runs sat ahead of release publish even though earlier draft guards had kept their jobs light. Pull-request CI, plugin validation, and SDK conformance now trigger only on a label event and run only when that event applies ci-full. Opening, pushing, and marking ready create no run. Remove and re-add ci-full after a new push to test that head; ci-os, ci-hosts, and perf still extend that dispatch. --- .github/workflows/ci.yml | 22 +++++++++++----------- .github/workflows/plugin-validation.yml | 6 +++--- .github/workflows/sdk-conformance.yml | 8 ++++---- CONTRIBUTING.md | 17 +++++++++-------- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dbb27aab6b..67ac02ced4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,11 +3,13 @@ name: CI on: push: branches: [master, feature/holographic-memory] + # Pull-request CI is deliberately on demand. `opened`/`synchronize` would + # create a queued workflow run even when every job's `if` skips it; 173 + # concurrently opened PRs produced 80 such runs ahead of release publish. + # Add (or remove and re-add) `ci-full` to test the current head. pull_request: branches: ['**'] - # `ready_for_review` and `labeled` are what lift a pull request from the - # light gates into full CI, so they must start a run. - types: [opened, synchronize, reopened, ready_for_review, labeled] + types: [labeled] permissions: contents: read @@ -39,8 +41,7 @@ jobs: # # * `run-heavy`: the Linux build/test/lint lane. Pushes always; pull # requests only when trusted (this repository, or a fork targeting an - # integration branch) and either ready for review or labelled `ci-full`. - # A draft runs no job at all (see the `if` below). + # integration branch) and explicitly dispatched with `ci-full`. # * `run-os`: the macOS and Windows matrices. Pushes, or a pull request # labelled `ci-os`. macOS has its own 5-slot cap and Windows shards take # 7 jobs; both verify the same code the Linux lane already covers and @@ -56,7 +57,7 @@ jobs: # and even three light gates apiece queued the release behind ~400 jobs; # a job that is skipped here costs no runner, and every guarded job reads # this job's outputs, so skipping it skips them. `ci-full` opts a draft in. - if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.draft || contains(github.event.pull_request.labels.*.name, 'ci-full') }} + if: ${{ github.event_name != 'pull_request' || github.event.label.name == 'ci-full' }} runs-on: ubuntu-latest timeout-minutes: 5 permissions: @@ -75,14 +76,13 @@ jobs: env: EVENT: ${{ github.event_name }} TRUSTED: ${{ github.event.pull_request.head.repo.full_name == github.repository || contains(fromJSON('["master","feature/holographic-memory"]'), github.event.pull_request.base.ref) }} - DRAFT: ${{ github.event.pull_request.draft }} LABELS: ${{ join(github.event.pull_request.labels.*.name, ' ') }} run: | has_label() { [[ " $LABELS " == *" $1 "* ]]; } heavy=false; os=false; hosts=false; perf=false if [[ $EVENT != pull_request ]]; then heavy=true; os=true; hosts=true; perf=true - elif [[ $TRUSTED == true ]] && { [[ $DRAFT != true ]] || has_label ci-full; }; then + elif [[ $TRUSTED == true ]] && has_label ci-full; then heavy=true has_label ci-os && os=true has_label ci-hosts && hosts=true @@ -94,7 +94,7 @@ jobs: echo "run-hosts=$hosts" echo "run-perf=$perf" } >>"$GITHUB_OUTPUT" - echo "run-heavy=$heavy run-os=$os run-hosts=$hosts run-perf=$perf (event=$EVENT draft=${DRAFT:-n/a} labels='$LABELS')" + echo "run-heavy=$heavy run-os=$os run-hosts=$hosts run-perf=$perf (event=$EVENT labels='$LABELS')" # The Linux and macOS test matrices come from the same manifest the # partition jobs select their targets from, so a partition cannot exist @@ -242,7 +242,7 @@ jobs: benchmark-harness: name: Benchmark harness self-tests - if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.draft || contains(github.event.pull_request.labels.*.name, 'ci-full') }} + if: ${{ github.event_name != 'pull_request' || github.event.label.name == 'ci-full' }} runs-on: ubuntu-latest timeout-minutes: 10 steps: @@ -260,7 +260,7 @@ jobs: # queue entries per push doing what one does. gates: name: Repository gates - if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.draft || contains(github.event.pull_request.labels.*.name, 'ci-full') }} + if: ${{ github.event_name != 'pull_request' || github.event.label.name == 'ci-full' }} runs-on: ubuntu-latest timeout-minutes: 15 steps: diff --git a/.github/workflows/plugin-validation.yml b/.github/workflows/plugin-validation.yml index ac631ab3f5..e9aaee5c0d 100644 --- a/.github/workflows/plugin-validation.yml +++ b/.github/workflows/plugin-validation.yml @@ -16,7 +16,7 @@ on: - "crates/tracedecay/tests/agent_suite/*skill*" - ".github/workflows/plugin-validation.yml" pull_request: - types: [opened, synchronize, reopened, ready_for_review] + types: [labeled] paths: - "plugin/**" - "plugin/cursor-native-extension/**" @@ -34,7 +34,7 @@ concurrency: jobs: manifest-schema: - if: github.event_name != 'pull_request' || !github.event.pull_request.draft + if: github.event_name != 'pull_request' || github.event.label.name == 'ci-full' name: Manifest schema runs-on: ubuntu-latest timeout-minutes: 5 @@ -75,7 +75,7 @@ jobs: done claude-native-validation: - if: github.event_name != 'pull_request' || !github.event.pull_request.draft + if: github.event_name != 'pull_request' || github.event.label.name == 'ci-full' name: Claude native plugin validation runs-on: ubuntu-latest timeout-minutes: 10 diff --git a/.github/workflows/sdk-conformance.yml b/.github/workflows/sdk-conformance.yml index 6d5a1638e7..35d42caaee 100644 --- a/.github/workflows/sdk-conformance.yml +++ b/.github/workflows/sdk-conformance.yml @@ -2,7 +2,7 @@ name: SDK conformance on: pull_request: - types: [opened, synchronize, reopened, ready_for_review] + types: [labeled] paths: - ".github/workflows/**" - ".github/release-targets.json" @@ -55,7 +55,7 @@ concurrency: jobs: publish-workflow-policy: - if: github.event_name != 'pull_request' || !github.event.pull_request.draft + if: github.event_name != 'pull_request' || github.event.label.name == 'ci-full' runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -90,7 +90,7 @@ jobs: .github/workflows/release-please.yml .github/workflows/release-pr-integrity.yml packages: - if: github.event_name != 'pull_request' || !github.event.pull_request.draft + if: github.event_name != 'pull_request' || github.event.label.name == 'ci-full' runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -111,7 +111,7 @@ jobs: working-directory: sdks/typescript production-router: - if: github.event_name != 'pull_request' || !github.event.pull_request.draft + if: github.event_name != 'pull_request' || github.event.label.name == 'ci-full' runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 30c3cbeed4..84479ab95c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -257,16 +257,17 @@ integration branch waits behind, so a run spends only what its state earns: | State | Runs | |---|---| -| Draft | Nothing. Mark it ready or add `ci-full` to run CI. | -| Ready for review (or labelled `ci-full`) | Repository gates (commit lint, release guards, rustfmt), benchmark-harness self-tests, and the Linux lane: build, clippy, feature gates, dashboard, Linux test partitions, PR dogfood with the MCP conformance smoke. | -| Labelled `ci-os` | Adds the macOS and Windows matrices. | -| Labelled `ci-hosts` | Adds the stock Hermes / Claude Code / OpenCode integrations. | -| Labelled `perf` | Adds hotpath parity and runs the hotpath profile, coverage, and runtime-core workflows. | +| Pull request without `ci-full` | Nothing. Opening, pushing, and marking ready do not create CI runs. | +| Add `ci-full` | Repository gates, benchmark-harness self-tests, and the Linux lane: build, clippy, feature gates, dashboard, Linux test partitions, PR dogfood with the MCP conformance smoke. | +| Also labelled `ci-os` | Adds the macOS and Windows matrices to that `ci-full` dispatch. | +| Also labelled `ci-hosts` | Adds the stock Hermes / Claude Code / OpenCode integrations. | +| Also labelled `perf` | Adds hotpath parity and runs the hotpath profile, coverage, and runtime-core workflows. | | Push to `master` | Everything. | -Marking a PR ready or adding a label starts the run; a newer push cancels -the one in flight, on every branch including `master`. Closing or merging a -PR cancels its remaining runs and drops its Actions caches. Nothing runs on a +Add `ci-full` to run CI for the PR's current head. If the head changes, remove +and re-add `ci-full` to test the new commit; opening, pushing, and marking ready +create no run at all. A newer master push cancels the one in flight. Closing or +merging a PR cancels its remaining runs and drops its Actions caches. Nothing runs on a timer: the packaged-crate distribution battery and the Hawk lint are `workflow_dispatch` only.