From d70f5c14e0c1dbdc786b8e3771a16c1fcb912abe Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Sat, 29 Aug 2026 23:12:37 +0200 Subject: [PATCH] Name rust-analyzer everywhere the toolchain is installed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VS Code's rust-analyzer extension ships a server newer than 1.92.0 supports and prompts, on every window, to add one. Listing the component in rust-toolchain.toml makes rustup supply the server matching the pin — the same thing the pin buys everywhere else. The cost lands outside the editor, which is why this is four files rather than one. rustup reconciles that component list against the installed toolchain on the first cargo call in the work tree and downloads what is missing, inside whatever job happens to be running. An unasked-for fetch in the middle of a build step is nobody's line item and hard to find in a log. So every environment that builds this repo names it too: baked into the Android image, and in the install step of each CI job that rolls its own toolchain. Co-Authored-By: Claude Opus 5 --- .gitea/workflows/build-and-test.yml | 18 ++++++++++++++++-- .gitea/workflows/traceability-check.yml | 9 +++++++-- docker/android/Dockerfile | 10 +++++++++- rust-toolchain.toml | 15 ++++++++++++++- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/.gitea/workflows/build-and-test.yml b/.gitea/workflows/build-and-test.yml index 5350cd3..0945317 100644 --- a/.gitea/workflows/build-and-test.yml +++ b/.gitea/workflows/build-and-test.yml @@ -117,12 +117,20 @@ jobs: # The act image ships Node but no Rust. Pinned to the workspace # rust-version so CI, the Android image, and local builds agree — a # floating toolchain turns an unrelated push into a mystery failure. + # + # The component list mirrors rust-toolchain.toml's, rust-analyzer + # included, even though nothing in this job runs it. rustup reconciles + # that file against the installed toolchain on the first cargo call in + # the work tree and fetches whatever is missing — so leaving it out does + # not save the download, it only moves it into the middle of a build + # step where it is nobody's line item. Naming it here keeps every fetch + # inside the step whose name says it is installing things. - name: Install Rust 1.92.0 run: | set -e curl -fsSL https://sh.rustup.rs | sh -s -- \ -y --no-modify-path --profile minimal \ - --default-toolchain 1.92.0 --component rustfmt,clippy + --default-toolchain 1.92.0 --component rustfmt,clippy,rust-analyzer echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" # Free space before and after the expensive steps, so a repeat of the @@ -370,11 +378,17 @@ jobs: # `cargo tree` resolves the dependency graph, so it needs the registry # index but no system libraries — this job builds nothing. + # + # rust-analyzer is named for the reason given in the desktop job: rustup + # installs rust-toolchain.toml's components on the first cargo call + # whether or not this step asks for them, and an unasked-for download is + # the one nobody can find in the log. - name: Install Rust 1.92.0 run: | set -e curl -fsSL https://sh.rustup.rs | sh -s -- \ - -y --no-modify-path --profile minimal --default-toolchain 1.92.0 + -y --no-modify-path --profile minimal --default-toolchain 1.92.0 \ + --component rust-analyzer echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" # ARCH §6.5a: no core/ crate may depend on the UI toolkit. One stray diff --git a/.gitea/workflows/traceability-check.yml b/.gitea/workflows/traceability-check.yml index 8b37b2d..68e7ba0 100644 --- a/.gitea/workflows/traceability-check.yml +++ b/.gitea/workflows/traceability-check.yml @@ -44,12 +44,17 @@ jobs: key: traces-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }} # Source-comment and markdown parsing only, so the minimal profile is - # enough — no system libraries and no components beyond cargo itself. + # enough — no system libraries and nothing this job itself needs beyond + # cargo. rust-analyzer is here anyway because rust-toolchain.toml lists + # it: rustup installs that file's components on the first cargo call in + # the work tree regardless, and a download named in the install step + # beats the same download appearing unannounced inside the gate. - name: Install Rust 1.92.0 run: | set -e curl -fsSL https://sh.rustup.rs | sh -s -- \ - -y --no-modify-path --profile minimal --default-toolchain 1.92.0 + -y --no-modify-path --profile minimal --default-toolchain 1.92.0 \ + --component rust-analyzer echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" # The gate's own arithmetic is the thing being trusted, so its tests run diff --git a/docker/android/Dockerfile b/docker/android/Dockerfile index ca1cd62..6f6c6d3 100644 --- a/docker/android/Dockerfile +++ b/docker/android/Dockerfile @@ -118,6 +118,14 @@ ENV ANDROID_NDK_HOME=${ANDROID_HOME}/ndk/${NDK_VERSION} \ # # All four ABIs. arm64-v8a covers essentially every current device; the others # exist so an ABI-specific build break is caught here rather than at release. +# +# The component list must be a superset of rust-toolchain.toml's. rustup +# reconciles that file against the installed toolchain on the first cargo +# invocation in the work tree, and silently downloads whatever is missing — +# inside the CI job, after this image has already been pulled. Anything the +# repo asks for therefore belongs here, or the image is not the whole +# environment it claims to be. rust-analyzer is in that list for the editor's +# sake; here it costs a layer and buys a job that fetches nothing. # --------------------------------------------------------------------------- RUN curl -fsSL https://sh.rustup.rs | sh -s -- \ -y --no-modify-path --profile minimal --default-toolchain ${RUST_VERSION} \ @@ -126,7 +134,7 @@ RUN curl -fsSL https://sh.rustup.rs | sh -s -- \ armv7-linux-androideabi \ x86_64-linux-android \ i686-linux-android \ - && rustup component add rustfmt clippy \ + && rustup component add rustfmt clippy rust-analyzer \ && cargo install cargo-ndk --locked \ && chmod -R a+rwX ${CARGO_HOME} ${RUSTUP_HOME} diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 82aa8c7..2c79a60 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -17,7 +17,20 @@ # sufficient one. # # rustup reads this automatically and will fetch the toolchain on first use. +# +# `rust-analyzer` is in the component list for the editor's sake, not the +# build's. VS Code's rust-analyzer extension ships a server newer than 1.92.0 +# supports; without a component here it prompts, on every window, to add one. +# Listing it makes rustup supply the server that matches the pin, which is the +# same thing the pin buys everywhere else. +# +# Adding anything here has a cost outside the editor: rustup reconciles this +# list against the installed toolchain on the first cargo call in the work +# tree and downloads what is missing, inside whatever job is running. So every +# environment that builds this repo already carries it — baked into +# docker/android's image, and named in the install step of each CI job that +# rolls its own toolchain. Keep those in step with this line. [toolchain] channel = "1.92.0" -components = ["rustfmt", "clippy"] +components = ["rustfmt", "clippy", "rust-analyzer"]