feat(preflight): host/toolchain validation + VERSIONS pin-file — T01
- VERSIONS: 7 container images (CONTRACT_003 §3.2) + 13 host tools, KEY=value, source-able+greppable; images carry :PIN_DIGEST placeholders with a documented pin-digests procedure (D5 determinism — no real deploy until pinned). - preflight.sh: fails closed (non-zero on any required check), bash-3.2 safe, composable checks/ (versions,tools,env,docker) + gated (ssh,dns) that WARN-skip until the stack is configured. - env check honors D2 (passphrase presence only, never printed). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
188e30e23e
commit
edc708b826
12 changed files with 763 additions and 0 deletions
89
preflight/checks/tools.sh
Executable file
89
preflight/checks/tools.sh
Executable file
|
|
@ -0,0 +1,89 @@
|
|||
#!/usr/bin/env bash
|
||||
# -----------------------------------------------------------------------------
|
||||
# checks/tools.sh — every required host tool is present and >= its VERSIONS pin.
|
||||
# Reads TOOL_<X>_MIN from foundation/VERSIONS (PLAN-002 §9.1 host validation).
|
||||
# Exits non-zero if any required tool is missing or below its minimum.
|
||||
# -----------------------------------------------------------------------------
|
||||
set -euo pipefail
|
||||
PF_DIR=$(cd "$(dirname "$0")/.." && pwd)
|
||||
# shellcheck source=../lib/common.sh
|
||||
. "$PF_DIR/lib/common.sh"
|
||||
|
||||
echo "[tools] required host tools present and >= VERSIONS pin"
|
||||
|
||||
# pf_get_version <tool> : echo a parseable version string for the tool, or "".
|
||||
# Kept in one place so the per-tool quirks are visible and testable.
|
||||
pf_get_version() {
|
||||
case "$1" in
|
||||
pulumi) pulumi version 2>/dev/null ;; # -> v3.243.0
|
||||
bun) bun --version 2>/dev/null ;; # -> 1.3.9
|
||||
node) node --version 2>/dev/null ;; # -> v24.10.0
|
||||
docker) docker --version 2>/dev/null | sed 's/.*version //' ;; # Docker version 29.5.3, build ...
|
||||
git) git --version 2>/dev/null ;; # git version 2.54.0
|
||||
age) age --version 2>/dev/null ;; # v1.1.1 (or "1.1.1")
|
||||
zstd) zstd --version 2>/dev/null | sed -n 's/.*[ vV]\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/p' ;; # *** Zstandard CLI (64-bit) v1.5.7, ...
|
||||
jq) jq --version 2>/dev/null ;; # jq-1.8.1
|
||||
vault) vault --version 2>/dev/null ;; # Vault v1.18.0 (...)
|
||||
psql) psql --version 2>/dev/null ;; # psql (PostgreSQL) 16.2
|
||||
pg_dump) pg_dump --version 2>/dev/null ;; # pg_dump (PostgreSQL) 16.2
|
||||
ssh) ssh -V 2>&1 ;; # OpenSSH_10.2p1, LibreSSL ...
|
||||
mc) mc --version 2>/dev/null | head -1 ;; # mc version RELEASE.2025-08-13T08-35-41Z
|
||||
*) printf '' ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# pf_check_tool <bin> <VERSIONS_KEY> <pretty-name>
|
||||
pf_check_tool() {
|
||||
bin="$1"; key="$2"; pretty="$3"
|
||||
min=$(pf_versions_get "$key" 2>/dev/null || true)
|
||||
if [ -z "$min" ]; then
|
||||
pf_fail "$pretty: no $key in VERSIONS (cannot determine minimum)"
|
||||
return
|
||||
fi
|
||||
if ! pf_have "$bin"; then
|
||||
pf_fail "$pretty ($bin): NOT INSTALLED (need >= $min)"
|
||||
return
|
||||
fi
|
||||
raw=$(pf_get_version "$bin" || true)
|
||||
# mc uses a date-stamped RELEASE.YYYY-MM-DD... tag; normalize to a dotted date.
|
||||
if [ "$bin" = "mc" ]; then
|
||||
norm=$(printf '%s' "$raw" | sed -n 's/.*RELEASE\.\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\).*/\1.\2.\3/p')
|
||||
minn=$(printf '%s' "$min" | tr '-' '.')
|
||||
if [ -z "$norm" ]; then
|
||||
pf_warn "$pretty ($bin): present but version unparseable ('$raw'); assuming OK"
|
||||
return
|
||||
fi
|
||||
if pf_ge "$norm" "$minn"; then
|
||||
pf_pass "$pretty ($bin) $norm >= $min"
|
||||
else
|
||||
pf_fail "$pretty ($bin) $norm < required $min"
|
||||
fi
|
||||
return
|
||||
fi
|
||||
if [ -z "$raw" ]; then
|
||||
pf_warn "$pretty ($bin): present but version unparseable; assuming OK"
|
||||
return
|
||||
fi
|
||||
if pf_ge "$raw" "$min"; then
|
||||
pf_pass "$pretty ($bin) $(printf '%s' "$raw" | sed -e 's/^[^0-9]*//' -e 's/[^0-9.].*$//') >= $min"
|
||||
else
|
||||
pf_fail "$pretty ($bin) '$raw' < required $min"
|
||||
fi
|
||||
}
|
||||
|
||||
# bin VERSIONS key pretty name
|
||||
pf_check_tool pulumi TOOL_PULUMI_MIN "Pulumi"
|
||||
pf_check_tool bun TOOL_BUN_MIN "Bun"
|
||||
pf_check_tool node TOOL_NODE_MIN "Node.js"
|
||||
pf_check_tool docker TOOL_DOCKER_MIN "Docker CLI"
|
||||
pf_check_tool git TOOL_GIT_MIN "Git"
|
||||
pf_check_tool age TOOL_AGE_MIN "age"
|
||||
pf_check_tool zstd TOOL_ZSTD_MIN "zstd"
|
||||
pf_check_tool jq TOOL_JQ_MIN "jq"
|
||||
pf_check_tool vault TOOL_VAULT_MIN "Vault CLI"
|
||||
pf_check_tool psql TOOL_PSQL_MIN "PostgreSQL client (psql)"
|
||||
pf_check_tool pg_dump TOOL_PG_DUMP_MIN "PostgreSQL client (pg_dump)"
|
||||
pf_check_tool ssh TOOL_OPENSSH_MIN "OpenSSH client"
|
||||
pf_check_tool mc TOOL_MC_MIN "S3/RustFS client (mc)"
|
||||
|
||||
pf_summary "tools"
|
||||
Loading…
Add table
Add a link
Reference in a new issue