Files
igny8/scripts/ops/deploy-production.sh
IGNY8 VPS (Salman) 4a200822bb Dev ops prep
2026-01-21 17:53:42 +00:00

146 lines
4.5 KiB
Bash

#!/bin/bash
# =============================================================================
# IGNY8 Deploy to Production
# =============================================================================
# Safely deploys code to production with backup and rollback capability
# Usage: ./deploy-production.sh
# =============================================================================
set -e
APP_DIR="/data/app/igny8"
COMPOSE_FILE="docker-compose.app.yml"
PROJECT_NAME="igny8-app"
# 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 DEPLOYMENT"
echo "=========================================="
echo ""
# Safety confirmation
log_warn "This will deploy to PRODUCTION!"
log_warn "Make sure you have tested on staging first."
echo ""
read -p "Type 'deploy' to continue: " confirm
if [[ "${confirm}" != "deploy" ]]; then
log "Deployment cancelled"
exit 0
fi
cd "${APP_DIR}"
# Verify on main branch
CURRENT_BRANCH=$(git branch --show-current)
if [[ "${CURRENT_BRANCH}" != "main" ]]; then
log_error "Not on main branch (currently on: ${CURRENT_BRANCH})"
log "Switch to main: git checkout main && git pull"
exit 1
fi
# Step 1: Create pre-deploy backup
log "Step 1/8: Creating pre-deploy backup..."
/data/app/igny8/scripts/ops/backup-db.sh pre-deploy
log_success "Backup created"
# Step 2: Tag current images for rollback
log "Step 2/8: Tagging current images for rollback..."
docker tag igny8-backend:latest igny8-backend:rollback 2>/dev/null || true
docker tag igny8-frontend-dev:latest igny8-frontend-dev:rollback 2>/dev/null || true
docker tag igny8-marketing-dev:latest igny8-marketing-dev:rollback 2>/dev/null || true
log_success "Rollback images tagged"
# Step 3: Pull latest code
log "Step 3/8: Pulling latest code..."
git pull origin main
log_success "Code updated"
# Step 4: Build new images
log "Step 4/8: Building new images..."
docker build -t igny8-backend:latest -f backend/Dockerfile backend/
docker build -t igny8-frontend-dev:latest -f frontend/Dockerfile.dev frontend/
docker build -t igny8-marketing-dev:latest -f frontend/Dockerfile.marketing.dev frontend/
log_success "Images built"
# Step 5: Check for pending migrations
log "Step 5/8: Checking for pending migrations..."
PENDING=$(docker exec igny8_backend python manage.py showmigrations --plan 2>/dev/null | grep "\[ \]" || true)
if [[ -n "${PENDING}" ]]; then
log_warn "Pending migrations found:"
echo "${PENDING}"
read -p "Apply migrations? (yes/no): " apply_migrations
if [[ "${apply_migrations}" != "yes" ]]; then
log "Skipping migrations"
fi
fi
# Step 6: Restart containers
log "Step 6/8: Restarting containers..."
docker compose -f "${COMPOSE_FILE}" -p "${PROJECT_NAME}" down
docker compose -f "${COMPOSE_FILE}" -p "${PROJECT_NAME}" up -d
# Step 7: Wait for backend to be healthy
log "Step 7/8: 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 become healthy"
log_error "ROLLING BACK..."
/data/app/igny8/scripts/ops/rollback.sh --auto
exit 1
fi
echo -n "."
sleep 2
done
# Step 8: Apply migrations and collect static
log "Step 8/8: Applying migrations and collecting static..."
if [[ "${apply_migrations}" == "yes" ]] || [[ -z "${PENDING}" ]]; then
docker exec igny8_backend python manage.py migrate --noinput
fi
docker exec igny8_backend python manage.py collectstatic --noinput
echo ""
echo "=========================================="
log_success "PRODUCTION DEPLOYMENT COMPLETE"
echo "=========================================="
echo ""
echo "Production is live!"
echo " App: https://app.igny8.com"
echo " API: https://api.igny8.com"
echo ""
echo "Monitor logs for 10 minutes:"
echo " docker compose -f ${COMPOSE_FILE} -p ${PROJECT_NAME} logs -f"
echo ""
echo "If issues occur, rollback:"
echo " /data/app/igny8/scripts/ops/rollback.sh"
echo ""
echo "Container status:"
docker compose -f "${COMPOSE_FILE}" -p "${PROJECT_NAME}" ps
echo "=========================================="