pipeline { agent any // πŸ” VΓ©rifie le code toutes les minutes (ou via Webhook Gitea) triggers { pollSCM('* * * * *') } // βš™οΈ ParamΓ¨tre pour choisir l’environnement parameters { choice(name: 'ENV', choices: ['dev', 'preprod', 'prod'], description: 'Choisir l’environnement de dΓ©ploiement') } // 🌍 Variables globales environment { REGISTRY_URL = "registry.wk-archi-o24a-15m-g3.fr" IMAGE_NAME = "the-tip-top-backend" TAG = "${params.ENV}-latest" DEPLOY_PATH = "/srv/devops/the-tip-top/${params.ENV}" } stages { /* ─────────────────────────────── * 1️⃣ Checkout du code source * ─────────────────────────────── */ stage('Checkout') { steps { echo "πŸ“¦ RΓ©cupΓ©ration du code source depuis Gitea..." checkout scm } } /* ─────────────────────────────── * 2️⃣ Tests qualitΓ© et unitaires * ─────────────────────────────── */ stage('Tests & QualitΓ©') { steps { echo "πŸ§ͺ Lancement des tests et analyse de code..." sh ''' npm ci npm run lint || echo "⚠️ Erreurs de lint dΓ©tectΓ©es" npm test || echo "⚠️ Tests Γ©chouΓ©s β€” vΓ©rifier les logs" ''' } } /* ─────────────────────────────── * 3️⃣ Build de l’image Docker * ─────────────────────────────── */ stage('Build Docker image') { steps { echo "🐳 Construction de l’image Docker backend..." sh ''' docker build -t ${REGISTRY_URL}/${IMAGE_NAME}:${TAG} . docker tag ${REGISTRY_URL}/${IMAGE_NAME}:${TAG} ${REGISTRY_URL}/${IMAGE_NAME}:latest ''' } } /* ─────────────────────────────── * 4️⃣ Push vers le registre privΓ© * ─────────────────────────────── */ stage('Push to Registry') { steps { echo "πŸ“€ Envoi de l’image vers le registre Docker privΓ©..." withCredentials([usernamePassword(credentialsId: 'registry-credentials', usernameVariable: 'REG_USER', passwordVariable: 'REG_PASS')]) { sh ''' echo "$REG_PASS" | docker login ${REGISTRY_URL} -u "$REG_USER" --password-stdin docker push ${REGISTRY_URL}/${IMAGE_NAME}:${TAG} docker push ${REGISTRY_URL}/${IMAGE_NAME}:latest ''' } } } /* ─────────────────────────────── * 5️⃣ Sauvegarde avant dΓ©ploiement * ─────────────────────────────── */ stage('Backup Before Deploy') { steps { echo "πŸ’Ύ ExΓ©cution du script de sauvegarde avant dΓ©ploiement..." sh ''' if [ -f /srv/devops/the-tip-top/backup.sh ]; then bash /srv/devops/the-tip-top/backup.sh else echo "⚠️ Aucun script backup.sh trouvΓ©, dΓ©ploiement sans sauvegarde." fi ''' } } /* ─────────────────────────────── * 6️⃣ DΓ©ploiement du backend * ─────────────────────────────── */ stage('Deploy') { steps { echo "πŸš€ DΓ©ploiement du backend sur ${params.ENV}..." sh ''' if [ ! -f ${DEPLOY_PATH}/docker-compose.yml ]; then echo "❌ Fichier docker-compose.yml introuvable dans ${DEPLOY_PATH}" exit 1 fi cd ${DEPLOY_PATH} docker compose pull backend docker compose up -d --force-recreate backend ''' } } /* ─────────────────────────────── * 7️⃣ VΓ©rification du dΓ©ploiement * ─────────────────────────────── */ stage('Health Check') { steps { echo "🩺 VΓ©rification du backend aprΓ¨s dΓ©ploiement..." script { def domain = (params.ENV == 'dev') ? "api.dev.dsp5-archi-o24a-15m-g3.fr" : (params.ENV == 'preprod') ? "api.preprod.dsp5-archi-o24a-15m-g3.fr" : "api.dsp5-archi-o24a-15m-g3.fr" def maxRetries = 10 def statusCode = "000" for (int i = 1; i <= maxRetries; i++) { statusCode = sh( script: "curl -k -s -o /dev/null -w '%{http_code}' https://${domain}/health || echo 000", returnStdout: true ).trim() if (statusCode == '200') { echo "βœ… Backend ${params.ENV} opΓ©rationnel (HTTP ${statusCode}) aprΓ¨s ${i} essai(s)" break } else { echo "⏳ Tentative ${i}/${maxRetries} β†’ HTTP ${statusCode}" sleep 5 } } if (statusCode != '200') { error("❌ Health check Γ©chouΓ© sur ${params.ENV} - code HTTP ${statusCode}") } } } } } post { success { echo "βœ… Pipeline backend ${params.ENV} terminΓ© avec succΓ¨s !" } failure { echo "❌ Γ‰chec du pipeline backend pour ${params.ENV}." } } }