#!/usr/bin/env bash # Image boot-smoke: prove the backend IMAGE actually boots and serves its contract # (a `docker build` succeeding does not prove the container starts). Builds the image # locally (or uses a provided BACKEND_IMAGE_TAG), runs it + a throwaway TimescaleDB via # docker-compose.test.yml, waits for /healthz, then asserts /healthz and the version # endpoint. Always tears the stack down. # # ./scripts/smoke.sh # build :local and smoke it # BACKEND_IMAGE_TAG=sha-abc123 ./scripts/smoke.sh # smoke a published image (CI) set -euo pipefail cd "$(dirname "$0")/.." export POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-smoke}" # The image to smoke, pulled from the registry (no local build). CI passes the just- # pushed sha (BACKEND_IMAGE_TAG=sha-<12hex>); locally it defaults to a published tag. export BACKEND_IMAGE_TAG="${BACKEND_IMAGE_TAG:-v0.0.2-split-ci}" IMG="${REGISTRY_HOST:-git.thermograph.org}/${BACKEND_IMAGE_PATH:-emi/thermograph-backend/app}:${BACKEND_IMAGE_TAG}" export SMOKE_HOST_PORT="${SMOKE_HOST_PORT:-18137}" COMPOSE=(docker compose -f docker-compose.test.yml) PORT_URL="http://127.0.0.1:${SMOKE_HOST_PORT}" cleanup() { echo "==> tearing down"; "${COMPOSE[@]}" down -v --remove-orphans >/dev/null 2>&1 || true; } trap cleanup EXIT echo "==> pulling $IMG" "${COMPOSE[@]}" pull backend echo "==> starting backend + db ($IMG)" "${COMPOSE[@]}" up -d echo "==> waiting for /healthz (up to 90s)" for i in $(seq 1 45); do if curl -fsS -o /dev/null "$PORT_URL/healthz"; then ok=1; break; fi sleep 2 done [ "${ok:-}" = 1 ] || { echo "!! backend never became healthy"; "${COMPOSE[@]}" logs --tail=40 backend; exit 1; } echo "==> asserting contract" curl -fsS "$PORT_URL/healthz" >/dev/null && echo " /healthz 200 ok" ver=$(curl -fsS "$PORT_URL/api/version") echo " /api/version -> $ver" echo "$ver" | grep -q '"backend_version"[[:space:]]*:[[:space:]]*"2"' \ || { echo "!! /api/version did not report backend_version=2"; exit 1; } echo "==> SMOKE PASSED"