#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" . "$ROOT_DIR/scripts/lib.sh" load_env # Determine rollback target TARGET_TAG="${1:-}" if [ -z "$TARGET_TAG" ]; then PREV_TAG_FILE="$ROOT_DIR/.deploy-state/previous-image-tag.txt" [ -f "$PREV_TAG_FILE" ] || fail_json "XUQM_PRIVATE_4030" \ "no previous version recorded; pass target version as argument" "rollback" TARGET_TAG="$(cat "$PREV_TAG_FILE" | tr -d '[:space:]')" fi CURRENT_TAG="${IMAGE_TAG:-$(cat "$ROOT_DIR/VERSION" | tr -d '[:space:]')}" audit "rollback" "STARTED" "from=$CURRENT_TAG to=$TARGET_TAG" progress "rollback" "STARTED" "from=$CURRENT_TAG to=$TARGET_TAG" printf 'Rolling back from %s to %s\n' "$CURRENT_TAG" "$TARGET_TAG" # Confirm unless running in CI if [ -t 0 ]; then printf 'Confirm rollback to %s (y/N): ' "$TARGET_TAG" read -r CONFIRM [ "$CONFIRM" = "y" ] || { printf 'Rollback cancelled.\n'; exit 0; } fi # Save current tag as future rollback point printf '%s\n' "$CURRENT_TAG" > "$ROOT_DIR/.deploy-state/previous-image-tag.txt" # Switch to target tag set_env_value "$ROOT_DIR/.env" "IMAGE_TAG" "$TARGET_TAG" set_env_value "$ROOT_DIR/.env" "PRIVATE_VERSION" "$TARGET_TAG" load_env # Pull target images PROFILES="${COMPOSE_PROFILES:-base}" COMPOSE_PROFILES="$PROFILES" compose pull "$ROOT_DIR/scripts/render-config.sh" COMPOSE_PROFILES="$PROFILES" compose up -d --remove-orphans if ! "$ROOT_DIR/scripts/healthcheck.sh"; then fail_json "XUQM_PRIVATE_4031" "health check failed after rollback to $TARGET_TAG" "rollback" fi printf '%s\n' "$TARGET_TAG" > "$ROOT_DIR/VERSION" audit "rollback" "DONE" "from=$CURRENT_TAG to=$TARGET_TAG" progress "rollback" "DONE" "from=$CURRENT_TAG to=$TARGET_TAG" printf 'Rollback complete: %s → %s\n' "$CURRENT_TAG" "$TARGET_TAG"