Skip to content

chore: pin the exact nightly toolchain used for rustfmt - #681

Open
varex83agent wants to merge 1 commit into
mainfrom
chore/pin-nightly-rustfmt
Open

chore: pin the exact nightly toolchain used for rustfmt#681
varex83agent wants to merge 1 commit into
mainfrom
chore/pin-nightly-rustfmt

Conversation

@varex83agent

Copy link
Copy Markdown
Collaborator

Problem

Formatting runs via cargo +nightly fmt, which resolves to whatever nightly happens to be installed in each environment. A newly released nightly can silently change formatting output and break the cargo +nightly fmt --all -- --check gate in CI — with no change to our code.

The float was happening in four independent places, each resolving nightly on its own: CI (rustup +nightly), the git pre-push hook, the Claude formatting hook, and the Nix dev shell (selectLatestNightlyWith).

Fix

Add rustfmt-toolchain as a single source of truth:

nightly-2026-08-30

2026-08-30 is the nightly the tree is currently formatted with — verified that cargo +nightly-2026-08-30 fmt --all --check reports zero diffs, so this pin causes no reformatting churn.

Every consumer now reads that file:

File Change
.github/workflows/linter.yml Read the pin, install + run that dated toolchain; add rustfmt-toolchain to path triggers
.githooks/pre-push Use the pinned toolchain under rustup; keep wrapped cargo +nightly fmt under Nix
.claude/hooks/check-formatting.sh Same, and auto-installs the pinned toolchain if missing
flake.nix Pin dev-shell rustfmt to the same date instead of selectLatestNightlyWith
AGENTS.md Document the pin

The Nix subtlety

The Nix dev shell has no rustup — it wraps cargo +nightly fmt via a shell script. So the scripts detect that wrapper (command -v cargo-+nightly) and keep using cargo +nightly fmt there (pinned by the flake), while rustup/CI use the dated toolchain name. Both resolve to the same nightly.

Bumping later

Edit the single line in rustfmt-toolchain, run cargo fmt with the new nightly, commit.

Testing

  • ✅ Both shell scripts pass bash -n; the Claude hook runs and verifies the tree clean with the pinned toolchain.
  • ✅ Confirmed bare +nightly (rustfmt build 9085017724) differs from the pinned build (fd7ed57dfd) — the drift is real and now controlled.
  • ⚠️ flake.nix not evaluated locally (no nix available). On first nix develop, if rust-overlay doesn't know the pinned date, run nix flake update rust-overlay (noted in a comment in the flake).

🤖 Generated with Claude Code

`cargo +nightly fmt` floated to whatever nightly happened to be installed,
so a newly released nightly could silently change formatting and break the
`--check` gate in CI.

Introduce `rustfmt-toolchain` as a single source of truth
(`nightly-2026-08-30`, the nightly the tree is currently formatted with) and
have every consumer read it:

- .github/workflows/linter.yml: install and run the pinned dated toolchain;
  add `rustfmt-toolchain` to the path triggers.
- .githooks/pre-push and .claude/hooks/check-formatting.sh: use the pinned
  toolchain under rustup, keep the wrapped `cargo +nightly fmt` under Nix.
- flake.nix: pin the dev-shell rustfmt to the same date instead of
  `selectLatestNightlyWith`.
- AGENTS.md: document the pin.

Bump the version by editing the single `rustfmt-toolchain` file.

Co-Authored-By: Bohdan Ohorodnii <35969035+varex83@users.noreply.github.com>

@emlautarom1 emlautarom1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It kind of works but:

  • Running the formatting from the terminal is non standard: cargo fmt is incorrect, cargo +nightly fmt is also incorrect, you need to know the specific version to use resulting in cargo +"$(cat rustfmt-toolchain)" fmt incantations.
  • On this, the PR updated docs are incorrect.
  • Editors won't immediately know how to format - the command to use is non-standard.
  • Nix users can use cargo +nightly fmt, but that is due to a hack and unexpected in many ways.

If we go this route we need a wrapper script that runs the specific formatter so it's consistent across all environments (rustup, CI, Nix, etc) with no intervention (the suggested example project uses a wrapper over cargo itself)

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