diff --git a/Jenkinsfile b/Jenkinsfile index 81e27f2..b40b40f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,7 +9,8 @@ * 1. Init - Détection de l'environnement (dev/preprod/prod) * 2. Checkout - Récupération du code source depuis Git * 3. Install - Installation des dépendances Node.js - * 4. Quality - Vérification qualité (ESLint + Jest + SonarQube) + * 4a. Lint & Tests - ESLint + Jest avec couverture de code + * 4b. SonarQube - Analyse statique (après tests pour avoir la couverture) * 5. Build - Construction de l'image Docker (avec variables env) * 6. Push - Envoi de l'image vers le registre Docker privé * 7. Deploy - Déploiement sur le serveur cible @@ -130,73 +131,67 @@ pipeline { } // ===================================================================== - // ÉTAPE 4 : CONTRÔLES QUALITÉ (Exécution parallèle) + // ÉTAPE 4a : LINT & TESTS // --------------------------------------------------------------------- - // Exécute en parallèle : - // - Lint & Tests : ESLint + Jest avec couverture de code - // - SonarQube : Analyse statique de la qualité du code + // ESLint : Vérifie le style et les erreurs de code + // Jest : Exécute les tests unitaires React/Next.js + // Couverture : Génère un rapport de couverture (lcov) // ===================================================================== - stage('🔍 Quality - Contrôles qualité') { - parallel { - // ------------------------------------------------------------- - // 4a. LINT & TESTS - // ------------------------------------------------------------- - // ESLint : Vérifie le style et les erreurs de code - // Jest : Exécute les tests unitaires React/Next.js - // Couverture : Génère un rapport de couverture (lcov) - // ------------------------------------------------------------- - stage('🧪 Lint & Tests') { - agent { - docker { - image 'node:20' - args "-u root -v ${NPM_CACHE}:/root/.npm" - } - } - steps { - unstash 'node_modules' - echo "🧪 Lancement ESLint et Jest..." - script { - def lintStatus = sh(script: 'npm run lint', returnStatus: true) - def testStatus = sh(script: 'npm test', returnStatus: true) - - if (lintStatus != 0) { - error "❌ ESLint a échoué - Corrigez les erreurs de style" - } - if (testStatus != 0) { - error "❌ Les tests ont échoué - Vérifiez les tests unitaires" - } - echo "✅ Lint et tests passés avec succès" - } - } + stage('🧪 Lint & Tests') { + agent { + docker { + image 'node:20' + args "-u root -v ${NPM_CACHE}:/root/.npm" } + } + steps { + unstash 'node_modules' + echo "🧪 Lancement ESLint et Jest..." + script { + def lintStatus = sh(script: 'npm run lint', returnStatus: true) + def testStatus = sh(script: 'npm test', returnStatus: true) - // ------------------------------------------------------------- - // 4b. SONARQUBE - // ------------------------------------------------------------- - // Analyse statique du code pour détecter : - // - Bugs potentiels - // - Vulnérabilités de sécurité - // - Code smells (mauvaises pratiques) - // - Couverture de code insuffisante - // - Duplications de code - // ------------------------------------------------------------- - stage('📊 SonarQube Analysis') { - agent { - docker { - image 'sonarsource/sonar-scanner-cli:latest' - args '-u root' - } + if (lintStatus != 0) { + error "❌ ESLint a échoué - Corrigez les erreurs de style" } - steps { - echo "📊 Analyse SonarQube en cours..." - withSonarQubeEnv('SonarQube') { - sh """ - sonar-scanner - """ - } - echo "✅ Analyse SonarQube terminée" + if (testStatus != 0) { + error "❌ Les tests ont échoué - Vérifiez les tests unitaires" } + echo "✅ Lint et tests passés avec succès" } + // Stash coverage report for SonarQube + stash includes: 'coverage/**', name: 'coverage' + } + } + + // ===================================================================== + // ÉTAPE 4b : SONARQUBE + // --------------------------------------------------------------------- + // Analyse statique du code pour détecter : + // - Bugs potentiels + // - Vulnérabilités de sécurité + // - Code smells (mauvaises pratiques) + // - Couverture de code insuffisante + // - Duplications de code + // NOTE: Exécuté APRÈS les tests pour avoir accès au rapport de couverture + // ===================================================================== + stage('📊 SonarQube Analysis') { + agent { + docker { + image 'sonarsource/sonar-scanner-cli:latest' + args '-u root' + } + } + steps { + // Unstash coverage report from tests + unstash 'coverage' + echo "📊 Analyse SonarQube en cours..." + withSonarQubeEnv('SonarQube') { + sh """ + sonar-scanner + """ + } + echo "✅ Analyse SonarQube terminée" } }