#!/usr/bin/env bash set -euo pipefail cd "$(dirname "$0")/.." PID_FILE=/tmp/kraiken-watcher.pid PROJECT_NAME=${COMPOSE_PROJECT_NAME:-$(basename "$PWD")} start_stack() { if [[ -f "$PID_FILE" ]]; then local existing_pid existing_pid=$(cat "$PID_FILE") if kill -0 "$existing_pid" 2>/dev/null; then echo "Stopping existing kraiken-lib watcher ($existing_pid)..." kill "$existing_pid" 2>/dev/null || true wait "$existing_pid" 2>/dev/null || true fi rm -f "$PID_FILE" fi # Show branch if set if [[ -n "${GIT_BRANCH:-}" ]]; then echo "Branch: $GIT_BRANCH" fi echo "Building kraiken-lib..." ./scripts/build-kraiken-lib.sh echo "Starting stack..." # Start services in strict dependency order with explicit create+start # This avoids podman dependency graph issues # Create all containers first (without starting) echo " Creating containers..." podman-compose up --no-start 2>&1 | grep -v "STEP\|Copying\|Writing\|Getting\|fetch\|Installing\|Executing" || true # Phase 1: Start base services (no dependencies) echo " Starting anvil & postgres..." podman-compose start anvil postgres >/dev/null 2>&1 # Wait for base services to be healthy echo " Waiting for anvil & postgres..." for i in {1..30}; do anvil_healthy=$(podman healthcheck run harb_anvil_1 >/dev/null 2>&1 && echo "yes" || echo "no") postgres_healthy=$(podman healthcheck run harb_postgres_1 >/dev/null 2>&1 && echo "yes" || echo "no") if [[ "$anvil_healthy" == "yes" ]] && [[ "$postgres_healthy" == "yes" ]]; then break fi sleep 2 done # Phase 2: Start bootstrap (depends on anvil & postgres healthy) echo " Starting bootstrap..." podman-compose start bootstrap >/dev/null 2>&1 # Wait for bootstrap to complete echo " Waiting for bootstrap..." for i in {1..60}; do bootstrap_status=$(podman inspect harb_bootstrap_1 --format='{{.State.Status}}') if [[ "$bootstrap_status" == "exited" ]]; then break fi sleep 2 done # Phase 3: Start ponder (depends on bootstrap completed) echo " Starting ponder..." podman-compose start ponder >/dev/null 2>&1 # Wait for ponder to be healthy echo " Waiting for ponder..." for i in {1..60}; do ponder_healthy=$(podman healthcheck run harb_ponder_1 >/dev/null 2>&1 && echo "yes" || echo "no") if [[ "$ponder_healthy" == "yes" ]]; then break fi sleep 2 done # Phase 4: Start frontend services (depend on ponder healthy) echo " Starting webapp, landing, txn-bot..." podman-compose start webapp landing txn-bot >/dev/null 2>&1 # Phase 5: Start caddy (depends on frontend services) sleep 5 echo " Starting caddy..." podman-compose start caddy >/dev/null 2>&1 echo "Watching for kraiken-lib changes..." ./scripts/watch-kraiken-lib.sh & echo $! > "$PID_FILE" echo "" echo "[ok] Stack started" echo " Web App: http://localhost:8081/app/" echo " GraphQL: http://localhost:8081/graphql" } stop_stack() { if [[ -f "$PID_FILE" ]]; then local watcher_pid watcher_pid=$(cat "$PID_FILE") if kill "$watcher_pid" 2>/dev/null; then wait "$watcher_pid" 2>/dev/null || true fi rm -f "$PID_FILE" fi podman-compose down echo "[ok] Stack stopped" } check_health() { echo "Checking health..." local services=(anvil postgres ponder webapp landing txn-bot caddy) for service in "${services[@]}"; do local container container=$(podman ps --all \ --filter "label=com.docker.compose.project=${PROJECT_NAME}" \ --filter "label=com.docker.compose.service=${service}" \ --format '{{.Names}}' | head -n1) if [[ -z "$container" ]]; then echo " [??] $service (not created)" continue fi if podman healthcheck run "$container" &>/dev/null; then echo " [ok] $service" else echo " [!!] $service" fi done } restart_light() { echo "Light restart: webapp + txn-bot only..." echo " Preserving Anvil state (contracts remain deployed)" local webapp_container txnbot_container webapp_container=$(podman ps --all \ --filter "label=com.docker.compose.project=${PROJECT_NAME}" \ --filter "label=com.docker.compose.service=webapp" \ --format '{{.Names}}' | head -n1) txnbot_container=$(podman ps --all \ --filter "label=com.docker.compose.project=${PROJECT_NAME}" \ --filter "label=com.docker.compose.service=txn-bot" \ --format '{{.Names}}' | head -n1) if [[ -z "$webapp_container" ]]; then echo "[!!] webapp container not found - run './scripts/dev.sh start' first" exit 1 fi local start_time=$(date +%s) echo " Restarting containers..." podman restart "$webapp_container" >/dev/null [[ -n "$txnbot_container" ]] && podman restart "$txnbot_container" >/dev/null echo " Waiting for webapp to be ready..." local max_attempts=30 local attempt=0 while ((attempt < max_attempts)); do if curl -s -f -o /dev/null http://localhost:5173/app/ 2>/dev/null; then local end_time=$(date +%s) local duration=$((end_time - start_time)) echo "[ok] Light restart complete (~${duration}s)" echo " Web App: http://localhost:8081/app/" return 0 fi sleep 2 ((attempt++)) done echo "[!!] Webapp failed to respond after ${max_attempts} attempts" exit 1 } restart_full() { echo "Full restart: all containers + bootstrap..." stop_stack start_stack echo "[ok] Full restart complete" } usage() { cat <