# CI/CD Workflow - Xpeditis PreProd Ce document décrit le pipeline CI/CD automatisé pour déployer Xpeditis sur l'environnement de préproduction. ## Vue d'Ensemble Le pipeline CI/CD s'exécute automatiquement à chaque push ou pull request sur la branche `preprod`. Il effectue les opérations suivantes : ``` ┌─────────────────────────────────────────────────────────────────┐ │ TRIGGER: Push sur preprod │ └────────────────────────┬────────────────────────────────────────┘ │ ┌───────────────┴───────────────┐ │ │ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ │ Backend Build │ │ Frontend Build │ │ & Test │ │ & Test │ │ │ │ │ │ • ESLint │ │ • ESLint │ │ • Unit Tests │ │ • Type Check │ │ • Integration │ │ • Build Next.js │ │ • Build NestJS │ │ │ └────────┬─────────┘ └────────┬─────────┘ │ │ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ │ Backend Docker │ │ Frontend Docker │ │ Build & Push │ │ Build & Push │ │ │ │ │ │ • Build Image │ │ • Build Image │ │ • Push to SCW │ │ • Push to SCW │ │ • Tag: preprod │ │ • Tag: preprod │ └────────┬─────────┘ └────────┬─────────┘ │ │ └───────────────┬───────────────┘ │ ▼ ┌────────────────┐ │ Deploy PreProd │ │ │ │ • Portainer │ │ Webhook │ │ • Health Check │ │ • Notification │ └────────┬───────┘ │ ▼ ┌────────────────┐ │ Smoke Tests │ │ │ │ • API Health │ │ • Endpoints │ │ • Frontend │ └────────────────┘ ``` ## Jobs Détaillés ### 1. Backend Build & Test (~5-7 minutes) **Objectif** : Valider le code backend et s'assurer qu'il compile sans erreur **Étapes** : 1. **Checkout** : Récupère le code source 2. **Setup Node.js** : Configure Node.js 20 avec cache npm 3. **Install Dependencies** : `npm ci` dans `apps/backend` 4. **ESLint** : Vérifie le style et la qualité du code 5. **Unit Tests** : Exécute les tests unitaires (domaine) 6. **Integration Tests** : Lance PostgreSQL + Redis et exécute les tests d'intégration 7. **Build** : Compile TypeScript → JavaScript 8. **Upload Artifacts** : Sauvegarde le dossier `dist` pour inspection **Technologies** : - Node.js 20 - PostgreSQL 15 (container) - Redis 7 (container) - Jest - TypeScript **Conditions d'échec** : - ❌ Erreurs de syntaxe TypeScript - ❌ Tests unitaires échoués - ❌ Tests d'intégration échoués - ❌ Erreurs ESLint --- ### 2. Frontend Build & Test (~4-6 minutes) **Objectif** : Valider le code frontend et s'assurer qu'il compile sans erreur **Étapes** : 1. **Checkout** : Récupère le code source 2. **Setup Node.js** : Configure Node.js 20 avec cache npm 3. **Install Dependencies** : `npm ci` dans `apps/frontend` 4. **ESLint** : Vérifie le style et la qualité du code 5. **Type Check** : Vérifie les types TypeScript (`tsc --noEmit`) 6. **Build** : Compile Next.js avec les variables d'environnement preprod 7. **Upload Artifacts** : Sauvegarde le dossier `.next` pour inspection **Technologies** : - Node.js 20 - Next.js 14 - TypeScript - Tailwind CSS **Variables d'environnement** : ```bash NEXT_PUBLIC_API_URL=https://api-preprod.xpeditis.com NEXT_PUBLIC_WS_URL=wss://api-preprod.xpeditis.com ``` **Conditions d'échec** : - ❌ Erreurs de syntaxe TypeScript - ❌ Erreurs de compilation Next.js - ❌ Erreurs ESLint - ❌ Type errors --- ### 3. Backend Docker Build & Push (~3-5 minutes) **Objectif** : Construire l'image Docker du backend et la pousser vers le registre Scaleway **Étapes** : 1. **Checkout** : Récupère le code source 2. **Setup QEMU** : Support multi-plateforme (ARM64, AMD64) 3. **Setup Buildx** : Builder Docker avancé avec cache 4. **Login Registry** : Authentification Scaleway Container Registry 5. **Extract Metadata** : Génère les tags pour l'image (preprod, preprod-SHA) 6. **Build & Push** : Construit et pousse l'image avec cache layers 7. **Docker Cleanup** : Nettoie les images temporaires **Image produite** : ``` rg.fr-par.scw.cloud/xpeditis/backend:preprod rg.fr-par.scw.cloud/xpeditis/backend:preprod-abc1234 ``` **Cache** : - ✅ Cache des layers Docker pour accélérer les builds suivants - ✅ Cache des dépendances npm **Taille estimée** : ~800 MB (Node.js Alpine + dépendances) --- ### 4. Frontend Docker Build & Push (~3-5 minutes) **Objectif** : Construire l'image Docker du frontend et la pousser vers le registre Scaleway **Étapes** : 1. **Checkout** : Récupère le code source 2. **Setup QEMU** : Support multi-plateforme 3. **Setup Buildx** : Builder Docker avancé avec cache 4. **Login Registry** : Authentification Scaleway Container Registry 5. **Extract Metadata** : Génère les tags pour l'image 6. **Build & Push** : Construit et pousse l'image avec build args 7. **Docker Cleanup** : Nettoie les images temporaires **Build Args** : ```dockerfile NODE_ENV=production NEXT_PUBLIC_API_URL=https://api-preprod.xpeditis.com NEXT_PUBLIC_WS_URL=wss://api-preprod.xpeditis.com ``` **Image produite** : ``` rg.fr-par.scw.cloud/xpeditis/frontend:preprod rg.fr-par.scw.cloud/xpeditis/frontend:preprod-abc1234 ``` **Taille estimée** : ~500 MB (Node.js Alpine + Next.js build) --- ### 5. Deploy to PreProd (~2-3 minutes) **Objectif** : Déployer les nouvelles images sur le serveur preprod via Portainer **Étapes** : #### 5.1 Trigger Backend Webhook ```bash POST https://portainer.xpeditis.com/api/webhooks/xxx-backend { "service": "backend", "image": "rg.fr-par.scw.cloud/xpeditis/backend:preprod", "timestamp": "2025-01-15T10:30:00Z" } ``` **Ce qui se passe côté Portainer** : 1. Portainer reçoit le webhook 2. Pull la nouvelle image `backend:preprod` 3. Effectue un rolling update du service `xpeditis-backend` 4. Démarre les nouveaux conteneurs 5. Arrête les anciens conteneurs (0 downtime) #### 5.2 Wait for Backend Deployment - Attend 30 secondes pour que le backend démarre #### 5.3 Trigger Frontend Webhook ```bash POST https://portainer.xpeditis.com/api/webhooks/xxx-frontend { "service": "frontend", "image": "rg.fr-par.scw.cloud/xpeditis/frontend:preprod", "timestamp": "2025-01-15T10:30:00Z" } ``` #### 5.4 Wait for Frontend Deployment - Attend 30 secondes pour que le frontend démarre #### 5.5 Health Check Backend ```bash # Vérifie que l'API répond (max 10 tentatives) GET https://api-preprod.xpeditis.com/health # Expected: HTTP 200 OK ``` #### 5.6 Health Check Frontend ```bash # Vérifie que le frontend répond (max 10 tentatives) GET https://app-preprod.xpeditis.com # Expected: HTTP 200 OK ``` #### 5.7 Send Notification Envoie une notification Discord (si configuré) avec : - ✅ Statut du déploiement (SUCCESS / FAILED) - 📝 Message du commit - 👤 Auteur du commit - 🔗 URLs des services - ⏰ Timestamp **Exemple de notification Discord** : ``` ✅ Deployment PreProd - SUCCESS Branch: preprod Commit: abc1234 Author: David Message: feat: add CSV booking workflow Backend: https://api-preprod.xpeditis.com Frontend: https://app-preprod.xpeditis.com Timestamp: 2025-01-15T10:30:00Z ``` --- ### 6. Smoke Tests (~1-2 minutes) **Objectif** : Vérifier que les services déployés fonctionnent correctement **Tests Backend** : 1. **Health Endpoint** ```bash GET https://api-preprod.xpeditis.com/health Expected: HTTP 200 OK ``` 2. **Swagger Documentation** ```bash GET https://api-preprod.xpeditis.com/api/docs Expected: HTTP 200 or 301 ``` 3. **Rate Search Endpoint** ```bash POST https://api-preprod.xpeditis.com/api/v1/rates/search-csv Body: { "origin": "NLRTM", "destination": "USNYC", "volumeCBM": 5, "weightKG": 1000, "palletCount": 3 } Expected: HTTP 200 or 401 (unauthorized) ``` **Tests Frontend** : 1. **Homepage** ```bash GET https://app-preprod.xpeditis.com Expected: HTTP 200 OK ``` 2. **Login Page** ```bash GET https://app-preprod.xpeditis.com/login Expected: HTTP 200 OK ``` **Résultat** : ``` ================================================ ✅ All smoke tests passed successfully! ================================================ Backend API: https://api-preprod.xpeditis.com Frontend App: https://app-preprod.xpeditis.com Swagger Docs: https://api-preprod.xpeditis.com/api/docs ================================================ ``` --- ## Durée Totale du Pipeline **Temps estimé** : ~18-26 minutes | Job | Durée | Parallèle | |------------------------|----------|-----------| | Backend Build & Test | 5-7 min | ✅ | | Frontend Build & Test | 4-6 min | ✅ | | Backend Docker | 3-5 min | ✅ | | Frontend Docker | 3-5 min | ✅ | | Deploy PreProd | 2-3 min | ❌ | | Smoke Tests | 1-2 min | ❌ | **Avec parallélisation** : - Build & Test (parallèle) : ~7 min - Docker (parallèle) : ~5 min - Deploy : ~3 min - Tests : ~2 min - **Total** : ~17 minutes --- ## Variables d'Environnement ### Backend (Production) ```bash NODE_ENV=production PORT=4000 DATABASE_HOST=xpeditis-db DATABASE_PORT=5432 DATABASE_USER=xpeditis DATABASE_PASSWORD=*** (secret Portainer) DATABASE_NAME=xpeditis_prod DATABASE_SSL=false REDIS_HOST=xpeditis-redis REDIS_PORT=6379 REDIS_PASSWORD=*** (secret Portainer) JWT_SECRET=*** (secret Portainer) AWS_S3_ENDPOINT=http://xpeditis-minio:9000 AWS_ACCESS_KEY_ID=*** (secret Portainer) AWS_SECRET_ACCESS_KEY=*** (secret Portainer) CORS_ORIGIN=https://app-preprod.xpeditis.com FRONTEND_URL=https://app-preprod.xpeditis.com API_URL=https://api-preprod.xpeditis.com ``` ### Frontend (Build Time) ```bash NODE_ENV=production NEXT_PUBLIC_API_URL=https://api-preprod.xpeditis.com NEXT_PUBLIC_WS_URL=wss://api-preprod.xpeditis.com ``` --- ## Rollback en Cas d'Échec Si un déploiement échoue, vous pouvez facilement revenir à la version précédente : ### Option 1 : Via Portainer UI 1. Allez dans **Stacks** → **xpeditis** 2. Sélectionnez le service (backend ou frontend) 3. Cliquez sur **Rollback** 4. Sélectionnez la version précédente 5. Cliquez sur **Apply** ### Option 2 : Via Portainer API ```bash # Rollback backend curl -X POST "https://portainer.xpeditis.com/api/services/xpeditis_xpeditis-backend/update?version=123" \ -H "X-API-Key: YOUR_API_KEY" \ -d '{"rollback": {"force": true}}' # Rollback frontend curl -X POST "https://portainer.xpeditis.com/api/services/xpeditis_xpeditis-frontend/update?version=456" \ -H "X-API-Key: YOUR_API_KEY" \ -d '{"rollback": {"force": true}}' ``` ### Option 3 : Redéployer une Version Précédente ```bash # Sur votre machine locale git checkout preprod git log # Trouver le SHA du commit précédent # Revenir à un commit précédent git reset --hard abc1234 git push origin preprod --force # Le CI/CD va automatiquement déployer cette version ``` --- ## Monitoring du Pipeline ### Voir les Logs GitHub Actions 1. Allez sur GitHub : `https://github.com/VOTRE_USERNAME/xpeditis/actions` 2. Cliquez sur le workflow en cours 3. Cliquez sur un job pour voir ses logs détaillés ### Voir les Logs des Services Déployés ```bash # Logs backend docker service logs xpeditis_xpeditis-backend -f --tail 100 # Logs frontend docker service logs xpeditis_xpeditis-frontend -f --tail 100 ``` ### Vérifier les Health Checks ```bash # Backend curl https://api-preprod.xpeditis.com/health # Frontend curl https://app-preprod.xpeditis.com ``` --- ## Optimisations Possibles ### 1. Cache des Dépendances npm ✅ **Déjà implémenté** : Les dépendances npm sont cachées via `actions/setup-node@v4` ### 2. Cache des Layers Docker ✅ **Déjà implémenté** : Utilise `cache-from` et `cache-to` de Buildx ### 3. Parallélisation des Jobs ✅ **Déjà implémenté** : Backend et Frontend build/test en parallèle ### 4. Skip Tests pour Hotfix (Non recommandé) ```yaml # Ajouter dans le workflow if: "!contains(github.event.head_commit.message, '[skip tests]')" ``` Puis commit avec : ```bash git commit -m "hotfix: fix critical bug [skip tests]" ``` ⚠️ **Attention** : Utiliser uniquement en cas d'urgence absolue ! --- ## Troubleshooting ### Le pipeline échoue sur "Backend Build & Test" **Causes possibles** : - Tests unitaires échoués - Tests d'intégration échoués - Erreurs TypeScript **Solution** : ```bash # Lancer les tests localement cd apps/backend npm run test npm run test:integration # Vérifier la compilation npm run build ``` --- ### Le pipeline échoue sur "Docker Build & Push" **Causes possibles** : - Token Scaleway invalide - Dockerfile incorrect - Dépendances manquantes **Solution** : ```bash # Tester le build localement docker build -t test -f apps/backend/Dockerfile . # Vérifier les logs GitHub Actions pour plus de détails ``` --- ### Le déploiement échoue sur "Health Check" **Causes possibles** : - Service ne démarre pas correctement - Variables d'environnement incorrectes - Base de données non accessible **Solution** : 1. Vérifier les logs Portainer 2. Vérifier les variables d'environnement dans la stack 3. Vérifier que PostgreSQL, Redis, MinIO sont opérationnels --- ## Support Pour plus d'informations : - [Configuration des Secrets GitHub](GITHUB-SECRETS-SETUP.md) - [Guide de Déploiement Portainer](../docker/PORTAINER-DEPLOYMENT-GUIDE.md) - [Documentation GitHub Actions](https://docs.github.com/en/actions)