Skip to main content

max / alloy

Ask a build host for rustfmt, clippy and minisign Rehearsal 4 ran the publish recipe for makeover 3.2.1 inside a container from the fw13 image, twice. On the image alone `cargo fmt` and `cargo clippy` are `no such command`: Fedora's rust package carries neither and the image ships no rustup, so every crate release dies at its first gate. `cargo test` and `cargo publish --dry-run` ran green regardless, on 1.98.0 against a tree pinning 1.97.1. With rustup in $HOME the pin was honoured, its two components came with it, and every shell step of the recipe passed. So the toolchain row asks for the components as well as the channel: a --profile minimal install on the right channel still fails a release, and nothing else would say so. minisign was present by luck rather than by contract. Both Linux recipes call dist/sign-artifacts.sh and it hard-fails without it, so both .requires now state it.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session
https://claude.ai/code/session_013wvegQEzB5piwPowYQ3ZbV
Author: Max Johnson <me@maxj.phd> · 2026-09-04 20:39 UTC
Signed with PGP, not checked
Commit: d82c3e33997fe9e90c6d2f916b9f7c71ffe8fcb7
Parent: 35a55cd
4 files changed, +36 insertions, -1 deletion
@@ -364,6 +364,16 @@
364 364 # versions, which is the whole reason the pins exist, and the sweep's fmt cell
365 365 # then measures which machine formatted last.
366 366 #
367 + # Two of the three publish gates are louder than that, and only by accident:
368 + # Fedora's rust package carries neither rustfmt nor clippy, so on the fw13 image
369 + # `cargo fmt` and `cargo clippy` are `no such command` rather than the wrong
370 + # version. Measured in the rehearsal-4 run. That makes the publish recipe fail at
371 + # its first gate on a rustup-less host, which is the good outcome; `cargo test`
372 + # and `cargo publish --dry-run` both ran green there on 1.98.0, which is the bad
373 + # one. So the components are asked for separately below: rustup being installed
374 + # and on the right channel does not mean the toolchain carries them, and a
375 + # `--profile minimal` install without them fails a release rather than a build.
376 + #
367 377 # Only a build host is asked. A laptop with no tree is not failing anything by
368 378 # not having a toolchain, so the absence of either the tree or rustc is a SKIP.
369 379 pin_file="$(target_home)/Code/alloy/rust-toolchain.toml"
@@ -380,7 +390,16 @@
380 390 if [ -z "$pinned" ] || [ -z "$active" ]; then
381 391 row SKIP toolchain "could not read the pin or the active version from this output shape"
382 392 elif [ "$pinned" = "$active" ]; then
383 - row PASS toolchain "rustc $active matches the pinned channel"
393 + # The channel is right. Now the two components the publish recipe runs
394 + # before anything else, each asked for by the command that would fail.
395 + missing=""
396 + cargo fmt --version >/dev/null 2>&1 || missing="rustfmt"
397 + cargo clippy --version >/dev/null 2>&1 || missing="${missing:+$missing }clippy"
398 + if [ -n "$missing" ]; then
399 + row FAIL toolchain "rustc $active matches the pin but $missing is absent -- run: rustup component add $missing"
400 + else
401 + row PASS toolchain "rustc $active matches the pinned channel, with rustfmt and clippy"
402 + fi
384 403 elif have rustup; then
385 404 row FAIL toolchain "rustc $active, tree pins $pinned, and rustup is installed -- run: rustup toolchain install $pinned"
386 405 else
@@ -333,6 +333,13 @@
333 333 - Runtime interactions. linuxdeploy bundling a binutils that cannot read Fedora
334 334 43's `.relr.dyn` sections is the example, and no static check finds it. What
335 335 `guards` catches is that workaround being *lost*, which is how it was.
336 + - Anything a role needs that lives in `$HOME` rather than in the image. The
337 + publish role is the measured case: Fedora's `rust` carries neither rustfmt nor
338 + clippy and the image declines rustup, so `cargo fmt` and `cargo clippy` are
339 + `no such command` on a clean mint and every crate release fails at its first
340 + gate. That is not a finding this file can make -- the image is correct -- so it
341 + is `build/check-host.sh`'s `toolchain` row, which asks an installed machine for
342 + the pinned channel and for those two components.
336 343
337 344 ## The answer sheet
338 345
@@ -36,3 +36,7 @@
36 36 # without it cannot collect a build from another host or hand a release over.
37 37 bin:rsync
38 38 bin:ssh
39 +
40 + # --- release signing. Same as fw13: dist/sign-artifacts.sh hard-fails without
41 + # minisign, and an arm64 release is signed on the host that built it.
42 + bin:minisign
@@ -47,3 +47,8 @@
47 47 # without it cannot collect a build from another host or hand a release over.
48 48 bin:rsync
49 49 bin:ssh
50 +
51 + # --- release signing. Both Linux recipes call dist/sign-artifacts.sh, which
52 + # hard-fails without minisign, and the key material is a $HOME restore rather
53 + # than image content — so the binary is the part an image can be asked for.
54 + bin:minisign