#!/usr/bin/env bash # Static checks for the host-config templating. No root needed. # ./tests/check-templates.sh set -euo pipefail cd "$(dirname "$(readlink -f "$0")")/.." fail=0 ok() { echo "ok - $*"; } bad() { echo "FAIL - $*"; fail=1; } # 1. shell syntax for f in deploy.sh failover/sync-usb-backup.sh failover/sync-sd-backup.sh tests/check-templates.sh; do if bash -n "$f"; then ok "bash -n $f"; else bad "bash -n $f"; fi done # 3. every host file passes deploy.sh --check (validates vars, renders all templates) for c in hosts/*.conf; do if out=$(./deploy.sh --check "$c" 2>&1); then ok "--check $c" else bad "--check $c"; echo "$out" | sed 's/^/ /' fi done # 4. the example defines exactly the variables deploy.sh knows about known=$(sed -n '/^REQUIRED_VARS=(/,/^)/p;/^OPTIONAL_VARS=(/,/^)/p' deploy.sh \ | grep -vE '^[A-Z_]+=\(|^\)' | tr -s ' \t' '\n' | grep -v '^$' | sort || true) defined=$(grep -oE '^[A-Z][A-Z0-9_]*=' hosts/vanlink.conf.example 2>/dev/null | tr -d = | sort || true) if [ -n "$known" ] && [ "$known" = "$defined" ]; then ok "hosts/vanlink.conf.example defines exactly the variables deploy.sh knows" else bad "hosts/vanlink.conf.example differs from deploy.sh's variable lists" diff <(echo "$known") <(echo "$defined") | sed 's/^/ /' || true fi # 2. every file carrying an @TOKEN@ is installed through install_rendered # (plain `install` would ship the placeholder unrendered — the 2026-09-23 failure) # vanrouter.js: installed by the loop in the cockpit block; 50-van-wan.yaml: reference copy, # rendered by hand via `deploy.sh render` (deploy.sh only warns when it differs) exempt=" cockpit/vanrouter/vanrouter.js ap/50-van-wan.yaml " for f in $(./deploy.sh --templates); do case "$exempt" in *" $f "*) continue ;; esac if grep -qE "^[[:space:]]*install_rendered +$f[[:space:]]" deploy.sh; then ok "install_rendered $f" else bad "$f contains an @TOKEN@ but deploy.sh does not install it with install_rendered" fi done # 5. host-specific values land in the rendered output r() { VANLINK_CONF="hosts/$1.conf" ./deploy.sh render "$2"; } expect() { # expect if r "$1" "$2" | grep -qF -- "$3"; then ok "$1: $2 has '$3'"; else bad "$1: $2 lacks '$3'"; fi } expect van ap/nftables.conf 'ip saddr 10.42.1.0/24' expect wan ap/nftables.conf 'ip saddr 10.42.0.0/24' expect van ap/van-br0-setup.service 'brctl addif br0 enP1p17s0' expect wan ap/van-br0-setup.service 'brctl addif br0 enx00e04c331140' expect van failover/config.json '"device": "wlan0"' expect van router-status/config.json '"wifi_wan_iface": "wlan0"' expect van failover/van-wlan-watchdog.service 'van-wlan-watchdog wlan0' expect van ap/van-ap-unmanaged.conf 'interface-name:enP1p17s0' expect wan ap/van-ap-unmanaged.conf 'interface-name:enx00e04c331140;interface-name:eth0' expect wan ap/23-van-lan-eth0.network 'Name=eth0' expect van power/nvme-watch-config.json '"nvme_device": ""' if r van ap/van-ap-unmanaged.conf | grep -q 'eth0'; then bad "van: unmanaged-devices must not mention eth0 (ONBOARD_LAN_IFACE is empty)" else ok "van: unmanaged-devices has no eth0" fi # 6. flagged units/paths only appear inside their ENABLE_* guard in deploy.sh. # Convention: guards are column-0 `if [ "$ENABLE_X" = 1 ]; then` ... `fi`, # contents indented (so a nested `fi` never sits in column 0). if awk ' BEGIN { need["van-li3-battery"]="ENABLE_LI3" need["van-nvme-watch"]="ENABLE_NVME_WATCH" need["nvme-watch-config"]="ENABLE_NVME_WATCH" need["homeassistant"]="ENABLE_HA" need["esphome"]="ENABLE_HA" need["frigate"]="ENABLE_FRIGATE" need["cockpit"]="ENABLE_COCKPIT" } /^if \[ "\$ENABLE_[A-Z0-9_]+" = 1 \]/ { match($0, /ENABLE_[A-Z0-9_]+/); guard=substr($0, RSTART, RLENGTH); next } /^fi([[:space:]]|$)/ { guard=""; next } /^[[:space:]]*(#|echo)/ { next } { for (u in need) if (index($0, u) && guard != need[u]) { printf " deploy.sh:%d mentions %s outside an %s guard: %s\n", NR, u, need[u], $0; bad=1 } } END { exit bad } ' deploy.sh; then ok "flagged units are only touched inside their ENABLE_* guard"; else bad "flag gating"; fi # 8. ./deploy.sh --diff runs (no root) and lists rendered files if out=$(./deploy.sh --diff hosts/van.conf 2>&1) && echo "$out" | grep -qE '^(NEW|CHANGED) '; then ok "deploy.sh --diff hosts/van.conf" else bad "deploy.sh --diff hosts/van.conf"; echo "$out" | sed 's/^/ /' fi exit "$fail"