From 5794a80d0e3d45019b39e0f83b01ad62df50c123 Mon Sep 17 00:00:00 2001 From: codex-bot-andresmgsl <244098813+codex-bot-andresmgsl@users.noreply.github.com> Date: Sat, 25 Jul 2026 13:34:58 +0000 Subject: [PATCH 1/4] feat: prefer installed template snapshot --- changelog.d/153.md | 1 + commands/lib/templates.sh | 35 ++++++++++++++++++++++++++++++++--- test/cli.sh | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 changelog.d/153.md diff --git a/changelog.d/153.md b/changelog.d/153.md new file mode 100644 index 0000000..5511116 --- /dev/null +++ b/changelog.d/153.md @@ -0,0 +1 @@ +- Pinned template registries install with rig and serve default converges offline (#153) diff --git a/commands/lib/templates.sh b/commands/lib/templates.sh index 18acbd3..15c26f9 100644 --- a/commands/lib/templates.sh +++ b/commands/lib/templates.sh @@ -18,7 +18,8 @@ # /creds.md the per-vendor creds-free paragraph the context # renderer splices in # -# THE SOURCE IS THREE KNOBS, precedence _DIR > _REF > pin: +# THE SOURCE IS THREE KNOBS plus the installed pin snapshot, precedence +# _DIR > _REF > snapshot > pin fetch: # RIG_TEMPLATES_DIR a local folder — bypasses the fetch entirely (the # offline-test path, and "try a template before it # exists anywhere") @@ -26,7 +27,8 @@ # bootstrap time (the same shape as the rig preinstall) # RIG_TEMPLATES_REPO which repo that ref lives in (default # heavy-duty/rig-templates) -# and, absent both overrides, the PIN below. +# and, absent both overrides, the snapshot installed beside this file when it +# matches the PIN below, then a live fetch of that pin as the fallback. # The default registry ref a mint converges — the BOX_RELEASE discipline # (#103): one line, bumped deliberately by ordinary rig PR after review, so a @@ -51,6 +53,10 @@ MACHINE_KEYS_REQUIRED=(ROOT_DOOR HOST JOIN) templates_source_desc() { if [ -n "${RIG_TEMPLATES_DIR:-}" ]; then printf 'local dir %s (RIG_TEMPLATES_DIR)' "$RIG_TEMPLATES_DIR" + elif [ -z "${RIG_TEMPLATES_REF:-}" ] && templates_snapshot_usable; then + printf '%s@%s (snapshot)' \ + "${RIG_TEMPLATES_REPO:-heavy-duty/rig-templates}" \ + "$RIG_TEMPLATES_PIN" else printf '%s@%s%s' \ "${RIG_TEMPLATES_REPO:-heavy-duty/rig-templates}" \ @@ -59,7 +65,26 @@ templates_source_desc() { fi } -# templates_resolve — resolve the three knobs to a LOCAL directory holding +# The snapshot path is derived from this library's installed tree. Its +# pin-bearing directory name is the staleness guard: an older snapshot is +# invisible after a pin bump. A usable registry has at least one definition; +# an empty directory means an interrupted extraction and falls through to the +# same live fetch as an absent snapshot. +templates_snapshot_dir() { + local lib_dir + lib_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + printf '%s/templates@%s' "$(cd "$lib_dir/../.." && pwd)" "$RIG_TEMPLATES_PIN" +} + +templates_snapshot_usable() { + local snapshot role_env + snapshot="$(templates_snapshot_dir)" + [ -d "$snapshot" ] || return 1 + role_env="$(find "$snapshot" -mindepth 2 -maxdepth 2 -type f -name template.env -print -quit 2>/dev/null)" + [ -n "$role_env" ] +} + +# templates_resolve — resolve the knobs to a LOCAL directory holding # the registry, left in the REGISTRY_DIR global (a global, not stdout: a # $(…) call site would run the fetch in a subshell and lose TEMPLATES_TMP, # the path the caller's cleanup trap must rm). RIG_TEMPLATES_DIR wins and is @@ -83,6 +108,10 @@ templates_resolve() { REGISTRY_DIR="$RIG_TEMPLATES_DIR" return 0 fi + if [ -z "${RIG_TEMPLATES_REF:-}" ] && templates_snapshot_usable; then + REGISTRY_DIR="$(templates_snapshot_dir)" + return 0 + fi repo="${RIG_TEMPLATES_REPO:-heavy-duty/rig-templates}" ref="${RIG_TEMPLATES_REF:-$RIG_TEMPLATES_PIN}" command -v curl >/dev/null 2>&1 || { printf 'curl is required to fetch the template registry\n' >&2; return 1; } diff --git a/test/cli.sh b/test/cli.sh index fff0f8c..25ed744 100644 --- a/test/cli.sh +++ b/test/cli.sh @@ -854,6 +854,45 @@ check "templates: the pin is one greppable line" 0 "1" \ check "templates: unset knobs fall back to the pin" 0 "the in-tree pin" \ bash -c '. "$1/commands/lib/templates.sh" && templates_source_desc' _ "$ROOT" +# The installed snapshot is found relative to templates.sh itself, so exercise +# it in a copied rig tree: no fixture-only path knob can accidentally make the +# production precedence pass. Poisoned curl makes any network attempt fatal. +mkdir -p "$TPL_WORK/rig/commands/lib" +cp "$ROOT/commands/lib/templates.sh" "$TPL_WORK/rig/commands/lib/templates.sh" +TPL_PIN="$(sed -n 's/^RIG_TEMPLATES_PIN=//p' "$ROOT/commands/lib/templates.sh")" +cp -r "$TPL_FIX" "$TPL_WORK/rig/templates@$TPL_PIN" +cat > "$TPL_WORK/bin/curl" <<'CURLEOF' +#!/usr/bin/env bash +echo "poisoned curl: snapshot resolution attempted network I/O" >&2 +exit 99 +CURLEOF +chmod +x "$TPL_WORK/bin/curl" +# shellcheck disable=SC2016 +snapshot_resolve='set -euo pipefail + . "$1/commands/lib/templates.sh" + templates_resolve + printf "%s\n%s\n" "$REGISTRY_DIR" "$(templates_source_desc)"' +check "templates: matching snapshot resolves with poisoned curl" 0 "(snapshot)" \ + env PATH="$TPL_WORK/bin:$PATH" bash -c "$snapshot_resolve" _ "$TPL_WORK/rig" + +# A stale directory and an empty current directory are both unusable. The +# poisoned fetch exit is folded into templates_resolve's normal loud refusal; +# the important assertion is that neither path answers as the registry. +mv "$TPL_WORK/rig/templates@$TPL_PIN" "$TPL_WORK/rig/templates@stale-pin" +mkdir "$TPL_WORK/rig/templates@$TPL_PIN" +check "templates: empty matching snapshot falls back to fetch" 1 "cannot fetch" \ + env PATH="$TPL_WORK/bin:$PATH" bash -c "$snapshot_resolve" _ "$TPL_WORK/rig" +rm -rf "$TPL_WORK/rig/templates@$TPL_PIN" +check "templates: stale snapshot is ignored" 1 "cannot fetch" \ + env PATH="$TPL_WORK/bin:$PATH" bash -c "$snapshot_resolve" _ "$TPL_WORK/rig" + +# An explicit ref always means a live fetch, even when the matching snapshot +# exists: restore it and prove the poison is reached. +mv "$TPL_WORK/rig/templates@stale-pin" "$TPL_WORK/rig/templates@$TPL_PIN" +check "templates: explicit REF never reads the snapshot" 1 "cannot fetch" \ + env PATH="$TPL_WORK/bin:$PATH" RIG_TEMPLATES_REF=operator-ref \ + bash -c "$snapshot_resolve" _ "$TPL_WORK/rig" + # rig template-lint — the registry repo's CI gate, same schema as the mint's # parser (rig defines validity; rig-templates CI enforces it on every PR). check "template-lint: --help exits 0" 0 "usage:" "$ROOT/commands/template-lint.sh" --help From 247d9b9ec59d376295cb2ce3cfd45ec513863053 Mon Sep 17 00:00:00 2001 From: codex-bot-andresmgsl <244098813+codex-bot-andresmgsl@users.noreply.github.com> Date: Sat, 25 Jul 2026 13:38:54 +0000 Subject: [PATCH 2/4] feat: install and record registry snapshot --- README.md | 11 ++++++-- drill/drill.sh | 12 ++++++--- install.sh | 53 +++++++++++++++++++++++++++++++++++++++ test/cli.sh | 29 ++++++++++++++++++++- test/install-lifecycle.sh | 20 ++++++++++++++- 5 files changed, 118 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 17e2732..09e06ef 100644 --- a/README.md +++ b/README.md @@ -464,13 +464,20 @@ actually contains. `staging-box` is the one in-tree tenant — mechanism-adjacen (sshd hardening through the shared `lib/sshd.sh`, docker, no agent), user `ops`, box#69's server posture with `root-door=open` acceptance. -**Where the registry comes from — three knobs, precedence high to low:** +**Where the registry comes from — precedence high to low:** | knob | meaning | |------|---------| | `RIG_TEMPLATES_DIR` | a local folder — no fetch: the offline-test path, and "try a template before it exists anywhere" | | `RIG_TEMPLATES_REF` | any ref of `RIG_TEMPLATES_REPO` (default `heavy-duty/rig-templates`), fetched as an unauthenticated tarball at bootstrap time | -| *(neither set)* | **the in-tree pin** — `RIG_TEMPLATES_PIN` in `commands/lib/templates.sh`, the `BOX_RELEASE` discipline: bumped by ordinary reviewed rig PR, so a rig release freezes the mechanism+registry pair, and a newer rig matches newer templates by default (the #110 ruling) | +| *(neither set; matching snapshot installed)* | **the installed pin snapshot** — `install.sh` best-effort fetches `RIG_TEMPLATES_PIN` once into `templates@/` inside the versioned rig tree; default converges read it with zero registry network I/O | +| *(snapshot absent, empty, or stale)* | **live fetch of the in-tree pin** — the pre-snapshot fallback: `RIG_TEMPLATES_PIN` in `commands/lib/templates.sh` is fetched at converge time. A failed snapshot download only warns during install, so rig remains usable and retries here | + +The pin remains the only source of truth. An older `templates@/` +directory cannot answer after a pin bump, and an explicit +`RIG_TEMPLATES_REF` always fetches that ref rather than consulting the +snapshot. Logs mark the installed path as `(snapshot)` so drill evidence +records which source actually served the converge. **The security trade — in bold, not a footnote.** **A main-tracked rig-templates repo means every merged PR there executes as root inside every diff --git a/drill/drill.sh b/drill/drill.sh index 7671d53..8046e29 100644 --- a/drill/drill.sh +++ b/drill/drill.sh @@ -59,6 +59,7 @@ BOXREF="${BOX_REF:-}" TPLREPO="${RIG_TEMPLATES_REPO:-heavy-duty/rig-templates}" TPLREF="${RIG_TEMPLATES_REF:-}" TPL_SHA="" +TPL_SOURCE="fetched" ROLE=staging-server USERS_FILE="${DRILL_USERS_FILE:-}" RUN_ID="${DRILL_RUN_ID:-drill-$(date -u +%F)}" @@ -274,8 +275,9 @@ emit_record() { printf 'Run ID: %s. Host: %s, %s vCPU / %s GB RAM (%s).\n' "$RUN_ID" "${os:-unknown}" "$cpus" "$ram" "$virt" printf 'Candidate refs: rig@%s (RIG_REF=%s), box@%s (BOX_REF=%s).\n' \ "${RIG_SHA:-unresolved}" "$REF" "${BOX_SHA:-unresolved}" "$BOXREF" - printf 'Template registry: %s@%s (ref %s) — the rig-templates the converge read (#110).\n' \ - "${TPLREPO:-heavy-duty/rig-templates}" "${TPL_SHA:-unresolved}" "${TPLREF:-unresolved}" + printf 'Template registry: %s@%s (ref %s, %s) — the rig-templates source the converge read (#110/#153).\n' \ + "${TPLREPO:-heavy-duty/rig-templates}" "${TPL_SHA:-unresolved}" \ + "${TPLREF:-unresolved}" "$TPL_SOURCE" printf 'Instrument: drill/drill.sh, legs in execution order.\n\n' printf '| Leg | Result |\n' printf '| --- | --- |\n' @@ -396,13 +398,17 @@ ok "installed tree confirms: $REPO@$REF (version $DRILL_VERSION)" # through ref_sha like the two candidates above. if [ -z "$TPLREF" ]; then TPLREF="$(sed -n 's/^RIG_TEMPLATES_PIN=//p' "$RIG_TREE/commands/lib/templates.sh" 2>/dev/null | head -n1)" + if [ -n "$TPLREF" ] && + [ -n "$(find "$RIG_TREE/templates@$TPLREF" -mindepth 2 -maxdepth 2 -type f -name template.env -print -quit 2>/dev/null)" ]; then + TPL_SOURCE="snapshot" + fi fi if [[ "$TPLREF" =~ ^[0-9a-f]{40}$ ]]; then TPL_SHA="${TPLREF:0:7}" elif [ -n "$TPLREF" ]; then TPL_SHA="$(ref_sha "$TPLREPO" "$TPLREF")" fi -inf "templates: $TPLREPO@${TPLREF:-unresolved} (${TPL_SHA:-unresolved})" +inf "templates: $TPLREPO@${TPLREF:-unresolved} (${TPL_SHA:-unresolved}, $TPL_SOURCE)" [ -n "$RECORD" ] || RECORD="$ROOT/drills/$DRILL_VERSION.md" # ============================================================================= diff --git a/install.sh b/install.sh index 3c1e30b..1423211 100644 --- a/install.sh +++ b/install.sh @@ -249,6 +249,57 @@ set_exec() { # $1 = a rig tree: the executable bits install.sh owns fi } +# snapshot_templates — best-effort install-time cache of the exact +# registry pin carried by that tree. The pin remains the sole source of truth; +# the directory name makes a stale snapshot invisible after an upgrade. +# Failure is deliberately a warning: rig itself is still a complete install, +# and templates_resolve preserves the live-fetch fallback. +snapshot_templates() { + local tree="$1" pin repo url got="" unpack top snapshot + pin="$(sed -n 's/^RIG_TEMPLATES_PIN=//p' "$tree/commands/lib/templates.sh" 2>/dev/null | head -n1 || true)" + if [ -z "$pin" ]; then + warn "installed tree carries no RIG_TEMPLATES_PIN; template registry snapshot skipped." + return 0 + fi + repo="${RIG_TEMPLATES_REPO:-heavy-duty/rig-templates}" + snapshot="$tree/templates@$pin" + if ! command -v curl >/dev/null 2>&1; then + warn "curl is unavailable; template registry snapshot $repo@$pin was not installed (converge will retry the live fetch)." + return 0 + fi + unpack="$TMPDIR/templates-unpack" + rm -rf "$unpack" + mkdir -p "$unpack" + log "downloading template registry snapshot $repo@$pin" + for url in \ + "https://github.com/$repo/archive/refs/tags/$pin.tar.gz" \ + "https://github.com/$repo/archive/refs/heads/$pin.tar.gz" \ + "https://github.com/$repo/archive/$pin.tar.gz"; do + if curl -fsSL "$url" -o "$TMPDIR/templates.tar.gz" 2>/dev/null; then got="$url"; break; fi + done + if [ -z "$got" ]; then + warn "could not fetch template registry snapshot $repo@$pin; rig installed without it (converge will retry the live fetch)." + return 0 + fi + if ! tar -xzf "$TMPDIR/templates.tar.gz" -C "$unpack"; then + warn "could not extract template registry snapshot from $got; rig installed without it (converge will retry the live fetch)." + return 0 + fi + set -- "$unpack"/*/ + if ! { [ $# -eq 1 ] && [ -d "$1" ]; }; then + warn "template registry snapshot from $got has an unexpected archive shape; rig installed without it (converge will retry the live fetch)." + return 0 + fi + top="${1%/}" + if [ -z "$(find "$top" -mindepth 2 -maxdepth 2 -type f -name template.env -print -quit 2>/dev/null)" ]; then + warn "template registry snapshot from $got has no definitions; rig installed without it (converge will retry the live fetch)." + return 0 + fi + rm -rf "$snapshot" + mv "$top" "$snapshot" + log "template registry snapshot installed: $repo@$pin" +} + # --- install into $DEST/versions/ ----------------------------------- VDIR="$DEST/versions/$new_ver" newly_installed=0 @@ -259,6 +310,7 @@ if [ -d "$VDIR" ]; then log "RIG_REINSTALL=1 — replacing the installed $new_ver tree" stage="$VDIR.new.$$"; old="$VDIR.old.$$" rm -rf "$stage" "$old" + snapshot_templates "$EXTRACTED" set_exec "$EXTRACTED" mv "$EXTRACTED" "$stage" # Swap by renames, delete LAST: rm-then-move leaves a hole the whole @@ -276,6 +328,7 @@ if [ -d "$VDIR" ]; then else log "installing $new_ver into $VDIR" mkdir -p "$DEST/versions" + snapshot_templates "$EXTRACTED" set_exec "$EXTRACTED" mv "$EXTRACTED" "$VDIR" newly_installed=1 diff --git a/test/cli.sh b/test/cli.sh index 25ed744..f184847 100644 --- a/test/cli.sh +++ b/test/cli.sh @@ -2654,6 +2654,19 @@ check "help lists the versioned verbs" 0 "uninstall" "$ROOT/bin/rig" --help WORK="$(mktemp -d)" FAKEHOME="$WORK/home"; mkdir -p "$FAKEHOME" +# Every real installer run gets a deterministic registry archive. The curl +# shim can also be poisoned per call to prove warn-and-continue behavior. +SNAPBIN="$WORK/snapshot-bin" +mkdir -p "$SNAPBIN" "$WORK/snapshot-stage/rig-templates-pin/scratch-box" +printf 'USER="scratch"\n' > "$WORK/snapshot-stage/rig-templates-pin/scratch-box/template.env" +tar -czf "$WORK/snapshot.tar.gz" -C "$WORK/snapshot-stage" rig-templates-pin +cat > "$SNAPBIN/curl" <<'CURLEOF' +#!/usr/bin/env bash +[ -z "${SNAPSHOT_FETCH_FAIL:-}" ] || exit 22 +cp "${SNAPSHOT_TARBALL:?}" "$4" +CURLEOF +chmod +x "$SNAPBIN/curl" + # A fabricated "newer release": the same CLI, a different VERSION — what an # upgrade actually is, from the installer's point of view. SRC9="$WORK/src-9.9.9"; mkdir -p "$SRC9/bin" @@ -2665,7 +2678,8 @@ echo "8.8.8-drill" > "$SRC8/VERSION" inst() { # inst [VAR=val ...] — run install.sh for real local h="$1" b="$2"; shift 2 - env HOME="$FAKEHOME" RIG_ROLE_MARKER="$WORK/no-marker" \ + env HOME="$FAKEHOME" PATH="$SNAPBIN:$PATH" \ + SNAPSHOT_TARBALL="$WORK/snapshot.tar.gz" RIG_ROLE_MARKER="$WORK/no-marker" \ RIG_HOME="$h" RIG_BIN="$b" \ RIG_INSTALL_SOURCE="$ROOT" "$@" bash "$ROOT/install.sh" } @@ -2681,6 +2695,16 @@ check "install: 'current' points at versions/" 0 "versions/$VER" readlink "$H check "install: the PATH symlink rides the chain" 0 "$H1/current/bin/rig" readlink "$B1/rig" check "install: rig --version answers through the whole chain" 0 "rig $VER" irig "$B1/rig" --version check "install: INSTALLED_FROM records the local source" 0 "local:" cat "$H1/versions/$VER/INSTALLED_FROM" +check "install: the pinned registry snapshot lands inside the version tree" 0 "" \ + test -f "$H1/versions/$VER/templates@$TPL_PIN/scratch-box/template.env" + +HFAIL="$WORK/h-failed-snapshot"; BFAIL="$WORK/b-failed-snapshot" +check "install: unreachable registry warns and still installs rig" 0 "WARNING: could not fetch template registry snapshot" \ + inst "$HFAIL" "$BFAIL" SNAPSHOT_FETCH_FAIL=1 +check "install: failed snapshot fetch leaves a working tree" 0 "rig $VER" \ + "$BFAIL/rig" --version +check "install: failed snapshot fetch leaves no hollow snapshot" 1 "" \ + test -e "$HFAIL/versions/$VER/templates@$TPL_PIN" # --- rig#39: no $HOME in the environment (cloud-init's runcmd) --------------- # The box#88 seed runs install.sh from runcmd, which carries NO $HOME; under @@ -2703,10 +2727,13 @@ check "install: no \$HOME and no getent answer refuses by name" 1 "set HOME and # --- converge, don't clobber ------------------------------------------------ touch "$H1/versions/$VER/CANARY" +touch "$H1/versions/$VER/templates@$TPL_PIN/STALE" check "install: a same-version re-run is a no-op that says so" 0 "already installed" inst "$H1" "$B1" check "install: the no-op left the tree untouched" 0 "" test -e "$H1/versions/$VER/CANARY" check "install: RIG_REINSTALL=1 replaces that version's tree" 0 "reinstalled" inst "$H1" "$B1" RIG_REINSTALL=1 check "install: the reinstall really replaced it (canary gone)" 1 "" test -e "$H1/versions/$VER/CANARY" +check "install: reinstall replaces the registry snapshot" 1 "" \ + test -e "$H1/versions/$VER/templates@$TPL_PIN/STALE" # --- a second version: side-by-side, and the flip --------------------------- check "install: a second version installs side-by-side" 0 "" inst "$H1" "$B1" RIG_INSTALL_SOURCE="$SRC9" diff --git a/test/install-lifecycle.sh b/test/install-lifecycle.sh index 1a221a9..8000877 100755 --- a/test/install-lifecycle.sh +++ b/test/install-lifecycle.sh @@ -65,6 +65,18 @@ VER="$(cat "$ROOT/VERSION")" WORK="$(mktemp -d)" trap 'rm -rf "$WORK"' EXIT +# install.sh snapshots the pinned registry even for the local source channel. +# Serve a deterministic archive so this lifecycle remains fully offline. +SNAPBIN="$WORK/snapshot-bin" +mkdir -p "$SNAPBIN" "$WORK/snapshot-stage/rig-templates-pin/test-box" +printf 'USER="test"\n' > "$WORK/snapshot-stage/rig-templates-pin/test-box/template.env" +tar -czf "$WORK/snapshot.tar.gz" -C "$WORK/snapshot-stage" rig-templates-pin +cat > "$SNAPBIN/curl" <<'CURLEOF' +#!/usr/bin/env bash +cp "${SNAPSHOT_TARBALL:?}" "$4" +CURLEOF +chmod +x "$SNAPBIN/curl" + # tree_state — what "changed nothing" must mean: every file's bytes, # every path's type and mode, every symlink's target. Beat 3 captures this # before and after the re-run and diffs the two. @@ -124,7 +136,10 @@ check "honesty: a really-gone path passes the absence assert" 0 "" \ # RIG_INSTALL_SOURCE is the supported local channel (its contract — dir, # tarball, loud refusal, no silent download fallback — is test/release.sh's); # in CI $ROOT is $GITHUB_WORKSPACE, so what lands is the code under review. -b1() { RIG_INSTALL_SOURCE="$ROOT" bash "$ROOT/install.sh"; } +b1() { + PATH="$SNAPBIN:$PATH" SNAPSHOT_TARBALL="$WORK/snapshot.tar.gz" \ + RIG_INSTALL_SOURCE="$ROOT" bash "$ROOT/install.sh" +} check "beat 1: install.sh installs this checkout" 0 "done" b1 # --- beat 2: assert what landed ---------------------------------------------- @@ -140,6 +155,9 @@ check "beat 2: rig --version answers through the whole chain" 0 "rig $VER" \ "$BINDIR/rig" --version check "beat 2: INSTALLED_FROM names the local source" 0 "local:$ROOT" \ cat "$DEST/versions/$VER/INSTALLED_FROM" +TPL_PIN="$(sed -n 's/^RIG_TEMPLATES_PIN=//p' "$ROOT/commands/lib/templates.sh")" +check "beat 2: pinned registry snapshot landed in the version tree" 0 "" \ + test -f "$DEST/versions/$VER/templates@$TPL_PIN/test-box/template.env" # --- beat 3: the converging re-run ------------------------------------------- # "Ran twice without crashing" is the self-deception this beat exists to From b849eb57d39f5c044013057cf935f7450880ca69 Mon Sep 17 00:00:00 2001 From: codex-bot-andresmgsl <244098813+codex-bot-andresmgsl@users.noreply.github.com> Date: Sat, 25 Jul 2026 13:41:01 +0000 Subject: [PATCH 3/4] test: prove drill records registry source --- drill/drill.sh | 2 +- test/drill.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drill/drill.sh b/drill/drill.sh index 8046e29..a6f161d 100644 --- a/drill/drill.sh +++ b/drill/drill.sh @@ -277,7 +277,7 @@ emit_record() { "${RIG_SHA:-unresolved}" "$REF" "${BOX_SHA:-unresolved}" "$BOXREF" printf 'Template registry: %s@%s (ref %s, %s) — the rig-templates source the converge read (#110/#153).\n' \ "${TPLREPO:-heavy-duty/rig-templates}" "${TPL_SHA:-unresolved}" \ - "${TPLREF:-unresolved}" "$TPL_SOURCE" + "${TPLREF:-unresolved}" "${TPL_SOURCE:-fetched}" printf 'Instrument: drill/drill.sh, legs in execution order.\n\n' printf '| Leg | Result |\n' printf '| --- | --- |\n' diff --git a/test/drill.sh b/test/drill.sh index b189931..8c01a08 100644 --- a/test/drill.sh +++ b/test/drill.sh @@ -159,7 +159,7 @@ check "…and the diff names the drifted sshd keyword, not just 'differs'" 1 "pa emit() { # emit — emit_record with the harness globals staged DRILL_VERSION="9.9.9" RUN_ID="drill-2026-01-01-a" \ REF="release/9.9.9" BOXREF="release/0.4.0" RIG_SHA="5d6e7f8" BOX_SHA="1a2b3c4" \ - TPLREPO="heavy-duty/rig-templates" TPLREF="9f8e7d6c5b4a39281706f5e4d3c2b1a098765432" TPL_SHA="9f8e7d6" \ + TPLREPO="heavy-duty/rig-templates" TPLREF="9f8e7d6c5b4a39281706f5e4d3c2b1a098765432" TPL_SHA="9f8e7d6" TPL_SOURCE="snapshot" \ bash -c ' . "$1" pass=12 fail=1 skipped=1 @@ -174,7 +174,7 @@ check "record: the version-and-date heading" 0 "# Release drill — 9.9.9 — " check "record: the run ID that joins the family's records" 0 "Run ID: drill-2026-01-01-a" cat "$WORK/record.md" check "record: both pinned refs with their SHAs" 0 "rig@5d6e7f8 (RIG_REF=release/9.9.9)" cat "$WORK/record.md" check "record: …box's too" 0 "box@1a2b3c4 (BOX_REF=release/0.4.0)" cat "$WORK/record.md" -check "record: the template registry SHA rides alongside the pair (#110)" 0 "rig-templates@9f8e7d6 (ref 9f8e7d6c5b4a39281706f5e4d3c2b1a098765432)" cat "$WORK/record.md" +check "record: the template registry SHA and actual source ride alongside the pair (#110/#153)" 0 "rig-templates@9f8e7d6 (ref 9f8e7d6c5b4a39281706f5e4d3c2b1a098765432, snapshot)" cat "$WORK/record.md" check "record: one table row per leg, result verbatim" 0 "| re-converge (idempotence) | clean, no changes |" cat "$WORK/record.md" check "record: the numbers, skips counted apart from passes" 0 "12 passed, 1 failed, 1 skipped" cat "$WORK/record.md" check "record: a FAILED run still names what failed (evidence, not success)" 0 "FAIL: coolify container state: absent" cat "$WORK/record.md" From dfd2debff1815ccfb85a85de55d313052b965952 Mon Sep 17 00:00:00 2001 From: codex-bot-andresmgsl <244098813+codex-bot-andresmgsl@users.noreply.github.com> Date: Sat, 25 Jul 2026 16:00:29 +0000 Subject: [PATCH 4/4] fix: group template snapshot changelog entry --- changelog.d/153.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog.d/153.md b/changelog.d/153.md index 5511116..0dabcf3 100644 --- a/changelog.d/153.md +++ b/changelog.d/153.md @@ -1 +1,3 @@ +### Added + - Pinned template registries install with rig and serve default converges offline (#153)