smoke-addon.sh 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. #!/usr/bin/env bash
  2. # Smoke test for the sm121 add-on image (specs/tech-architecture/
  3. # ha-addon-recipe-repos.md): run the entrypoint with a `file://` recipe
  4. # repo (mounted) + a token, and assert the dashboard answers on 3100
  5. # (curl /api/state).
  6. #
  7. # The thin image compiles sm121 from the launcher repo on first boot —
  8. # hermetically, from THIS checkout via file:// (SM121_LAUNCHER_URL), with
  9. # the cargo target dir persisted in a volume (re-runs are incremental).
  10. #
  11. # scripts/smoke-addon.sh [image] (default sm121-addon:latest)
  12. set -euo pipefail
  13. cd "$(dirname "$0")/.."
  14. IMG="${1:-sm121-addon:latest}"
  15. TOKEN=smoke-test
  16. # The image source lives in the sibling add-on repo (the HA add-on store).
  17. # Build it locally if it isn't there yet (CI builds the registry one).
  18. if ! docker image inspect "$IMG" >/dev/null 2>&1; then
  19. echo "building $IMG from ../sm121-ha-integration/sm121/"
  20. docker build -q -t "$IMG" -f ../sm121-ha-integration/sm121/Dockerfile ../sm121-ha-integration/sm121/
  21. fi
  22. # A minimal `file://` recipe repo, mounted read-only at /repos. It lives
  23. # under target/ (gitignored) so it sits on a volume the docker VM shares
  24. # — colima only mounts /Volumes here; a $HOME tmpdir would mount empty.
  25. REPO="$(pwd)/target/smoke-addon-repo"
  26. rm -rf "$REPO"; mkdir -p "$REPO"
  27. git init -q "$REPO"
  28. mkdir -p "$REPO/recipes/demo"
  29. echo 'engine = "vllm"' > "$REPO/recipes/demo/recipe.toml"
  30. git -C "$REPO" add -A
  31. git -C "$REPO" -c user.email=t@sm121.test -c user.name=sm121-test commit -qm init
  32. # Persistent HOME (the add-on data folder in HA; here: the sm121 binary +
  33. # the cargo target cache, so re-runs don't rebuild the world).
  34. HOMEV="$(pwd)/target/smoke-addon-home"
  35. mkdir -p "$HOMEV"
  36. CID="$(docker run -d \
  37. -p 3100:3100 \
  38. -v "$REPO":/repos:ro \
  39. -v "$HOMEV":/root \
  40. -v "$(pwd)":/src-launcher:ro \
  41. -e SM121_RECIPE_REPOS='[{"url":"file:///repos"}]' \
  42. -e SM121_LAUNCHER_URL="file:///src-launcher" \
  43. -e SM121_LAUNCHER_REV=HEAD \
  44. -e SM121_SSH_USER=u \
  45. -e SM121_WEB_TOKEN="$TOKEN" \
  46. "$IMG")"
  47. trap 'docker rm -f "$CID" >/dev/null 2>&1 || true; rm -rf "$REPO"' EXIT
  48. # Wait for the dashboard (up to 8 min — the first run compiles sm121 from
  49. # source; a warm cache is seconds).
  50. ok=""
  51. for _ in $(seq 1 480); do
  52. if curl -sf -H "Authorization: Bearer $TOKEN" \
  53. http://127.0.0.1:3100/api/state >/dev/null 2>&1; then
  54. ok=1
  55. break
  56. fi
  57. sleep 1
  58. done
  59. echo "--- container log (tail) ---"
  60. docker logs "$CID" 2>&1 | tail -5
  61. if [ -n "$ok" ]; then
  62. echo "--- /api/state (first 200 chars) ---"
  63. curl -sf -H "Authorization: Bearer $TOKEN" http://127.0.0.1:3100/api/state | head -c 200
  64. echo
  65. echo "smoke OK: the add-on dashboard answered on 3100"
  66. else
  67. echo "smoke FAILED: no answer on 3100" >&2
  68. exit 1
  69. fi