pipeline { agent any options { disableConcurrentBuilds() timestamps() skipDefaultCheckout(true) } environment { CI_NETWORK = "tiptop-ci-${BUILD_NUMBER}" CI_DATABASE = "tiptop-ci-db-${BUILD_NUMBER}" DATABASE_URL = "postgresql://tiptop_ci:tiptop_ci_password@${CI_DATABASE}:5432/the_tip_top_ci" REGISTRY = "localhost:5000" IMAGE_TAG = "${BUILD_NUMBER}" BACKEND_IMAGE = "${REGISTRY}/the-tip-top/backend" FRONTEND_IMAGE = "${REGISTRY}/the-tip-top/frontend" } stages { stage('Checkout') { steps { checkout scm } } stage('Vérification du workspace') { steps { sh ''' test -f backend/package.json test -f backend/package-lock.json test -f frontend/package.json test -f frontend/package-lock.json test -f deploy/dev/docker-compose.yml echo "Commit : ${GIT_COMMIT}" echo "Tag Docker : ${IMAGE_TAG}" ''' } } stage('Backend - Tests') { steps { sh ''' docker network create "${CI_NETWORK}" docker run -d \ --name "${CI_DATABASE}" \ --network "${CI_NETWORK}" \ -e POSTGRES_USER=tiptop_ci \ -e POSTGRES_PASSWORD=tiptop_ci_password \ -e POSTGRES_DB=the_tip_top_ci \ postgres:16-alpine echo "Attente de PostgreSQL..." for i in $(seq 1 30); do if docker exec "${CI_DATABASE}" \ pg_isready -U tiptop_ci -d the_tip_top_ci; then echo "PostgreSQL est prêt." break fi if [ "$i" -eq 30 ]; then docker logs "${CI_DATABASE}" exit 1 fi sleep 2 done docker run --rm \ --network "${CI_NETWORK}" \ --volumes-from furious-jenkins \ --user "$(id -u):$(id -g)" \ -e HOME=/tmp \ -e NPM_CONFIG_CACHE=/tmp/.npm \ -e DATABASE_URL="${DATABASE_URL}" \ -e JWT_SECRET=jenkins_ci_secret \ -e NODE_ENV=test \ -w "${WORKSPACE}/backend" \ node:22-alpine \ sh -c " npm ci && npx prisma generate && npx prisma migrate deploy && npm test " ''' } } stage('Frontend - Lint et Build') { steps { sh ''' docker run --rm \ --volumes-from furious-jenkins \ --user "$(id -u):$(id -g)" \ -e HOME=/tmp \ -e NPM_CONFIG_CACHE=/tmp/.npm \ -w "${WORKSPACE}/frontend" \ node:22-alpine \ sh -c " npm ci && npm run lint && npm run build " ''' } } stage('Construction des images Docker') { steps { sh ''' docker build \ -t "${BACKEND_IMAGE}:${IMAGE_TAG}" \ -t "${BACKEND_IMAGE}:latest" \ backend docker build \ --build-arg VITE_API_URL=http://192.168.1.23:5001 \ -t "${FRONTEND_IMAGE}:${IMAGE_TAG}" \ -t "${FRONTEND_IMAGE}:latest" \ frontend ''' } } stage('Publication dans le Registry') { steps { sh ''' docker push "${BACKEND_IMAGE}:${IMAGE_TAG}" docker push "${BACKEND_IMAGE}:latest" docker push "${FRONTEND_IMAGE}:${IMAGE_TAG}" docker push "${FRONTEND_IMAGE}:latest" ''' } } stage('Déploiement DEV') { steps { sh ''' REGISTRY="${REGISTRY}" \ IMAGE_TAG="${IMAGE_TAG}" \ docker compose \ -p tiptop-dev \ -f deploy/dev/docker-compose.yml \ up -d \ --pull always \ --remove-orphans echo "Attente du backend DEV..." for i in $(seq 1 30); do if curl -fsS http://localhost:5001/ >/dev/null; then echo "Backend DEV opérationnel." break fi if [ "$i" -eq 30 ]; then docker compose \ -p tiptop-dev \ -f deploy/dev/docker-compose.yml \ logs --tail=100 exit 1 fi sleep 5 done curl -fsS http://localhost:5173/ >/dev/null echo "Frontend DEV opérationnel." ''' } } } post { always { sh ''' docker rm -f "${CI_DATABASE}" 2>/dev/null || true docker network rm "${CI_NETWORK}" 2>/dev/null || true ''' } success { echo "Pipeline CI/CD réussi. Version DEV déployée : ${IMAGE_TAG}" } failure { echo "Pipeline CI/CD en échec. Consulte la Console Output." } } }