#!/bin/bash # Emergency rollback for AI QC. # # Usage: # rollback.sh last Roll back to the checkpoint saved by deploy.sh # rollback.sh Roll back to an explicit commit set -euo pipefail APP_DIR=/opt/ai_qc SERVICE=ai-qc.service HEALTH_URL=http://127.0.0.1:7183/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 | " 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 " 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" sudo systemctl restart "$SERVICE" sleep 3 if curl -sf -o /dev/null "$HEALTH_URL"; then echo "Rollback OK. Now at $TARGET_SHORT." exit 0 fi echo "Service unhealthy after rollback." echo "sudo journalctl -u $SERVICE -n 100" exit 1