2828 RUSTFLAGS : " -D warnings"
2929
3030jobs :
31+ # Gate the compile-heavy Rust jobs so artifact/docs-only PRs stop running the
32+ # full matrix and saturating the shared self-hosted pool. Pure `git diff` — no
33+ # third-party action, so the supply chain stays auditable. On push/main,
34+ # schedule and workflow_dispatch the filter always reports rust=true, so a
35+ # merge or the nightly run still exercises everything. Content-validating jobs
36+ # (traceability = `rivet validate`, docs-check, yaml-lint) are deliberately
37+ # NOT gated on this — they must run on artifact/doc PRs.
38+ changes :
39+ name : Detect changed areas
40+ runs-on : [self-hosted, linux, x64, light]
41+ outputs :
42+ rust : ${{ steps.filter.outputs.rust }}
43+ steps :
44+ - uses : actions/checkout@v6
45+ with :
46+ fetch-depth : 0
47+ - id : filter
48+ run : |
49+ if [ "${{ github.event_name }}" != "pull_request" ]; then
50+ echo "rust=true" >> "$GITHUB_OUTPUT"
51+ echo "non-PR event (${{ github.event_name }}) → full matrix"
52+ exit 0
53+ fi
54+ base="${{ github.event.pull_request.base.sha }}"
55+ changed="$(git diff --name-only "$base"...HEAD)"
56+ echo "changed files:"; echo "$changed"
57+ if echo "$changed" | grep -qE '(\.rs$)|((^|/)Cargo\.(toml|lock)$)|(^\.github/workflows/)'; then
58+ echo "rust=true" >> "$GITHUB_OUTPUT"
59+ echo "→ Rust/Cargo/workflow changes present; running full matrix"
60+ else
61+ echo "rust=false" >> "$GITHUB_OUTPUT"
62+ echo "→ no Rust/Cargo/workflow changes; skipping compile-heavy jobs"
63+ fi
64+
3165 # ── Fast checks ───────────────────────────────────────────────────────
3266 fmt :
3367 name : Format
68+ needs : changes
69+ if : needs.changes.outputs.rust == 'true'
3470 runs-on : [self-hosted, linux, x64, light]
3571 steps :
3672 - uses : actions/checkout@v6
4177
4278 clippy :
4379 name : Clippy
80+ needs : changes
81+ if : needs.changes.outputs.rust == 'true'
4482 runs-on : [self-hosted, linux, x64, rust-cpu]
4583 steps :
4684 - uses : actions/checkout@v6
@@ -154,6 +192,8 @@ jobs:
154192 # ── Tests ─────────────────────────────────────────────────────────────
155193 test :
156194 name : Test
195+ needs : changes
196+ if : needs.changes.outputs.rust == 'true'
157197 runs-on : [self-hosted, linux, x64, rust-cpu]
158198 env :
159199 RIVET_ACTIONLINT : " 1"
@@ -338,6 +378,8 @@ jobs:
338378 # Renamed: skipping advisories until smithy ships an upgraded
339379 # rustsec parser (see audit job comment). Same workaround as spar.
340380 name : Cargo Deny (licenses, bans, sources)
381+ needs : changes
382+ if : needs.changes.outputs.rust == 'true'
341383 runs-on : [self-hosted, linux, x64, light]
342384 steps :
343385 - uses : actions/checkout@v6
@@ -363,7 +405,8 @@ jobs:
363405 # escape to a release.
364406 semver-checks :
365407 name : Semver Checks (rivet-core public API)
366- if : github.event_name == 'pull_request'
408+ needs : changes
409+ if : github.event_name == 'pull_request' && needs.changes.outputs.rust == 'true'
367410 runs-on : [self-hosted, linux, x64, rust-cpu]
368411 steps :
369412 - uses : actions/checkout@v6
@@ -384,7 +427,8 @@ jobs:
384427 # ── Code coverage (Rust nightly for source-based instrumentation) ───
385428 coverage :
386429 name : Code Coverage
387- needs : [test]
430+ needs : [changes, test]
431+ if : needs.changes.outputs.rust == 'true'
388432 runs-on : [self-hosted, linux, x64, rust-cpu]
389433 steps :
390434 - uses : actions/checkout@v6
@@ -424,7 +468,8 @@ jobs:
424468 # (sexpr + yaml_cst); the FULL sweep runs nightly (miri-full, #498 pattern).
425469 miri :
426470 name : Miri (safety surface)
427- if : github.event_name != 'schedule'
471+ needs : changes
472+ if : github.event_name != 'schedule' && needs.changes.outputs.rust == 'true'
428473 runs-on : [self-hosted, linux, x64, lean-mem]
429474 steps :
430475 - uses : actions/checkout@v6
@@ -483,6 +528,8 @@ jobs:
483528 # ── Property-based testing (extended) ───────────────────────────────
484529 proptest :
485530 name : Proptest (extended)
531+ needs : changes
532+ if : needs.changes.outputs.rust == 'true'
486533 runs-on : [self-hosted, linux, x64, rust-cpu]
487534 steps :
488535 - uses : actions/checkout@v6
@@ -626,7 +673,8 @@ jobs:
626673 # RAM-bound gating jobs (Miri, Verus) and the nightly mutants-core fan-out.
627674 mutants-cli :
628675 name : Mutation Testing (rivet-cli)
629- needs : [test]
676+ needs : [changes, test]
677+ if : needs.changes.outputs.rust == 'true'
630678 runs-on : [self-hosted, linux, x64, rust-cpu]
631679 timeout-minutes : 45
632680 steps :
@@ -703,6 +751,8 @@ jobs:
703751 # ── Supply chain verification ───────────────────────────────────────
704752 supply-chain :
705753 name : Supply Chain (cargo-vet)
754+ needs : changes
755+ if : needs.changes.outputs.rust == 'true'
706756 runs-on : [self-hosted, linux, x64, light]
707757 timeout-minutes : 10
708758 steps :
@@ -866,6 +916,8 @@ jobs:
866916 # ── MSRV check ──────────────────────────────────────────────────────
867917 msrv :
868918 name : MSRV (1.89)
919+ needs : changes
920+ if : needs.changes.outputs.rust == 'true'
869921 runs-on : [self-hosted, linux, x64, rust-cpu]
870922 steps :
871923 - uses : actions/checkout@v6
0 commit comments