#!/usr/bin/env bash # Smoke test for the sm121 add-on image (specs/tech-architecture/ # ha-addon-recipe-repos.md): build the image from the sibling add-on repo # (rust:alpine compiles sm121 from THIS checkout → static musl binary → # alpine final), run the entrypoint with a `file://` recipe repo # (mounted), and assert the dashboard answers on 3100 (curl /api/state). # # scripts/smoke-addon.sh [image] (default sm121-addon:latest) set -euo pipefail cd "$(dirname "$0")/.." IMG="${1:-sm121-addon:latest}" TOKEN=smoke-test # The image source lives in the sibling add-on repo (the HA add-on store). # Build it locally if it isn't there yet (CI builds the registry one). # The Dockerfile's rust:alpine stage compiles the launcher from # launcher-src/ in the build context — rsync this checkout there. HA_REPO="../sm121-ha-integration" if ! docker image inspect "$IMG" >/dev/null 2>&1; then echo "building $IMG (launcher source → $HA_REPO/launcher-src/)" rm -rf "$HA_REPO/launcher-src" rsync -a --exclude .git --exclude target ./ "$HA_REPO/launcher-src/" docker build -q -t "$IMG" -f "$HA_REPO/sm121/Dockerfile" "$HA_REPO/" fi # A minimal `file://` recipe repo, mounted read-only at /repos. It lives # under target/ (gitignored) so it sits on a volume the docker VM shares # — colima only mounts /Volumes here; a $HOME tmpdir would mount empty. REPO="$(pwd)/target/smoke-addon-repo" rm -rf "$REPO"; mkdir -p "$REPO" git init -q "$REPO" mkdir -p "$REPO/recipes/demo" echo 'engine = "vllm"' > "$REPO/recipes/demo/recipe.toml" git -C "$REPO" add -A git -C "$REPO" -c user.email=t@sm121.test -c user.name=sm121-test commit -qm init # Persistent HOME (the add-on data folder in HA; here: the sm121 cache # dir — ~/.cache/sm121 — so re-runs reuse the recipe-repo cache). HOMEV="$(pwd)/target/smoke-addon-home" mkdir -p "$HOMEV" CID="$(docker run -d \ -p 3100:3100 \ -v "$REPO":/repos:ro \ -v "$HOMEV":/root \ -e SM121_RECIPE_REPOS='[{"url":"file:///repos"}]' \ -e SM121_SSH_USER=u \ -e SM121_WEB_TOKEN="$TOKEN" \ "$IMG")" trap 'docker rm -f "$CID" >/dev/null 2>&1 || true; rm -rf "$REPO"' EXIT # First boot is fast now (the binary ships in the image — just the # recipe-repo sync); give it 60 s to be safe. ok="" for _ in $(seq 1 60); do if curl -sf -H "Authorization: Bearer $TOKEN" \ http://127.0.0.1:3100/api/state >/dev/null 2>&1; then ok=1 break fi sleep 1 done echo "--- container log (tail) ---" docker logs "$CID" 2>&1 | tail -5 if [ -n "$ok" ]; then echo "--- /api/state (first 200 chars) ---" curl -sf -H "Authorization: Bearer $TOKEN" http://127.0.0.1:3100/api/state | head -c 200 echo echo "smoke OK: the add-on dashboard answered on 3100" else echo "smoke FAILED: no answer on 3100" >&2 exit 1 fi