Skip to content

ci: cache-thrash + compile-time + waste-on-failure optimizations - #120

Merged
doublegate merged 2 commits into
mainfrom
ci/workflow-optimizations
Jun 17, 2026
Merged

ci: cache-thrash + compile-time + waste-on-failure optimizations#120
doublegate merged 2 commits into
mainfrom
ci/workflow-optimizations

Conversation

@doublegate

Copy link
Copy Markdown
Owner

CI workflow optimizations — cache thrash, compile time, wasted-on-failure compute

From an exhaustive 2024–2026 best-practices research pass (rust-cache README, docs.github.com/actions, nexte.st, dorny/paths-filter, taiki-e/install-action, cargo-hack, the Rust perf-book / kobzol / corrode.dev compile-time posts, and real ripgrep/rust-analyzer/tokio workflows), reconciled against the actual ci.yml + rust-setup composite (not assumptions).

Implemented here (safe, high-ROI, zero coverage loss, no behaviour change)

# Change Why Where
1 save-if: ${{ github.ref == 'refs/heads/main' }} on the cargo cache A PR-branch cache save is scoped to that branch (no other PR can read it) yet still counts against the 10 GB repo cache budget and LRU-evicts the shared main caches every PR restores from — i.e. PR saves are write-only garbage that lower everyone's hit rate. Restore-on-PR + save-on-main removes the thrash. rust-setup/action.yml (covers all callers)
2 cache-on-failure: true on test-roms A ROM-assertion (test-stage) failure shouldn't discard the ~10-min release-mode dependency compile. rust-setup input + ci.yml
3 CARGO_PROFILE_DEV/TEST_DEBUG: line-tables-only CI builds clean, so the dev/test debug = 2 default only slows linking + bloats target/ (worse caching). line-tables-only keeps panic/backtrace file:line (failing-test diagnostics stay readable) while cutting debug compile ~20–40%. Set via CARGO_PROFILE_* (a stable cache-key contributor) — not RUSTFLAGS=-Cdebuginfo=0, which busts the rust-cache key and forces a full dep rebuild. Release profile (test-roms/bench) is unaffected (already debug = 0). ci.yml env
4 needs: lint on the 3-OS test matrix + test-roms A fmt/clippy/rustdoc slip fails in seconds — gating the two heaviest jobs on it saves the entire matrix + release-ROM compile's runner-minutes on every lint failure (the "job chain" requested). Cost: ~lint's duration of happy-path latency. ci.yml

