ci: bake the runner-build toolchain into a prepared image (prepare adoption) #44
ci/prepare-multiarch-release
into main
Delivers pillar 1 of the prepare epic (fangorn/anvil#354 → fangorn/anvil-cli#43): anvil-cli’s own release build now uses Anvil’s headline prepare feature.
Why
build-runner took ~1860s, of which ~1750s was re-acquiring a toolchain every run — downloading zig, compiling cargo-zigbuild from source (~130 crates), fetching the macOS SDK, adding four rustup targets. The four cross-compiles are ~110s. That re-acquisition is also what pushed the job past its 1800s timeout and shipped release 2026.07.6 with half its assets missing (#40).
What
- Toolchain → step-level
prepare. Baked into a cached image once, reused across runs.ci/build-runner.shdrops to build + verify + publish. Version pins move into the.anvil.ymlprepare commands, because the prepared-image cache key hashes those strings — a bump in the script wouldn’t invalidate the image (the correctness constraint I flagged). - Atomic publish (#40). Create the release as a
--draft, upload all five assets, thenrelease publish. Confirmed server-side:latest_release()filtersdraft: false, so/runner/versionnever serves a draft — a mid-upload failure leaves an invisible draft, not a broken public release. prepare removing the timeout is the primary fix; the draft is the backstop. - Delete the
cache:blocks.cacheis validated but does nothing (fangorn/anvil#358); the six blocks cached nothing and misrepresented the pipeline.
Deferred to a follow-up (blocked on deploy)
The same-ISA multi-arch split — one linux/arm64 + one linux/amd64 runner, each building its own ISA to avoid slow cross-ISA ring codegen — is the other half of #43. It needs the affinity fix (fangorn/anvil#209 / #361) deployed first: two per-ISA jobs on the current server would deadlock, since affinity pins the whole run to one worker and the other arch’s job hangs. Shipping it now would hang this repo’s CI.
Validation note
The first CI run on this branch builds the prepared image (~25 min, once); subsequent runs are fast. I can’t build the prepared image locally (no Docker, 25-min build) — CI on this PR is the first real exercise of the prepare commands. They are the same install steps ci/build-runner.sh ran before, relocated verbatim with pins intact, so the risk is low, but watch the first run.