| 27 |
27 |
|
# committed rather than whatever resolves that day.
|
| 28 |
28 |
|
FROM quay.io/fedora/fedora:43 AS rust-build
|
| 29 |
29 |
|
|
| 30 |
|
- |
# python3 for tools/vtrgb.py, which renders the greeter's console palette from
|
| 31 |
|
- |
# the theme file below. It is in the base already; naming it keeps the palette
|
| 32 |
|
- |
# step from breaking silently if a future base drops it. This stage is
|
| 33 |
|
- |
# discarded, so the cost is nil.
|
| 34 |
|
- |
RUN dnf install -y cargo rust python3 && dnf clean all
|
|
30 |
+ |
# No python3 any more. It was here for tools/vtrgb.py, which rendered the
|
|
31 |
+ |
# greeter's console palette; skelgen emits that table now, along with the rest
|
|
32 |
+ |
# of the desktop skeleton, so there is one implementation of the ANSI mapping
|
|
33 |
+ |
# instead of three.
|
|
34 |
+ |
RUN dnf install -y cargo rust && dnf clean all
|
| 35 |
35 |
|
|
| 36 |
36 |
|
WORKDIR /src
|
| 37 |
37 |
|
|
| 38 |
38 |
|
# The dependency graph first, against a stub main. Without this split
|
| 39 |
39 |
|
# every console edit re-downloads and rebuilds every crate underneath it,
|
| 40 |
40 |
|
# and the console is the part of this image that changes most often.
|
|
41 |
+ |
#
|
|
42 |
+ |
# Both workspace members are named, or cargo cannot resolve the workspace and
|
|
43 |
+ |
# the whole split silently degrades to a full rebuild every time.
|
| 41 |
44 |
|
COPY Cargo.toml Cargo.lock ./
|
| 42 |
45 |
|
COPY crates/alloy/Cargo.toml crates/alloy/Cargo.toml
|
| 43 |
|
- |
RUN mkdir -p crates/alloy/src \
|
|
46 |
+ |
COPY crates/skelgen/Cargo.toml crates/skelgen/Cargo.toml
|
|
47 |
+ |
RUN mkdir -p crates/alloy/src crates/skelgen/src \
|
| 44 |
48 |
|
&& echo 'fn main() {}' > crates/alloy/src/main.rs \
|
|
49 |
+ |
&& echo 'fn main() {}' > crates/skelgen/src/main.rs \
|
| 45 |
50 |
|
&& cargo build --release --locked \
|
| 46 |
51 |
|
&& rm -rf target/release/alloy target/release/deps/alloy-* \
|
| 47 |
|
- |
target/release/.fingerprint/alloy-*
|
|
52 |
+ |
target/release/.fingerprint/alloy-* \
|
|
53 |
+ |
target/release/alloy-skelgen target/release/deps/alloy_skelgen-* \
|
|
54 |
+ |
target/release/deps/skelgen-* target/release/.fingerprint/skelgen-*
|
| 48 |
55 |
|
|
| 49 |
56 |
|
# Then the real source. The removals above are what make cargo rebuild
|
| 50 |
57 |
|
# the binary rather than find the stub's artifact already in place.
|
| 68 |
75 |
|
RUN /src/target/release/alloy --version | grep -q '^alloy ' \
|
| 69 |
76 |
|
|| { echo "built console is the stub; the cache-split cleanup matched nothing" >&2; exit 1; }
|
| 70 |
77 |
|
|
|
78 |
+ |
# skelgen gets the same assertion for the same reason. Its stub would exit 0
|
|
79 |
+ |
# having written nothing, and `--help` is the one thing clap gives the real
|
|
80 |
+ |
# binary and not `fn main() {}`.
|
|
81 |
+ |
RUN /src/target/release/alloy-skelgen --help | grep -q -- '--templates' \
|
|
82 |
+ |
|| { echo "built skelgen is the stub; the cache-split cleanup matched nothing" >&2; exit 1; }
|
|
83 |
+ |
|
| 71 |
84 |
|
# The console's themes, staged at a path the runtime stage can name.
|
| 72 |
85 |
|
#
|
| 73 |
86 |
|
# theme.rs has no built-in palette on purpose (docs/TOKENS.md: no hex in
|
| 90 |
103 |
|
mkdir -p /staged-themes; \
|
| 91 |
104 |
|
cp -a "$1/akari-dawn.toml" "$1/akari-night.toml" /staged-themes/
|
| 92 |
105 |
|
|
| 93 |
|
- |
# The greeter's console palette, derived from the default light theme.
|
|
106 |
+ |
# The desktop skeleton, rendered from the two staged themes.
|
| 94 |
107 |
|
#
|
| 95 |
|
- |
# tuigreet runs on VT1, a raw Linux console with no terminal emulator under it,
|
| 96 |
|
- |
# and can only name ANSI colors. alloy-vtrgb.service applies this table with
|
| 97 |
|
- |
# setvtrgb at boot so those names land on Akari's tones (see the unit for the
|
| 98 |
|
- |
# mechanism). The table is a pure function of akari-dawn.toml, so it is
|
| 99 |
|
- |
# generated here, not committed (CLAUDE.md: never store regenerables).
|
|
108 |
+ |
# Everything in the image that carries a color — GTK, sway, yazi, helix, rio,
|
|
109 |
+ |
# zathura, the greeter's console palette, the kernel's own vt.default_* table —
|
|
110 |
+ |
# comes out of this one step. The templates hold structure and token names; the
|
|
111 |
+ |
# theme files hold the colors. Nothing here is committed, because it is a pure
|
|
112 |
+ |
# function of the two (CLAUDE.md: never store regenerables).
|
| 100 |
113 |
|
#
|
| 101 |
|
- |
# Asserted three lines of sixteen values, for the same reason the theme glob
|
| 102 |
|
- |
# above is asserted: generating nothing would ship the greeter back on the
|
| 103 |
|
- |
# stock console palette without a word.
|
| 104 |
|
- |
COPY tools/vtrgb.py /src/tools/vtrgb.py
|
|
114 |
+ |
# This replaces about four hundred hex literals that were transcribed by hand
|
|
115 |
+ |
# across seventeen files, three of which held their own copy of the ANSI slot
|
|
116 |
+ |
# mapping and no two of which agreed.
|
|
117 |
+ |
#
|
|
118 |
+ |
# skelgen fails the build on an unknown token or an empty render, so the
|
|
119 |
+ |
# assertions the vtrgb and theme-glob steps needed are inside it. The one worth
|
|
120 |
+ |
# keeping outside is the count: a template tree that silently matched nothing
|
|
121 |
+ |
# would copy an empty overlay and every program in the image would fall back to
|
|
122 |
+ |
# its own defaults, with the build log saying nothing at all.
|
|
123 |
+ |
COPY templates/ /src/templates/
|
| 105 |
124 |
|
RUN set -eux; \
|
| 106 |
|
- |
set -- /root/.cargo/registry/src/*/makeover-*/themes; \
|
| 107 |
|
- |
mkdir -p /staged-vtrgb; \
|
| 108 |
|
- |
python3 /src/tools/vtrgb.py "$1/akari-dawn.toml" > /staged-vtrgb/vtrgb; \
|
| 109 |
|
- |
awk 'NF != 16 { exit 1 } END { if (NR != 3) exit 1 }' /staged-vtrgb/vtrgb
|
|
125 |
+ |
/src/target/release/alloy-skelgen \
|
|
126 |
+ |
--templates /src/templates \
|
|
127 |
+ |
--out /staged-skel \
|
|
128 |
+ |
--theme default=/staged-themes/akari-dawn.toml \
|
|
129 |
+ |
--theme night=/staged-themes/akari-night.toml; \
|
|
130 |
+ |
[ "$(find /staged-skel -type f | wc -l)" -ge 17 ] \
|
|
131 |
+ |
|| { echo "skelgen produced fewer files than the tree has templates" >&2; exit 1; }; \
|
|
132 |
+ |
awk 'NF != 16 { exit 1 } END { if (NR != 3) exit 1 }' /staged-skel/usr/share/alloy/vtrgb
|
| 110 |
133 |
|
|
| 111 |
134 |
|
# =====================================================================
|
| 112 |
135 |
|
# Runtime image — the bootable container itself.
|
| 549 |
572 |
|
# etc/skel/.mozilla/ (Firefox first-launch profile seed); system-
|
| 550 |
573 |
|
# wide config under etc/; Firefox autoconfig + mozilla.cfg under
|
| 551 |
574 |
|
# usr/lib64/firefox/. See docs/IMAGE.md for the layout.
|
|
575 |
+ |
#
|
|
576 |
+ |
# Two sources, in this order. The repo tree is everything whose content is
|
|
577 |
+ |
# fixed; the rendered tree is everything that carries a color, which is not in
|
|
578 |
+ |
# the repo at all — templates/ holds those files with their palette left as
|
|
579 |
+ |
# tokens. The generated tree mirrors `/` the same way, so it lands by the same
|
|
580 |
+ |
# 1:1 rule and simply completes the tree rather than patching it: no file
|
|
581 |
+ |
# appears in both, and a stale copy of a themed file cannot shadow its
|
|
582 |
+ |
# generated version because there is no copy to go stale.
|
| 552 |
583 |
|
# =====================================================================
|
| 553 |
584 |
|
COPY etc/ /etc/
|
| 554 |
585 |
|
COPY usr/ /usr/
|
|
586 |
+ |
COPY --from=rust-build /staged-skel/ /
|
| 555 |
587 |
|
|
| 556 |
588 |
|
# =====================================================================
|
| 557 |
589 |
|
# polkit rules — assert the grant is not inert.
|
| 742 |
774 |
|
# console, it is one that exits on launch.
|
| 743 |
775 |
|
COPY --from=rust-build /staged-themes /usr/share/alloy/themes
|
| 744 |
776 |
|
|
| 745 |
|
- |
# The greeter's console palette (generated in the build stage) and the tool
|
| 746 |
|
- |
# that applies it. alloy-vtrgb.service reads the table; setvtrgb ships in kbd,
|
| 747 |
|
- |
# which systemd's vconsole setup already pulls in. Assert it here rather than
|
| 748 |
|
- |
# let the unit's ConditionPathExists turn a missing binary into a silent
|
| 749 |
|
- |
# no-op that drops the greeter back to the stock console palette.
|
| 750 |
|
- |
COPY --from=rust-build /staged-vtrgb/vtrgb /usr/share/alloy/vtrgb
|
|
777 |
+ |
# The tool that applies the greeter's console palette. The table itself arrives
|
|
778 |
+ |
# with the rest of the rendered tree above, at /usr/share/alloy/vtrgb.
|
|
779 |
+ |
# alloy-vtrgb.service reads it; setvtrgb ships in kbd, which systemd's vconsole
|
|
780 |
+ |
# setup already pulls in. Assert it here rather than let the unit's
|
|
781 |
+ |
# ConditionPathExists turn a missing binary into a silent no-op that drops the
|
|
782 |
+ |
# greeter back to the stock console palette.
|
| 751 |
783 |
|
RUN command -v setvtrgb >/dev/null \
|
| 752 |
784 |
|
|| { echo "setvtrgb (kbd) is missing; alloy-vtrgb.service would no-op" >&2; exit 1; }
|
|
785 |
+ |
RUN test -s /usr/share/alloy/vtrgb \
|
|
786 |
+ |
|| { echo "the console palette did not arrive with the rendered tree" >&2; exit 1; }
|
| 753 |
787 |
|
|
| 754 |
788 |
|
# =====================================================================
|
| 755 |
789 |
|
# bootc validation — fails the build if the image isn't a valid
|