Skip to content

Pin the Rust toolchain so a new compiler arrives as a pull request - #273

Merged
JacobStephens2 merged 4 commits into
mainfrom
issue-270
Oct 1, 2026
Merged

JacobStephens2 merged 4 commits into
mainfrom
issue-270

Conversation

@JacobStephens2

@JacobStephens2 JacobStephens2 commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner

Summary

Closes #270

One file names the Rust version; everything that builds the crate reads it through rustup.

 /
+├── rust-toolchain.toml          # channel = "1.99.0", rustfmt, clippy: the only place the version is named
 ├── .github/
+│   ├── dependabot.yml           # opens the pull request that moves the pin (weekly check)
 │   └── workflows/
 │       ├── ci.yml               # test, test-macos:
-│       │                        #   uses: dtolnay/rust-toolchain@stable
+│       │                        #   run: rustup toolchain install   (no argument: installs what the file names)
 │       ├── publish-crates.yml   # same swap
 │       ├── release-smoke.yml    # a pull request that changes the pin also runs the Rocky and WSL checks
 │       └── release.yml          # generated by dist, untouched: see "The release workflow" below
 ├── README.md                    # "The Rust version": what the pin covers and how to move it
 └── tests/
+    ├── toolchain.rs             # the pin is exact, names rustfmt and clippy; no workflow installs a floating toolchain
     └── packaging.rs             # + the crates.io package leaves the toolchain file out

Update bot. Dependabot's rust-toolchain ecosystem updates channel = "1.xx.yy" in rust-toolchain.toml (GitHub's supported ecosystems reference, checked 2026-10-01). It can't be seen working until dependabot.yml is on main, so the README documents the manual bump as well.

Seams tested. The toolchain file at the repository root, the workflow files under .github/workflows/, and cargo package --list.

Evidence

  • Before: cargo test --test toolchain on main's workflows, with no toolchain file:

    test no_workflow_installs_a_floating_toolchain ... FAILED
      .github/workflows/publish-crates.yml:54:       - uses: dtolnay/rust-toolchain@stable
    test the_toolchain_file_names_an_exact_version ... FAILED
      could not read rust-toolchain.toml: Os { code: 2, kind: NotFound, .. }
    test the_toolchain_file_names_rustfmt_and_clippy ... FAILED
    

    After: all three pass, with package_leaves_out_the_toolchain_pin in tests/packaging.rs. Locally on 1.99.0, cargo fmt --check and cargo clippy --all-targets -- -D warnings are clean and cargo test passes in full (30 test binaries, 0 failed).

  • CI's logs, test and test-macos (run 36881322043):

    test        info: the active toolchain `1.99.0-x86_64-unknown-linux-gnu` has been installed
                rustc 1.99.0 (b940084d7 2026-09-28)
    test-macos  info: the active toolchain `1.99.0-aarch64-apple-darwin` has been installed
                rustc 1.99.0 (b940084d7 2026-09-28)
    

    cargo fmt --check and cargo clippy --all-targets -- -D warnings pass in test on 1.99.0.

The release workflow

release.yml installs no toolchain of its own: it runs cargo through the runner image's rustup, which now reads rust-toolchain.toml and installs the pin. Until now it built with whatever Rust the runner image carried, which was not the version CI tested with.

  • Before: the plan job of the release workflow on another open pull request, started the same hour (run 36881615905): "cargo_version_line": "cargo 1.98.1 (797e8a9bc 2026-08-05)", while CI on the same branches ran 1.99.0.
    After: this pull request's plan job (run 36881322620): "cargo_version_line": "cargo 1.99.0 (5f94df478 2026-08-27)". In both build-local-artifacts jobs the cache action reports 1.99.0 for the checkout beside the image's 1.98.1, and dist adds the x86_64-unknown-linux-musl target to the pinned toolchain (running rustup to ensure you have x86_64-unknown-linux-musl installed, info: downloading component rust-std).
  • Both builds pass, and so do the Rocky Linux 9 and WSL checks on the musl binary built with 1.99.0, which ran because this pull request touches release-smoke.yml.

CI notes

Merge Danger

Door: two-way

Reverting the commit puts the workflows back on floating stable.

Blast Radius: build

  • A contributor's cargo in a checkout now downloads 1.99.0 through rustup the first time, whatever their default toolchain is. A Rust installed without rustup ignores the file.
  • CI no longer picks up a new Rust on its own: main stays on 1.99.0 until a pull request moves the pin.
  • Dependabot starts opening pull requests on this repository, one per stable Rust release.
  • cargo install thirdshift is unchanged: the file is not in the package.

Unaddressed findings

Standards

  • The install step is written three times (ci.yml twice, publish-crates.yml): sharing two lines of shell needs a composite action, which is more to maintain than the duplication, and no_workflow_installs_a_floating_toolchain guards the three copies.
  • repository() in tests/toolchain.rs has the same body as manifest_dir() in tests/release.rs: each test file keeps its own small path helper here (site() in share_card.rs), and repository() says what these tests read.
  • The floating-toolchain check works line by line, so it would miss a toolchain named on a continuation line: it now catches any toolchain action, not only dtolnay's, and a full shell parse is more than a guard test needs.
  • Eight files change for one decision: inherent to the change; the version itself is in one place.

Spec

  • CI green on the pinned version: see "CI notes" below.
  • rust-toolchain.toml added to the release smoke tests' path filter, which the issue didn't ask for: kept, because a new compiler changes the musl binary the Rocky and WSL checks exist to test, and otherwise the first run on it would be the tag push.
  • profile = "minimal", which the issue didn't ask for: kept, because it is what dtolnay/rust-toolchain installed before; without it every CI job would also download rust-docs.
  • The generated release.yml still has a sh.rustup.rs install step: it runs only for a container build, there is none configured, and the file is generated by dist.

🤖 Generated with Claude Code

JacobStephens2 and others added 2 commits October 1, 2026 14:57
CI and the crates.io publish installed floating stable, so a Rust release
changed what main and every open pull request built with at once. The
repository now names one exact version, 1.99.0, with rustfmt and clippy, and
the workflows install what the file names instead of a channel. Dependabot
opens the pull request that moves the pin, and the README says how to move
it by hand.

The release smoke tests also run on a pull request that changes the pin,
since it changes the compiler the release binaries are built with.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… action, drop the version from prose

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JacobStephens2
JacobStephens2 merged commit c0f427d into main Oct 1, 2026
13 checks passed
@JacobStephens2
JacobStephens2 deleted the issue-270 branch October 1, 2026 16:19
@JacobStephens2 JacobStephens2 mentioned this pull request Oct 2, 2026
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.

Pin the Rust toolchain so a new compiler arrives as a pull request

1 participant