#!/usr/bin/env bash # Pull the latest main and (re)build the XIP stack on the deploy host. # Invoked over SSH by the Gitea Actions workflow on every push to main, # and runnable by hand on the CT for manual redeploys. set -euo pipefail APP_DIR="${XIP_APP_DIR:-/opt/xip}" COMPOSE_FILE="docker-compose.prod.yml" ENV_FILE=".env.prod" cd "$APP_DIR" echo "==> Fetching latest origin/main…" git fetch --all --prune git reset --hard origin/main echo "==> Building + starting the stack…" deploy_up() { docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --build --remove-orphans } # A raced or interrupted previous deploy (e.g. a manual `compose up` overlapping # the automated one) can leave a half-removed / renamed container behind, making # the next recreate fail with "removal of container ... is already in progress". # If the first attempt fails, prune stopped containers and retry once. if ! deploy_up; then echo "!! 'compose up' failed — pruning stopped containers, retrying once in 8s…" docker container prune -f >/dev/null 2>&1 || true sleep 8 deploy_up fi echo "==> Pruning dangling images…" docker image prune -f >/dev/null 2>&1 || true echo "==> Current state:" docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" ps echo "==> Deploy complete."