From a7535923a14022d5510e8504d551b8209bdbd7cd Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Fri, 18 Sep 2026 07:27:00 +0000 Subject: [PATCH] ci: run no job at all on draft pull requests Even three light gates per draft is too much when a swarm opens 130 drafts in ten minutes: 113 CI runs queued ahead of the release publish and the release-please refresh. A skipped job costs no runner, and every guarded job reads scope-gate's outputs, so skipping scope-gate on a draft skips the run. Marking the PR ready or adding ci-full still runs everything it earned. --- .github/workflows/ci.yml | 11 ++++++++--- CONTRIBUTING.md | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90f7dd0882..dbb27aab6b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,9 +40,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 gets the light gates (this job, commit lint, drift, harness) - # and nothing else: with 20 free runner slots, a swarm of drafts each - # spending ~30 jobs per push queued the integration branch for hours. + # A draft runs no job at all (see the `if` below). # * `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 @@ -54,6 +52,11 @@ jobs: # hotpath profile/coverage workflows. scope-gate: name: Scope gate + # A draft runs nothing at all. A swarm opened 130 drafts in ten minutes + # 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') }} runs-on: ubuntu-latest timeout-minutes: 5 permissions: @@ -239,6 +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') }} runs-on: ubuntu-latest timeout-minutes: 10 steps: @@ -256,6 +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') }} runs-on: ubuntu-latest timeout-minutes: 15 steps: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 335bbcd2a0..30c3cbeed4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -257,8 +257,8 @@ integration branch waits behind, so a run spends only what its state earns: | State | Runs | |---|---| -| Draft | Light gates only: scope gate, repository gates (commit lint, release guards, rustfmt), benchmark-harness self-tests. | -| Ready for review (or labelled `ci-full`) | The Linux lane: build, clippy, feature gates, dashboard, Linux test partitions, PR dogfood with the MCP conformance smoke. | +| 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. |