#!/bin/bash # ============================================================================= # IGNY8 Deploy to Staging # ============================================================================= # Safely deploys code to staging environment # Usage: ./deploy-staging.sh # ============================================================================= set -e APP_DIR="/data/app/igny8" COMPOSE_FILE="docker-compose.staging.yml" PROJECT_NAME="igny8-staging" # 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 STAGING DEPLOYMENT" echo "==========================================" echo "" cd "${APP_DIR}" # Check if staging compose file exists if [[ ! -f "${COMPOSE_FILE}" ]]; then log_error "Staging compose file not found: ${COMPOSE_FILE}" log "Please create it from the documentation template" exit 1 fi # Check if .env.staging exists if [[ ! -f ".env.staging" ]]; then log_error "Staging environment file not found: .env.staging" log "Please create it from .env.example" exit 1 fi # Step 1: Pull latest code log "Step 1/6: Pulling latest code..." git fetch origin CURRENT_BRANCH=$(git branch --show-current) log "Current branch: ${CURRENT_BRANCH}" if [[ "${CURRENT_BRANCH}" == "staging" ]]; then git pull origin staging elif [[ "${CURRENT_BRANCH}" == "main" ]]; then log_warn "On main branch, switching to staging..." git checkout staging git pull origin staging else log_warn "On feature branch '${CURRENT_BRANCH}', not pulling..." fi # Step 2: Build staging images log "Step 2/6: Building staging images..." docker build -t igny8-backend:staging -f backend/Dockerfile backend/ docker build -t igny8-frontend-dev:staging -f frontend/Dockerfile.dev frontend/ docker build -t igny8-marketing-dev:staging -f frontend/Dockerfile.marketing.dev frontend/ log_success "Images built" # Step 3: Stop existing staging containers log "Step 3/6: Stopping existing staging containers..." docker compose -f "${COMPOSE_FILE}" -p "${PROJECT_NAME}" down 2>/dev/null || true # Step 4: Start staging containers log "Step 4/6: Starting staging containers..." docker compose -f "${COMPOSE_FILE}" -p "${PROJECT_NAME}" up -d # Step 5: Wait for backend to be healthy log "Step 5/6: Waiting for backend to be healthy..." for i in {1..30}; do if docker exec igny8_staging_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" docker logs igny8_staging_backend --tail 50 exit 1 fi echo -n "." sleep 2 done # Step 6: Run migrations log "Step 6/6: Running database migrations..." docker exec igny8_staging_backend python manage.py migrate --noinput docker exec igny8_staging_backend python manage.py collectstatic --noinput echo "" echo "==========================================" log_success "STAGING DEPLOYMENT COMPLETE" echo "==========================================" echo "" echo "Staging environment is ready:" echo " App: https://staging.igny8.com" echo " API: https://staging-api.igny8.com" echo "" echo "View logs:" echo " docker compose -f ${COMPOSE_FILE} -p ${PROJECT_NAME} logs -f" echo "" echo "Container status:" docker compose -f "${COMPOSE_FILE}" -p "${PROJECT_NAME}" ps echo "=========================================="