Skip to main content

max / alloy

image: ship the themes the console cannot start without theme.rs has no built-in palette on purpose (docs/TOKENS.md keeps hex out of Rust), so a console that finds no theme file exits rather than falling back. Its last-resort path is makeover's bundled themes, which resolve through CARGO_MANIFEST_DIR into the registry checkout inside the build stage. Only the binary was copied out of that stage, so every alloy subcommand in the image died on launch with "Theme not found" -- install, net, audio, pkg, config, all of them. The console has never run in the image it ships in. No test could catch this: theme::tests::shipped_defaults_load_and_resolve passes on a dev box because the registry checkout is right there. Take only the two Akari defaults. makeover bundles about thirty, most of them other people's palettes with attribution obligations; widening this means shipping THIRD-PARTY-NOTICES with it.
Co-Authored-By
Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-07-20 17:34 UTC
Signed with PGP, not checked
Commit: 11045f132e1811c67663af3d8ead8c6b420c8b96
Parent: 05a91de
1 file changed, +27 insertions, -0 deletions
@@ -46,6 +46,28 @@
46 46 COPY crates/ crates/
47 47 RUN cargo build --release --locked
48 48
49 + # The console's themes, staged at a path the runtime stage can name.
50 + #
51 + # theme.rs has no built-in palette on purpose (docs/TOKENS.md: no hex in
52 + # Rust), so a console with no theme file on any search path does not fall
53 + # back, it exits. Its last-resort path is makeover's bundled themes, which
54 + # resolve through CARGO_MANIFEST_DIR into the registry checkout — a build
55 + # stage that gets discarded. Only the binary was copied out, so every
56 + # `alloy` subcommand in the image failed with "Theme not found".
57 + #
58 + # Only the two Akari defaults are taken. makeover ships around thirty,
59 + # most of them other people's palettes carrying attribution obligations;
60 + # Akari is the one Alloy is entitled to call its own (docs/TOKENS.md).
61 + # Widening this means shipping THIRD-PARTY-NOTICES alongside it.
62 + #
63 + # The glob is asserted rather than trusted: silently copying nothing here
64 + # would rebuild exactly the failure this fixes.
65 + RUN set -eux; \
66 + set -- /root/.cargo/registry/src/*/makeover-*/themes; \
67 + [ "$#" -eq 1 ] && [ -d "$1" ] || { echo "expected one makeover themes dir, got: $*" >&2; exit 1; }; \
68 + mkdir -p /staged-themes; \
69 + cp -a "$1/akari-dawn.toml" "$1/akari-night.toml" /staged-themes/
70 +
49 71 # =====================================================================
50 72 # Runtime image — the bootable container itself.
51 73 # =====================================================================
@@ -320,6 +342,11 @@
320 342 # something the operator dropped in.
321 343 COPY --from=rust-build /src/target/release/alloy /usr/bin/alloy
322 344
345 + # The themes that binary refuses to run without. Kept next to it so the
346 + # two move together: shipping the console without these is not a degraded
347 + # console, it is one that exits on launch.
348 + COPY --from=rust-build /staged-themes /usr/share/alloy/themes
349 +
323 350 # =====================================================================
324 351 # bootc validation — fails the build if the image isn't a valid
325 352 # bootable container.