#!/bin/bash # ============================================================================= # IGNY8 Rollback Script # ============================================================================= # Rolls back production to previous version using tagged images # Usage: ./rollback.sh [--auto] # ============================================================================= set -e APP_DIR="/data/app/igny8" COMPOSE_FILE="docker-compose.app.yml" PROJECT_NAME="igny8-app" AUTO_MODE="${1}" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log() { echo -e "${BLUE}[$(date '+%H:%M:%S')]${NC} $1" } log_success() { echo -e "${GREEN}✅ $1${NC}" } log_warn() { echo -e "${YELLOW}⚠️ $1${NC}" } log_error() { echo -e "${RED}❌ $1${NC}" } echo "==========================================" echo "IGNY8 PRODUCTION ROLLBACK" echo "==========================================" echo "" # Check for rollback images if ! docker image inspect igny8-backend:rollback &>/dev/null; then log_error "No rollback image found!" log "Rollback images are created during deployment." log "To restore from backup, use:" log " /data/app/igny8/scripts/ops/restore-db.sh /data/backups/latest_db.sql.gz" exit 1 fi # Confirmation (unless auto mode) if [[ "${AUTO_MODE}" != "--auto" ]]; then log_warn "This will rollback production to the previous version!" read -p "Type 'rollback' to continue: " confirm if [[ "${confirm}" != "rollback" ]]; then log "Rollback cancelled" exit 0 fi fi cd "${APP_DIR}" # Step 1: Stop current containers log "Step 1/4: Stopping current containers..." docker compose -f "${COMPOSE_FILE}" -p "${PROJECT_NAME}" down # Step 2: Restore rollback images log "Step 2/4: Restoring previous images..." docker tag igny8-backend:rollback igny8-backend:latest docker tag igny8-frontend-dev:rollback igny8-frontend-dev:latest docker tag igny8-marketing-dev:rollback igny8-marketing-dev:latest 2>/dev/null || true log_success "Images restored" # Step 3: Start containers log "Step 3/4: Starting containers with previous version..." docker compose -f "${COMPOSE_FILE}" -p "${PROJECT_NAME}" up -d # Step 4: Wait for backend log "Step 4/4: Waiting for backend to be healthy..." for i in {1..30}; do if docker exec igny8_backend python -c "import urllib.request; urllib.request.urlopen('http://localhost:8010/api/v1/system/status/').read()" 2>/dev/null; then log_success "Backend is healthy" break fi if [[ $i -eq 30 ]]; then log_error "Backend failed to start after rollback" log "Manual intervention required!" exit 1 fi echo -n "." sleep 2 done echo "" echo "==========================================" log_success "ROLLBACK COMPLETE" echo "==========================================" echo "" echo "Production is running on previous version." echo "" echo "If database rollback is also needed:" echo " /data/app/igny8/scripts/ops/restore-db.sh /data/backups/pre-deploy/LATEST/db_igny8_*.sql.gz" echo "" echo "Container status:" docker compose -f "${COMPOSE_FILE}" -p "${PROJECT_NAME}" ps echo "=========================================="