From a3e3206b061c2e26134bad3c0b266583e965d925 Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 24 Mar 2026 10:33:25 +0700 Subject: [PATCH] 260324:1033 fix ci-deploy : optimize #05 --- .gitea/workflows/ci-deploy.yml | 11 +- scripts/deploy.sh | 202 ++++++--------------------------- 2 files changed, 40 insertions(+), 173 deletions(-) diff --git a/.gitea/workflows/ci-deploy.yml b/.gitea/workflows/ci-deploy.yml index f7110f6..1fda2a2 100644 --- a/.gitea/workflows/ci-deploy.yml +++ b/.gitea/workflows/ci-deploy.yml @@ -102,14 +102,9 @@ jobs: # Ensure scripts are executable chmod +x scripts/deploy.sh scripts/rollback.sh 2>/dev/null || true - echo "🚀 Executing Blue-Green deployment..." - # Execute deployment with proper logging - ./scripts/deploy.sh 2>&1 | tee /share/np-dms/app/logs/deploy-$(date +%Y%m%d-%H%M%S).log + mkdir -p /share/np-dms/app/logs - DEPLOY_STATUS=${PIPESTATUS[0]} - if [ $DEPLOY_STATUS -ne 0 ]; then - echo "✗ Deployment failed with status $DEPLOY_STATUS" - exit 1 - fi + echo "🚀 Executing deployment..." + ./scripts/deploy.sh echo "✓ Deployment completed successfully" diff --git a/scripts/deploy.sh b/scripts/deploy.sh index a7a0b88..31b4153 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -1,60 +1,46 @@ #!/bin/bash # File: scripts/deploy.sh -# LCBP3-DMS Blue-Green Deployment Script -# v1.8.2 - Aligned with specs/04-Infrastructure-OPS/04-04-deployment-guide.md +# LCBP3-DMS Deployment Script v2.0 +# Simple direct deploy: build images → restart stack via docker compose -set -e # Exit on error +set -e -# Configuration -LCBP3_DIR="/share/np-dms/app" -CURRENT_FILE="$LCBP3_DIR/current" -ENV_FILE="$LCBP3_DIR/.env" # Single .env file per user requirement +SOURCE_DIR="/share/np-dms/app/source/lcbp3" +COMPOSE_FILE="$SOURCE_DIR/specs/04-Infrastructure-OPS/04-00-docker-compose/docker-compose-app.yml" +ENV_FILE="/share/np-dms/app/.env" -# Ensure base directory exists (QNAP path fix) -mkdir -p "$LCBP3_DIR" - -# Ensure current file exists -if [ ! -f "$CURRENT_FILE" ]; then - echo "blue" > "$CURRENT_FILE" -fi - -CURRENT=$(cat "$CURRENT_FILE") -TARGET=$([[ "$CURRENT" == "blue" ]] && echo "green" || echo "blue") - -echo "=========================================" -echo "LCBP3-DMS Blue-Green Deployment (v1.8.2)" -echo "Current environment: $CURRENT" -echo "Target environment: $TARGET" -echo "=========================================" - -# Step 1: Database backup (OPTIONAL - disabled per requirement) -echo "[1/9] Database backup skipped (not required)" - -# Step 2: Build latest images directly on QNAP -echo "[2/9] Building latest Docker images from source..." -cd "/share/np-dms/app/source/lcbp3" - -# Extract API_URL for Frontend Build Argument from .env -# Per spec: NEXT_PUBLIC_API_URL should be https://backend.np-dms.work/api API_URL="https://backend.np-dms.work/api" AUTH_URL="https://lcbp3.np-dms.work" +echo "=========================================" +echo "LCBP3-DMS Deployment v2.0" +echo "=========================================" + +# Read overrides from .env if present if [ -f "$ENV_FILE" ]; then ENV_URL=$(grep NEXT_PUBLIC_API_URL "$ENV_FILE" | cut -d '=' -f2 | tr -d '"' | tr -d "'") [ -n "$ENV_URL" ] && API_URL="$ENV_URL" - ENV_AUTH=$(grep AUTH_URL "$ENV_FILE" | cut -d '=' -f2 | tr -d '"' | tr -d "'") [ -n "$ENV_AUTH" ] && AUTH_URL="$ENV_AUTH" fi -echo "Building backend..." +if [ ! -f "$COMPOSE_FILE" ]; then + echo "✗ Compose file not found: $COMPOSE_FILE" + exit 1 +fi + +cd "$SOURCE_DIR" + +# [1/3] Build images +echo "[1/3] Building Docker images..." +echo " Building backend..." docker build -f backend/Dockerfile -t lcbp3-backend:latest . || { echo "✗ Backend build failed!" exit 1 } -echo "Building frontend with API URL: $API_URL, AUTH_URL: $AUTH_URL..." +echo " Building frontend (API: $API_URL)..." docker build -f frontend/Dockerfile \ --build-arg NEXT_PUBLIC_API_URL="$API_URL" \ --build-arg AUTH_URL="$AUTH_URL" \ @@ -62,145 +48,31 @@ docker build -f frontend/Dockerfile \ echo "✗ Frontend build failed!" exit 1 } +echo "✓ Images built" -echo "✓ Images built successfully" +# [2/3] Start / restart stack with new images +echo "[2/3] Starting application stack..." +docker compose -f "$COMPOSE_FILE" up -d --force-recreate +echo "✓ Stack started" -# Ensure target environment directory exists -mkdir -p "$LCBP3_DIR/$TARGET" - -# Copy compose file from source to target directory -SOURCE_COMPOSE="/share/np-dms/app/source/lcbp3/specs/04-Infrastructure-OPS/04-00-docker-compose/docker-compose-app.yml" -TARGET_COMPOSE="$LCBP3_DIR/$TARGET/docker-compose.yml" - -if [ -f "$SOURCE_COMPOSE" ]; then - cp "$SOURCE_COMPOSE" "$TARGET_COMPOSE" - echo "✓ Compose file copied to $TARGET environment" -else - echo "✗ Source compose file not found at $SOURCE_COMPOSE" - exit 1 -fi - -# Move correctly to target directory for docker-compose up -cd "$LCBP3_DIR/$TARGET" - -# Step 3: Update configuration -echo "[3/9] Updating configuration..." -# Copy .env from main location to target environment if needed -if [ -f "$ENV_FILE" ]; then - cp "$ENV_FILE" "$LCBP3_DIR/$TARGET/.env" - echo "✓ Configuration updated from $ENV_FILE" -fi - -# Step 4: Start target environment -echo "[4/9] Starting $TARGET environment..." -docker compose up -d -echo "✓ $TARGET environment started" - -# Step 5: Wait for services to be ready -echo "[5/9] Waiting for services to be healthy..." -sleep 15 - -# Check backend health with proper container name -BACKEND_CONTAINER="backend" -for i in {1..30}; do - if docker exec "$BACKEND_CONTAINER" curl -f http://localhost:3000/health > /dev/null 2>&1 || \ - docker exec "$BACKEND_CONTAINER" curl -f http://localhost:3000/ping > /dev/null 2>&1; then +# [3/3] Health check +echo "[3/3] Waiting for backend to be healthy..." +sleep 10 +for i in $(seq 1 30); do + if docker exec backend curl -sf http://localhost:3000/health > /dev/null 2>&1 || \ + docker exec backend curl -sf http://localhost:3000/ping > /dev/null 2>&1; then echo "✓ Backend is healthy" break fi - if [ $i -eq 30 ]; then - echo "✗ Backend health check failed!" - docker compose logs backend + if [ "$i" -eq 30 ]; then + echo "✗ Backend health check failed after 60s" + docker compose -f "$COMPOSE_FILE" logs backend --tail=50 exit 1 fi - echo " Waiting for backend... ($i/30)" + echo " Waiting... ($i/30)" sleep 2 done -# Step 6: Database migrations (ADR-009 - manual SQL preferred, but run sync) -echo "[6/9] Running database migrations check..." -# Per ADR-009: No TypeORM migrations - manual SQL is preferred -# But we run schema sync for DTO/Entity alignment -docker exec "$BACKEND_CONTAINER" sh -c 'cd /app && node -e "console.log(\"Schema validation check\")"' || echo "Migration check complete" -echo "✓ Migrations stage complete" - -# Step 7: Switch NGINX to target environment (OPTIONAL - skip if managing manually) -echo "[7/9] Switching NGINX to $TARGET..." -NGINX_CONF="$LCBP3_DIR/nginx-proxy/nginx.conf" -NGINX_CONTAINER="lcbp3-nginx" - -# Skip NGINX switch if manually managed -if [ "${SKIP_NGINX_SWITCH:-false}" = "true" ]; then - echo "⚠️ SKIP_NGINX_SWITCH=true - Skipping NGINX switch (managed manually)" - echo " Remember to update $NGINX_CONF manually if needed:" - echo " - lcbp3-${CURRENT}-backend → lcbp3-${TARGET}-backend" - echo " - lcbp3-${CURRENT}-frontend → lcbp3-${TARGET}-frontend" -else - if [ -f "$NGINX_CONF" ]; then - # Backup current config - cp "$NGINX_CONF" "$NGINX_CONF.bak.$(date +%Y%m%d-%H%M%S)" - - # Update upstream servers - sed -i "s/lcbp3-${CURRENT}-backend/lcbp3-${TARGET}-backend/g" "$NGINX_CONF" - sed -i "s/lcbp3-${CURRENT}-frontend/lcbp3-${TARGET}-frontend/g" "$NGINX_CONF" - - # Test and reload NGINX - if docker exec "$NGINX_CONTAINER" nginx -t > /dev/null 2>&1; then - docker exec "$NGINX_CONTAINER" nginx -s reload - echo "✓ NGINX switched to $TARGET" - else - echo "✗ NGINX config test failed! Reverting..." - cp "$NGINX_CONF.bak."* "$NGINX_CONF" - exit 1 - fi - else - echo "⚠️ NGINX config not found at $NGINX_CONF. Skipping switch." - fi -fi - -# Step 8: Verify new environment -echo "[8/9] Verifying new environment via Proxy..." -sleep 5 - -# Try multiple verification methods -VERIFY_SUCCESS=false - -# Method 1: Via NGINX container internal check -if docker exec "$NGINX_CONTAINER" curl -f -k http://backend:3000/health > /dev/null 2>&1 || \ - docker exec "$NGINX_CONTAINER" curl -f -k http://backend:3000/ping > /dev/null 2>&1; then - echo "✓ New environment is responding via internal network" - VERIFY_SUCCESS=true -fi - -# Method 2: Direct container check (fallback) -if [ "$VERIFY_SUCCESS" = false ]; then - if docker exec "$BACKEND_CONTAINER" curl -f http://localhost:3000/health > /dev/null 2>&1 || \ - docker exec "$BACKEND_CONTAINER" curl -f http://localhost:3000/ping > /dev/null 2>&1; then - echo "✓ Backend container is healthy" - VERIFY_SUCCESS=true - fi -fi - -if [ "$VERIFY_SUCCESS" = false ]; then - echo "✗ New environment verification failed!" - echo "Rolling back..." - # Call rollback script if it exists - if [ -f "$LCBP3_DIR/scripts/rollback.sh" ]; then - "$LCBP3_DIR/scripts/rollback.sh" - fi - exit 1 -fi - -# Step 9: Stop old environment -echo "[9/9] Stopping $CURRENT environment..." -cd "$LCBP3_DIR/$CURRENT" -docker compose down || echo "⚠️ Could not stop $CURRENT (may already be stopped)" -echo "✓ $CURRENT environment stopped" - -# Update current pointer -echo "$TARGET" > "$CURRENT_FILE" - echo "=========================================" echo "✓ Deployment completed successfully!" -echo "Active environment: $TARGET" echo "========================================="