diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index fbaf0ce..7b2680d 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -24,54 +24,106 @@ jobs: set -e cd /opt/wordly - echo "=== Git pull ===" + # ────────────────────────────────────────────── + # 1. GIT PULL + # ────────────────────────────────────────────── + echo "=== [1/8] Git pull ===" git config --global --add safe.directory /opt/wordly git fetch origin production-deployment git reset --hard origin/production-deployment - echo "=== Building images ===" + # ────────────────────────────────────────────── + # 2. DATABASE BACKUP (before anything else) + # ────────────────────────────────────────────── + echo "=== [2/8] Database backup ===" + BACKUP_DIR="/opt/backups/postgres" + BACKUP_FILE="${BACKUP_DIR}/translate_db_$(date +%Y%m%d_%H%M%S).sql.gz" + mkdir -p "$BACKUP_DIR" + + docker compose exec -T postgres pg_dumpall -U translate | gzip > "$BACKUP_FILE" + BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1) + echo " ✅ Backup saved: ${BACKUP_FILE} (${BACKUP_SIZE})" + + # Keep only last 10 backups + ls -t "${BACKUP_DIR}"/translate_db_*.sql.gz | tail -n +11 | xargs -r rm -- + echo " 📦 Retained last 10 backups" + + # ────────────────────────────────────────────── + # 3. BUILD IMAGES + # ────────────────────────────────────────────── + echo "=== [3/8] Building images ===" docker compose build backend frontend - echo "=== Starting services ===" + # ────────────────────────────────────────────── + # 4. START SERVICES + # ────────────────────────────────────────────── + echo "=== [4/8] Starting services ===" docker compose up -d --remove-orphans - echo "=== Waiting for postgres ===" + # ────────────────────────────────────────────── + # 5. WAIT FOR POSTGRES + # ────────────────────────────────────────────── + echo "=== [5/8] Waiting for postgres ===" for i in $(seq 1 30); do if docker compose exec -T postgres pg_isready -U translate >/dev/null 2>&1; then - echo "Postgres ready after $((i * 2))s" + echo " ✅ Postgres ready after $((i * 2))s" break fi if [ "$i" -eq 30 ]; then - echo "ERROR: Postgres not ready after 60s" + echo " ❌ Postgres not ready after 60s" docker compose logs postgres --tail=30 exit 1 fi sleep 2 done - echo "=== Running database migrations (one-shot container) ===" - docker compose run --rm backend alembic upgrade head + # ────────────────────────────────────────────── + # 6. RUN MIGRATIONS (one-shot container) + # ────────────────────────────────────────────── + echo "=== [6/8] Running database migrations ===" + if ! docker compose run --rm backend alembic upgrade head; then + echo " ❌ Migration FAILED!" + echo " ⚠️ Restoring database from backup..." + gunzip -c "$BACKUP_FILE" | docker compose exec -T postgres psql -U translate -d translate_db >/dev/null 2>&1 || true + echo " 🔄 Database restored. Restarting services..." + docker compose restart backend + echo " ❌ Deploy aborted. Database restored from backup." + exit 1 + fi + echo " ✅ Migrations applied" - echo "=== Restarting backend to pick up migration ===" + # Restart backend to pick up new schema docker compose restart backend - echo "=== Waiting for backend healthy ===" + # ────────────────────────────────────────────── + # 7. HEALTH CHECK + # ────────────────────────────────────────────── + echo "=== [7/8] Waiting for backend healthy ===" for i in $(seq 1 20); do if curl -sf http://localhost:8001/health >/dev/null 2>&1; then - echo "Backend healthy after $((i * 5))s" + echo " ✅ Backend healthy after $((i * 5))s" break fi if [ "$i" -eq 20 ]; then - echo "ERROR: Backend not healthy after 100s" + echo " ❌ Backend not healthy after 100s" + echo " ⚠️ Rolling back database..." + gunzip -c "$BACKUP_FILE" | docker compose exec -T postgres psql -U translate -d translate_db >/dev/null 2>&1 || true + docker compose restart backend + echo " ❌ Deploy failed. Database restored." docker compose logs backend --tail=50 exit 1 fi sleep 5 done - echo "=== Deploy summary ===" - docker compose ps + # ────────────────────────────────────────────── + # 8. SUMMARY + # ────────────────────────────────────────────── + echo "=== [8/8] Deploy summary ===" + docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}" + echo "" echo "Health: $(curl -sf http://localhost:8001/health 2>/dev/null || echo 'FAILED')" + echo "Backup: ${BACKUP_FILE} (${BACKUP_SIZE})" ENDSSH - name: Wait for frontend