#!/usr/bin/env bash # OPS-1: Compose health smoke test. # Usage: run from repo root: bash deploy/tests/test-compose-health.sh # Expected: compose up, wait for services, curl health endpoint, assert 200 + ok. set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)" COMPOSE_FILE="$REPO_ROOT/deploy/docker-compose.yml" ENV_FILE="$REPO_ROOT/deploy/.env" APP_HOSTNAME="${APP_HOSTNAME:-}" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' pass() { echo -e "${GREEN}PASS${NC} $*"; } fail() { echo -e "${RED}FAIL${NC} $*"; exit 1; } warn() { echo -e "${YELLOW}WARN${NC} $*"; } # ── Prerequisites ────────────────────────────────────────────────────────────── if ! command -v docker &>/dev/null; then warn "docker not found — skipping compose up, continuing with validation-only tests" SKIP_COMPOSE=1 else SKIP_COMPOSE=0 fi if ! command -v curl &>/dev/null; then fail "curl is required for health check" fi # ── Compose up ───────────────────────────────────────────────────────────────── if [ "$SKIP_COMPOSE" -eq 0 ]; then pass "Docker available, proceeding with compose up" if [ ! -f "$ENV_FILE" ]; then fail ".env file not found at $ENV_FILE. Copy .env.example and fill values." fi pass "Starting compose stack..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --build 2>&1 || fail "docker compose up failed" # Wait for services to be healthy pass "Waiting for services to be ready (up to 120s)..." MAX_WAIT=120 WAITED=0 while [ $WAITED -lt $MAX_WAIT ]; do STATUS=$(docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" ps --format json 2>/dev/null | grep -c '"status":"running"' || true) if [ "$STATUS" -eq 2 ]; then pass "Both frontend and fastapi running" break fi sleep 5 WAITED=$((WAITED + 5)) done if [ "$STATUS" -ne 2 ]; then warn "Services did not reach running state within ${MAX_WAIT}s — continuing with direct health check" fi fi # ── Health check ─────────────────────────────────────────────────────────────── HEALTH_URL="https://${APP_HOSTNAME}/api/health" if [ -z "$APP_HOSTNAME" ]; then HEALTH_URL="http://127.0.0.1:18081/api/health" warn "APP_HOSTNAME not set — using direct fastapi port for health check" fi pass "Checking health endpoint: $HEALTH_URL" HTTP_CODE=$(curl -sk -o /dev/null -w '%{http_code}' --max-time 15 "$HEALTH_URL" 2>/dev/null || echo "000") if [ "$HTTP_CODE" = "200" ]; then BODY=$(curl -sk --max-time 15 "$HEALTH_URL" 2>/dev/null) STATUS=$(echo "$BODY" | python3 -c "import sys,json; print(json.load(sys.stdin).get('status',''))" 2>/dev/null || echo "") if [ "$STATUS" = "ok" ]; then pass "OPS-1: Health check passed (HTTP 200, status=ok)" else fail "OPS-1: Health check returned unexpected status: $STATUS" fi else fail "OPS-1: Health check failed with HTTP $HTTP_CODE" fi echo "" echo "=== Compose health test complete ===" exit 0