Program.cs: wrap the boot-time MigrateAsync in try/catch (was an unhandled exception into a restart:unless-stopped crash-loop), log critical and exit(1) on failure, and add a --migrate-only flag that applies migrations then exits 0 without starting the web host. deploy.sh: run migrations as a preflight via the new --migrate-only image against the live novelly-data volume, before the running (old-image) stack is touched. A failing migration now aborts the deploy with the old containers still serving traffic, instead of swapping to a crash-looping new container first and finding out from the health-check timeout.
46 lines
1.6 KiB
Bash
Executable File
46 lines
1.6 KiB
Bash
Executable File
#!/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}"
|