One-time cost: the first post-merge main build does a cold cache save (#1) and a one-time recompile at the new debug level (#3); PRs are unaffected.

Confirmed already-optimal (NOT changed)

  • CARGO_INCREMENTAL=0 — rust-cache sets this automatically.
  • actions/checkout fetch-depth: 1 — already the v4/v6 default.
  • Per-job cache keys (not a shared-key) — correct here: the OS / wasm32 / thumbv7em target/ dirs are mutually incompatible, so a shared key would be ~100% miss + constant re-save.
  • sccache: skip — rust-cache (skip compile) beats it on a hit; both fight the same 10 GB pool; and sccache can't cache the bin/proc-macro/FFI-build-script crates this workspace ships.

Proposed follow-ups (left for maintainer review — some trade coverage/behaviour)

  • Coverage gap (worth doing): the scripting / scripting,hd-pack / retroachievements clippy gates CLAUDE.md mandates currently run only locally, never in CI. cargo hack clippy -p rustynes-frontend --feature-powerset --depth 2 --mutually-exclusive-features scripting,script-wasm -- -D warnings closes that on the one warm lint runner. (Adds lint time — a completeness vs speed trade.)
  • ubuntu-24.04-arm matrix legfree on this public repo (GA 2025-08), real arm64 determinism coverage at $0; parallel, so no wall-clock cost.
  • dorny/paths-filter per-job skips — skip the frontend/wasm/Pages jobs on chip-stack-only PRs (more granular than the current trigger-level paths-ignore); pair with a ci-success aggregator so skips stay safe.
  • merge_group + matrix split (maintainer decision): PRs run ubuntu-only; full macOS/Windows matrix + heavy test-roms run on the merge queue + a nightly backstop. Highest runner-minute saver (macOS 10×, Windows 2× multipliers) but trades PR-time cross-platform coverage — risky for this repo specifically (wgpu backend divergence, path separators, CRLF in .sym/golden text). Recommended with a full-ci label escape hatch.
  • cargo-nextest (maintainer decision): process-per-test isolation (good for the ROM/FFI suite) but only ~1.3–1.5× on CI's run phase (build-dominated here), and needs care: add cargo test --doc, translate #[ignore] probes, and no blanket retries (a green-on-retry would hide exactly the non-determinism the contract forbids).
  • cargo build --timings artifact to decide whether cargo-hakari workspace-hack is worth it.

🤖 Generated with Claude Code

Safe, coverage-preserving CI speedups (from an exhaustive 2024-2026 best-
practices pass, reconciled against the actual ci.yml + rust-setup):

- save-if (rust-setup): only WRITE the cargo cache from `main`. A PR-branch
  save is scoped to that branch (unreadable by other PRs) but still counts
  against the 10 GB repo budget and LRU-evicts the shared `main` caches every
  PR restores from. Restore-on-PR + save-on-main keeps the hit rate high
  without the thrash.
- CARGO_PROFILE_DEV/TEST_DEBUG = line-tables-only: CI builds clean, so the
  dev/test `debug = 2` default just slows linking + bloats target/ (worse
  caching). line-tables-only keeps panic/backtrace file:line while cutting
  debug compile ~20-40%. Set via CARGO_PROFILE_* (stable cache key), not
  RUSTFLAGS (which would bust the cache + force a dep rebuild).
- needs: lint on the two heaviest jobs (the 3-OS `test` matrix + release-mode
  `test-roms`): a fmt/clippy/rustdoc slip fails in seconds, so don't spin up
  the matrix or pay the release ROM compile until the cheap gate is green.
  ~+lint-duration happy-path latency; saves the full matrix's runner-minutes
  on every lint failure.
- cache-on-failure on test-roms: a ROM-assertion (test-stage) failure keeps
  the expensive release dependency compile cached instead of discarding it.

YAML validated. Further-gain follow-ups (arm64 runner, cargo-hack feature-combo
clippy to close the scripting/hd-pack/retroachievements CI gap, paths-filter
per-job skips, merge_group + PR-ubuntu-only matrix, cargo-nextest) are written
up in the PR for maintainer review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 17, 2026 21:50

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the Rust setup GitHub Action to support a cache-on-failure input and restricts cache saving to the default branch to prevent cache thrashing on PR branches. Feedback suggests avoiding hardcoding the default branch as 'refs/heads/main' and instead using 'github.event.repository.default_branch' to ensure compatibility with forks and repositories using different default branch names.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread .github/actions/rust-setup/action.yml Outdated
Locks in the maintainer-decided follow-ups (actionlint-clean):

- merge_group hybrid (OS matrix): a `setup` job picks the matrix by event —
  `pull_request` runs ubuntu-only (cheap, fast feedback); push-to-main, the
  merge queue, and dispatch run the full ubuntu+macOS+Windows matrix. macOS
  (10x) + Windows (2x) leave every PR push; full cross-platform coverage still
  runs pre-merge (merge_group, once the queue is enabled) and post-merge (push).
  Added the `merge_group` trigger and a `CI success` aggregator job — the single
  stable check to require in branch protection / the queue (skipped legs count
  as success, so the event-varying matrix can't block it).
  NOTE: test-roms (the AccuracyCoin gate) deliberately STILL runs on PRs — it's
  ubuntu (1x) and PR-time accuracy feedback is too valuable for this project to
  defer to the queue. One-line change if queue-only is preferred.
- Feature-combo clippy in `lint`: the `scripting` / `scripting,hd-pack` /
  `retroachievements` gates CLAUDE.md mandates previously ran ONLY locally — a
  feature-gated lint regression could land CI-green. Now run serially on the
  warm lint runner (NOT --all-features: scripting/script-wasm can't co-resolve).
- save-if: compare github.ref_name to the repo's actual default_branch instead
  of hardcoding "main" (robust on forks / renamed default; adopts the PR #120
  review comment).

REQUIRES (maintainer, one-time, in repo settings) to fully activate the queue:
enable the merge queue on `main` + add a branch-protection rule requiring the
`CI success` check. Until then the workflow is safe: PRs run ubuntu-only +
test-roms; push-to-main runs the full matrix (post-merge coverage).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@doublegate

Copy link
Copy Markdown
Owner Author

Maintainer decisions now implemented in this PR (was: proposed): merge_group OS-matrix hybrid (ubuntu-only PRs, full matrix on push/merge-queue/dispatch, CI success aggregator), targeted feature-combo clippy in lint (closes the scripting/hd-pack/retroachievements CI gap), and the dynamic-default-branch save-if. nextest landed separately as local-only dev tooling (#121).

One-time settings step to fully activate the merge queue (only you can do this): in repo Settings → Branches, add a branch-protection rule on main requiring the CI success status check, then enable the merge queue for main. Until then the workflow is safe — PRs run ubuntu + test-roms + lint, and push-to-main runs the full macOS/Windows matrix (post-merge coverage). Note I kept test-roms (AccuracyCoin) on PRs deliberately; say the word to move it queue-only.

@doublegate
doublegate merged commit 91e634e into main Jun 17, 2026
17 checks passed
@doublegate
doublegate deleted the ci/workflow-optimizations branch June 17, 2026 22:27
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.

2 participants