#!/usr/bin/env bash # Deploys the freshly-pushed :latest images to the persistent LAN novelly stack and # waits for the API to report healthy. Unlike a throwaway QA stack, `down` is run # without `-v` — the novelly-data volume (the author's actual novel) must survive # every redeploy. Recreating containers against an unchanged image is a no-op, so # this is safe to re-run. set -euo pipefail cd "$(dirname "${BASH_SOURCE[0]}")" && source ./lib.sh cd "$CI_ROOT" image_names registry_login export API_IMAGE WEB_IMAGE export ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:-}" export WEB_PORT="${WEB_PORT:-6173}" COMPOSE="docker compose -f deploy/qa/docker-compose.qa.yml" log "Pulling latest :latest images" $COMPOSE pull # Applies pending migrations against the live novelly-data volume using the new image, # before the running (old-image) stack is touched. If a migration is broken, this fails # here and the old containers keep serving traffic — `down`/`up` below never runs, so # there is nothing to roll back. log "Running preflight migration check" if ! $COMPOSE --profile tools run --rm migrate; then fail "migration failed against the new image; old novelly stack left running untouched" fi log "Recreating the novelly stack (data volume preserved)" $COMPOSE down $COMPOSE up -d log "Waiting for the API health check" attempts=30 until $COMPOSE exec -T api curl -fsS http://localhost:8080/api/health > /dev/null 2>&1; do attempts=$((attempts - 1)) if [[ "$attempts" -le 0 ]]; then fail "novelly stack did not become healthy in time" fi sleep 2 done log "novelly deployed and healthy at http://localhost:${WEB_PORT}"