Repository navigation
Write /etc/keel_version beside the compatibility file - #5
Conversation
|
The appliance side is Keel-Linux/keel-core#9 and the decision note is Keel-Linux/handbook#6. |
|
Reviewed together with Keel-Linux/keel-core#9 and handbook #6 and #4. Merging this one first is the ordering with no window in which anything is wrong: keel-core#9 reads What I verified rather than accepted:
MEDIUM1. Every appliance build now hard-depends on a script in the common checkout, and the failure will not name itself. 2. LOW3. A hyphenated 4. ApproveNo CRITICAL and no HIGH. The two MEDIUMs are hardening of a path that already fails in the right direction, and the LOWs are documentation. The mechanism it disarms is real, the normalisation is conservative, and the blast radius is one new file per image and no change to any existing one. |
|
MEDIUM 1 and 2 and both LOWs fixed in 8d19fbb and 0e47bdb, plus the gap #8 found: |
0e47bdb to
91f230b
Compare
An appliance had no file saying what it is. The console banner reads
/etc/turnkey_version for the appliance name and the version because there
was nothing else to read, and its own comment said so; everything else
Keel presents to an operator would have had to do the same.
/etc/keel_version is that file: the same four fields,
keel-<app>-<version>-<codename>-<architecture>, written at build time
beside /etc/turnkey_version. Decision 0014 settles what each of the two is
for: the TurnKey file is an interface we honour, the Keel file is what we
say we are.
Why here and not in an appliance conf script. A conf script runs in
root.patched/body, and /etc/turnkey_version is written in
root.patched/post, so at the moment a conf script runs the file it would
derive the Keel name from still holds the parent layer's value, or nothing
at all on a rootfs layer. The version string exists in exactly one place,
the recipe that computes it from the product changelog, and that place is
shared by every appliance rather than repeated in each of them. Measured
from the makefiles themselves, root.patched/post is also the last thing
that touches the tree before the removelists, so neither file can be
clobbered by an overlay or a conf script.
The prefix is normalised, which fixes a defect this work uncovered.
turnkey-version.py takes the name from the first line of the product
changelog, so a repository that renames its release package produces a
version string with that name's prefix. keel-core's changelog became
"keel-core-19.0 (1) keel" on 2026-09-27, so the next core layer would have
written keel-core-19.0-trixie-amd64 into /etc/turnkey_version, and every
parser of that file is prefix sensitive:
- sysversion._parse_turnkey_release matches "turnkey-.*?-(\d.*?)-[^\d]",
so get_turnkey_release() returns the empty string and the release
number disappears from everything that formats a version;
- sysversion.AppVer removes the prefix "turnkey-" and then splits, so
appname becomes "keel-core" instead of "core";
- keel.inspect.app.probe_appliance requires the string to start with
"turnkey-" and reports the appliance as missing otherwise, which costs
keel inspect and keel diff the appliance identity of the machine.
bin/keel-version-files now takes the changelog-derived string, removes at
most one product prefix and writes turnkey-<rest> and keel-<rest>. The
published core layer predates the changelog rename, so nothing shipped is
affected; the next build would have been.
The grammar and the prefix rules are lib/version-files.sh, pure functions
with no effect, and the script is the thin main that validates and writes
(decision 0004). Both are measured: 100 percent, 15 of 15 and 36 of 36
lines, 33 bats tests under kcov 43, covering every exit code (1 bad usage
or unparseable version, 2 an unwritable tree, 3 the library missing) and
the errexit trap of docs/traps.md. tests/coverage.sh grew the per-target
loop keel-core uses so it can measure more than one file;
conf/turnkey.d/postfix-local stays at 100 percent, 17 of 17 lines.
mk/turnkey-desktop.mk is a second copy of the root.patched/post block and still wrote /etc/turnkey_version from the raw changelog string, so a desktop build got no /etc/keel_version and none of the prefix normalisation. It now calls bin/keel-version-files like mk/turnkey.mk. Both makefiles check the script is there before calling it. A build host whose common checkout predates it would otherwise die in root.patched/post, after the whole root was built, with a bare "No such file or directory"; now it names the path and says the checkout is stale. And the version string is quoted, so an empty one or one with a space is refused as a version rather than, by luck, as a wrong argument count. tests/mk-identity.bats makes the recipe of both makefiles against stubs of fab and reads the files back; six of its eight tests failed before this change. make has no line coverage, so tests/coverage.sh runs it for its verdict.
kvf_app_version and kvf_is_app_version each walked KVF_PREFIXES to answer the same question with opposite senses; kvf_has_prefix is that question. A hyphenated VERSION_TAG gives the version string a fifth field and is refused. The usage now says the tag joins the version field, so that is not found for the first time during a release.
91f230b to
ca99941
Compare
Rebased onto 19.x after common#30 and #31. The root.patched/post recipe of mk/turnkey.mk now ends in mk/turnkey/seal-root (#31), which the fab stubs of tests/mk-identity.bats did not reach, so three of its tests failed. The harness links the real seal-root under its FAB_PATH and gives the scratch root a locked root, and asserts what both changes promise: both identity files, the build date stamped last, a shipped root password refused, and no per-appliance apt User-Agent written (#6), which this branch's makefiles used to write before the rebase. The feature gets its bullet in the unreleased changelog entry.
ca99941 to
de7f410
Compare
An appliance had no file saying what it is. The console banner reads
/etc/turnkey_versionfor the name and the version because there wasnothing else to read, and its own comment said so.
This adds
/etc/keel_version, the same four fields with thekeel-prefix, written at build time beside the compatibility file. Handbook
decision 0014 (Keel-Linux/handbook#6) settles what each of the two is
for: the TurnKey file is an interface we honour, the Keel file is what we
say we are.
Why here
mk/turnkey.mk, inroot.patched/post, is the only place the versionstring exists, it is shared by every appliance rather than repeated in
each recipe, and it is the last thing that touches the tree, so neither
file can be clobbered by an overlay or a conf script. An appliance conf
script cannot do it: conf scripts run in
root.patched/body, before/etc/turnkey_versionis written, so the value they would derive from isthe parent layer's, or nothing at all on a rootfs layer. The ordering was
read out of the makefiles, not assumed.
A defect this uncovered
turnkey-version.pytakes the name for/etc/turnkey_versionfrom thefirst line of the product changelog. keel-core's changelog became
keel-core-19.0 (1) keelon 2026-09-27, so the next core layer wouldhave written
keel-core-19.0-trixie-amd64into that file, and everyparser of it is prefix sensitive:
sysversion._parse_turnkey_releasematchesturnkey-.*?-(\d.*?)-[^\d],so
get_turnkey_release()returns the empty string and the releasenumber disappears from every version string built from it;
sysversion.AppVerremoves the prefixturnkey-and then splits, sothe app name comes out as
keel-corerather thancore;keel.inspect.app.probe_appliancerequires theturnkey-prefix andreports the appliance as missing otherwise, which costs
keel inspectandkeel diffthe identity of the machine.bin/keel-version-filesnow removes at most one product prefix from thechangelog-derived string and writes
turnkey-<rest>andkeel-<rest>.The published core layer predates the changelog rename, so nothing
shipped is affected; the next build would have been.
Tests
lib/version-files.shholds the grammar and the prefix rules as purefunctions,
bin/keel-version-filesis the thin main that validates andwrites (decision 0004). 33 bats tests, both files at 100 percent
under kcov 43 (15 of 15 and 36 of 36 lines), covering every exit code (1
bad usage or a version string that is not an appliance identity, 2 an
unwritable tree, 3 the library missing) and the errexit trap of
docs/traps.md.tests/coverage.shgrew the per-target loop keel-coreuses so it can measure more than one file;
conf/turnkey.d/postfix-localstays at 100 percent, 17 of 17 lines. The threshold stays at 100.
Test plan
COVERAGE_THRESHOLD=100 tests/coverage.sh: three files, all 100percent
shellcheck -S warningclean on the new filesread from
product.mkandmk/turnkey.mkwithmake -nimage and
keel inspectstill naming the applianceRebased onto 19.x, 2026-10-02 (after common#30 and #31)
mk/turnkey.mkandmk/turnkey-desktop.mk: the identity files are written bybin/keel-version-filesas before, with the-xcheck. The per-appliance apt User-Agent (01turnkey) that this branch's makefiles still wrote is not restored: common#6 replaced it with the overlay's fixed01keel, andconf/turnkey.d/apt-identitydeletes a01turnkey. The recipe ends inmk/turnkey/seal-root(fix: images ship root locked, or the build fails; stamp the build date #31) as on 19.x.tests/mk-identity.bats: the harness now links the realseal-rootunder itsFAB_PATHand gives the scratch root a locked root. Three of its tests failed after the rebase without that. Four new tests: the build date is stamped after the identity files, a shipped root password fails the build, and neither makefile writes anything intoapt.conf.d.tests/coverage.sh: thelib/version-files.shandbin/keel-version-filestargets and the unmeasuredmk-identity.batsrun are added beside 19.x's targets and its before-firstboot/pam-unix run.COVERAGE.md: both tables' rows kept, 17/17 and 36/36, 37 bats for the identity files.changes/turnkey.changelog: a bullet for/etc/keel_versionat the top of the unreleasedturnkey-core-19.0 (1)entry, above fix: images ship root locked, or the build fails; stamp the build date #31's; the branch had none.keel-<app>-<version>-<codename>-<arch>in/etc/keel_version,turnkey-prefix kept in/etc/turnkey_version.KEEL_APT_TRACK, decision 0047):mk/turnkey.mkno longer calls fab'smake-release-deb.py, so the recipe now writes the two identity files and nothing else beforeseal-root. build: KEEL_APT_TRACK picks the Keel track; the plan drops tklbam, hubdns and the release meta package #32's test that no release meta package is built asserted the oldturnkey_version=... > /etc/turnkey_versiontext; it now asserts thekeel-version-filescall, andtests/mk-identity.batsproves the files are written by running the recipe.