Files
ironclaw/rust-toolchain.toml
Henry Park cfb3761aa0 fix(ci): migrate the release lane onto the composite and unbreak two guards
An approach re-audit and a multi-agent code review both rejected the previous
round's work. Three real defects, all in code added by this PR.

1. The "accepted exception" was unjustified. The claim was that cargo-dist
   regenerates ironclaw-release.yml wholesale, so its `curl sh.rustup.rs`
   bootstrap could not be migrated. The repo contradicts that four ways:
   `allow-dirty = ["ci"]` exists precisely so hand-edits survive regeneration
   (.github/workflows/README.md documents it for the permission hardening);
   two other hand-added steps already live in that job; cargo-dist exposes
   `github-build-setup` (already used for Node/pnpm in
   .github/dist-build-setup.yml) as the durable seam for exactly this; and
   `actions/checkout` and `setup-python` already run via `uses:` in that same
   container job, so a composite call is not structurally precluded.

   The bootstrap now lives in .github/dist-build-setup.yml as a
   `uses: ./.github/actions/setup-rust` call, re-included on every
   regeneration, keeping the previous step's `if: ${{ matrix.container }}`
   condition so release behaviour is unchanged. ACCEPTED_RUST_BOOTSTRAPS is
   empty: no lane is exempt, and the prose in AGENTS.md and
   rust-toolchain.toml states that without carve-outs because it is now true.

2. The workflow-level RUSTFLAGS check was dead code. JOB_HEADING matches any
   two-space `key:` line, so `on:`'s children (`push:`, `workflow_call:`)
   matched and headings[0] truncated the preamble at the first TRIGGER —
   before the real top-level `env:`. Verified on the live reborn-tests.yml:
   first match was `workflow_call` at offset 26, `jobs:` at 3177. Headings are
   now bounded to the `jobs:` block. The old unit test passed only because its
   fixture omitted `on:`; the new one carries a realistic trigger block.

3. The per-job check was blind to YAML aliases. release-plz.yml's
   `release-plz-pr` reaches the composite via `- *install-rust` and contains
   no literal `uses:` line, so the scan skipped it — a job-level RUSTFLAGS
   there would have shadowed mold silently. Anchors carrying the composite are
   now resolved and aliased jobs are checked.

Also broadens the bootstrap guard beyond three rustup literals to known
third-party toolchain actions (actions-rs, actions-rust-lang, hecrj, raftario),
after the coverage lane showed the enumeration was trivially evadable. The one
case text cannot see — a `container:` image shipping Rust preinstalled — is
named in a comment as residual risk rather than papered over.

Proven against the real files that defeated the old guards: a workflow-level
RUSTFLAGS injected into reborn-tests.yml is now caught; a job-level RUSTFLAGS
in release-plz.yml's alias-reached job is now caught; both were silent before.
Also removes an orphaned comment left describing the deleted INPUT_HEADING.

Verified: ws12 self-tests 123 OK, ws12 live gate passed, planner suite 88 OK,
check-guidance OK, both changed workflows parse.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 04:18:12 +00:00

25 lines
1.4 KiB
TOML

# Single source of truth for the Rust toolchain, local and CI.
# - Every in-repo cargo/rustc run resolves this file (rustup precedence:
# RUSTUP_TOOLCHAIN env > directory override > this file > rustup default),
# so local clippy/rustfmt finally match CI's.
# - CI workflows install Rust through
# .github/actions/setup-rust, whose `toolchain` input defaults to the same
# version as `channel` below (kept in sync by
# scripts/ci/ws12_workflow_contracts.py); a lane that intentionally runs a
# different toolchain (the two nightly-2025-11-01 coverage lanes) passes
# an explicit `toolchain:` input, and the composite exports
# RUSTUP_TOOLCHAIN naming exactly what it installed either way, so this
# file can never silently override a job's chosen toolchain.
# - The cargo-dist release workflow is covered through
# .github/dist-build-setup.yml, which cargo-dist re-includes on every
# regeneration, so no lane installs Rust outside the composite.
# - Bumping: change `channel` here AND the `toolchain` input default in
# .github/actions/setup-rust/action.yml in the same PR (the ws12 gate
# fails on any mismatch). Expect Swatinem/rust-cache keys to rotate with
# the compiler version.
# - Docker builds are unaffected: the Dockerfile COPYs an explicit path list
# that excludes this file and stays on its base-image toolchain.
[toolchain]
channel = "1.98.0"
components = ["clippy", "rustfmt"]