From 590b8d9afcda100787dd1fe8b40f2543cda803fb Mon Sep 17 00:00:00 2001 From: Mudzz Date: Tue, 4 Mar 2025 10:27:19 +0100 Subject: [PATCH] cd: implement blue/green deployment strategy --- .github/workflows/cd.yml | 62 +++++++++++++++++++++++++++++++++ docker-compose.yml | 51 ++++++++++++++++++++++++++++ nginx.conf | 14 ++++++++ scripts/deploy-blue-green.sh | 66 ++++++++++++++++++++++++++++++++++++ 4 files changed, 193 insertions(+) create mode 100644 .github/workflows/cd.yml create mode 100644 docker-compose.yml create mode 100644 nginx.conf create mode 100644 scripts/deploy-blue-green.sh diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 000000000..5aa43ddd3 --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,62 @@ +name: Continuous Deployment + +on: + workflow_dispatch: + push: + branches: [ main ] + +jobs: + build: + runs-on: self-hosted + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup initial environment + run: | + # Préparation des fichiers de configuration s'ils n'existent pas + if [ ! -f "nginx.conf" ]; then + echo "Creating initial NGINX configuration..." + echo "upstream backend { server app-blue:80; # server app-green:80; }" > nginx.conf + echo "server { listen 80; location / { proxy_pass http://backend; proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; } }" >> nginx.conf + fi + + - name: Build and tag images + run: | + echo "Building Docker image..." + docker build -t angular-app:staging . + docker tag angular-app:staging angular-app:blue + docker tag angular-app:staging angular-app:green + + deploy-staging: + needs: build + runs-on: self-hosted + environment: staging + + steps: + - name: Deploy to staging + run: | + echo "Deploying to staging environment..." + docker-compose up -d app-staging + echo "Deployment to staging completed." + + - name: Verify staging deployment + run: | + echo "Verifying staging deployment..." + sleep 5 + curl -s http://localhost:8080 | grep -q "conduit" && echo "✅ Staging verification successful" || (echo "❌ Staging verification failed" && exit 1) + + deploy-production: + needs: deploy-staging + runs-on: self-hosted + environment: production + + steps: + - name: Checkout for production deployment + uses: actions/checkout@v3 + + - name: Blue/Green Deployment + run: | + echo "Executing Blue/Green deployment..." + ./scripts/deploy-blue-green.sh diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..ad950d1cb --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,51 @@ +version: '3.8' + +services: + # Environnement de staging + app-staging: + image: angular-app:staging + container_name: app-staging + ports: + - "8080:80" + restart: unless-stopped + networks: + - app-network + + # Production Blue + app-blue: + image: angular-app:blue + container_name: app-blue + ports: + - "8081:80" + restart: unless-stopped + networks: + - app-network + + # Production Green + app-green: + image: angular-app:green + container_name: app-green + ports: + - "8082:80" + restart: unless-stopped + networks: + - app-network + + # Proxy NGINX pour Blue/Green + proxy: + image: nginx:alpine + container_name: proxy + ports: + - "80:80" + volumes: + - ./nginx.conf:/etc/nginx/conf.d/default.conf + depends_on: + - app-blue + - app-green + restart: unless-stopped + networks: + - app-network + +networks: + app-network: + driver: bridge diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 000000000..4a11cc3aa --- /dev/null +++ b/nginx.conf @@ -0,0 +1,14 @@ +upstream backend { + server app-blue:80; + # server app-green:80; # Commenté par défaut, sera activé lors du déploiement +} + +server { + listen 80; + + location / { + proxy_pass http://backend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } +} diff --git a/scripts/deploy-blue-green.sh b/scripts/deploy-blue-green.sh new file mode 100644 index 000000000..4f1157047 --- /dev/null +++ b/scripts/deploy-blue-green.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +# Variables +TIMESTAMP=$(date +%s) +CURRENT_ENV="blue" +TARGET_ENV="green" + +# Détection de l'environnement actif +if grep -q "server app-green:80;" nginx.conf && ! grep -q "# server app-green:80;" nginx.conf; then + CURRENT_ENV="green" + TARGET_ENV="blue" +fi + +echo "Current environment: $CURRENT_ENV" +echo "Target environment: $TARGET_ENV" + +# 1. Construction de l'image pour le nouvel environnement +echo "Building image for $TARGET_ENV environment..." +docker build -t angular-app:$TARGET_ENV . + +# 2. Démarrage du conteneur cible (s'il n'est pas déjà actif) +echo "Starting $TARGET_ENV environment..." +docker-compose up -d app-$TARGET_ENV + +# 3. Vérification que le nouvel environnement fonctionne +TARGET_PORT=8081 +if [ "$TARGET_ENV" = "green" ]; then + TARGET_PORT=8082 +fi + +echo "Verifying $TARGET_ENV environment on port $TARGET_PORT..." +sleep 5 +if curl -s http://localhost:$TARGET_PORT | grep -q "conduit"; then + echo "✅ $TARGET_ENV environment is working correctly" +else + echo "❌ $TARGET_ENV environment verification failed" + exit 1 +fi + +# 4. Modification de la configuration NGINX +echo "Updating NGINX configuration..." +if [ "$CURRENT_ENV" = "blue" ]; then + # Activer Green, désactiver Blue + sed -i 's/server app-blue:80;/# server app-blue:80;/' nginx.conf + sed -i 's/# server app-green:80;/server app-green:80;/' nginx.conf +else + # Activer Blue, désactiver Green + sed -i 's/server app-green:80;/# server app-green:80;/' nginx.conf + sed -i 's/# server app-blue:80;/server app-blue:80;/' nginx.conf +fi + +# 5. Rechargement de NGINX +echo "Reloading NGINX configuration..." +docker-compose exec -T proxy nginx -s reload + +# 6. Vérification finale +echo "Verifying final deployment..." +sleep 2 +if curl -s http://localhost:80 | grep -q "conduit"; then + echo "✅ Production deployment successful!" +else + echo "❌ Production verification failed" + exit 1 +fi + +echo "Deployment completed successfully!"