hm_ai_qc_report_tool/deploy/rollback.sh
nickviljoen e772095158 Phase 2: deploy machinery for Dev/Prod cutover
- deploy.sh dev|prod with --dry-run, auto-rollback if /health fails
  within 60s; checkpoint saved to .last_deploy_rollback before reset
- deploy/rollback.sh last|<sha> with the same Docker compose dance
- deploy/health-check.sh — curl wrapper for monitoring/oncall
- deploy/apache-{dev,prod}.conf — Location blocks proxying /hm-aiqc/
  to gunicorn on 127.0.0.1:5050 with X-Script-Name set so wsgi.py's
  ReverseProxied middleware emits prefixed URLs
- deploy/.env.{dev,prod}.example — starter envs with Azure SSO config
2026-05-09 14:08:06 +02:00

75 lines
2.1 KiB
Bash
Executable file

#!/bin/bash
# Emergency rollback for HM AI QC.
#
# Usage:
# rollback.sh last Roll back to the checkpoint saved by deploy.sh
# rollback.sh <commit-hash> Roll back to an explicit commit
#
# Note: Alembic downgrade is intentionally NOT run here — schema rollbacks
# are risky on data-bearing tables. If the bad deploy added a column the
# rolled-back code doesn't know about, that's almost always fine. If it
# dropped or renamed a column, restore from the daily DB backup.
set -euo pipefail
APP_DIR=${APP_DIR:-/opt/hm-aiqc}
HEALTH_URL=${HEALTH_URL:-http://127.0.0.1:5050/health}
ROLLBACK_FILE="$APP_DIR/.last_deploy_rollback"
TARGET=${1:-}
if [[ -z "$TARGET" || "$TARGET" == "last" ]]; then
if [[ ! -f "$ROLLBACK_FILE" ]]; then
echo "No .last_deploy_rollback file. Specify a commit hash explicitly."
echo "Usage: $(basename "$0") last | <commit-hash>"
exit 1
fi
TARGET=$(cat "$ROLLBACK_FILE")
fi
cd "$APP_DIR"
if ! git rev-parse --verify --quiet "$TARGET^{commit}" > /dev/null; then
echo "ERROR: Commit '$TARGET' not found"
exit 1
fi
CURRENT_REV=$(git rev-parse HEAD)
CURRENT_SHORT=$(git rev-parse --short HEAD)
TARGET_REV=$(git rev-parse "$TARGET")
TARGET_SHORT=$(git rev-parse --short "$TARGET")
if [[ "$CURRENT_REV" == "$TARGET_REV" ]]; then
echo "Already at $TARGET_SHORT — nothing to do."
exit 0
fi
echo "============================================"
echo " HM AI QC rollback"
echo "============================================"
echo "Current: $CURRENT_SHORT $(git log -1 --format='%s' HEAD)"
echo "Target: $TARGET_SHORT $(git log -1 --format='%s' "$TARGET")"
echo ""
read -r -p "Proceed? (y/N): " confirm
if [[ ! $confirm =~ ^[Yy]$ ]]; then
echo "Cancelled."
exit 0
fi
git reset --hard "$TARGET_REV"
docker compose build
docker compose up -d
# 60s window — same as deploy.sh
for i in {1..30}; do
sleep 2
if curl -sf -o /dev/null "$HEALTH_URL"; then
echo "Rollback OK. Now at $TARGET_SHORT."
exit 0
fi
done
echo "Service unhealthy after rollback."
echo "docker compose logs --tail=200 web"
exit 1