From 92dfcbe61e8ed3a55e3a01baedd1dd4eb173f311 Mon Sep 17 00:00:00 2001 From: Andil Date: Tue, 4 Aug 2026 16:01:02 +0000 Subject: [PATCH 1/4] feat: add preproduction environment --- deploy/preprod/docker-compose.yml | 79 +++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 deploy/preprod/docker-compose.yml diff --git a/deploy/preprod/docker-compose.yml b/deploy/preprod/docker-compose.yml new file mode 100644 index 0000000..b61eef5 --- /dev/null +++ b/deploy/preprod/docker-compose.yml @@ -0,0 +1,79 @@ +services: + postgres: + image: postgres:16-alpine + restart: unless-stopped + + environment: + POSTGRES_USER: tiptop_preprod + POSTGRES_PASSWORD: tiptop_preprod_password + POSTGRES_DB: the_tip_top_preprod + + volumes: + - tiptop_preprod_postgres_data:/var/lib/postgresql/data + + healthcheck: + test: + [ + "CMD-SHELL", + "pg_isready -U tiptop_preprod -d the_tip_top_preprod" + ] + interval: 10s + timeout: 5s + retries: 10 + + networks: + - tiptop-preprod + + backend: + image: ${REGISTRY}/the-tip-top/backend:${IMAGE_TAG} + restart: unless-stopped + + depends_on: + postgres: + condition: service_healthy + + environment: + PORT: 5000 + NODE_ENV: preproduction + DATABASE_URL: postgresql://tiptop_preprod:tiptop_preprod_password@postgres:5432/the_tip_top_preprod + JWT_SECRET: preprod_secret_change_me + APP_URL: http://192.168.1.23:5002 + MAIL_HOST: smtp.gmail.com + MAIL_PORT: 587 + MAIL_USER: "" + MAIL_PASS: "" + MAIL_FROM: "The Tip Top Preprod " + + command: > + sh -c " + npx prisma migrate deploy && + npm run init:db && + npm start + " + + ports: + - "5002:5000" + + networks: + - tiptop-preprod + + frontend: + image: ${REGISTRY}/the-tip-top/frontend:${IMAGE_TAG} + restart: unless-stopped + + depends_on: + - backend + + ports: + - "5174:80" + + networks: + - tiptop-preprod + +volumes: + tiptop_preprod_postgres_data: + name: tiptop_preprod_postgres_data + +networks: + tiptop-preprod: + name: tiptop-preprod -- 2.49.1 From ac702c8835e69429031751e0a2313e654ef85224 Mon Sep 17 00:00:00 2001 From: Andil Date: Tue, 4 Aug 2026 16:13:53 +0000 Subject: [PATCH 2/4] feat: route branches to dev and preproduction --- Jenkinsfile | 117 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 84 insertions(+), 33 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index ecd3c7b..1434d2b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -8,16 +8,15 @@ pipeline { } 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" + + CI_NETWORK = "tiptop-ci-${JOB_BASE_NAME}-${BUILD_NUMBER}" + CI_DATABASE = "tiptop-ci-db-${JOB_BASE_NAME}-${BUILD_NUMBER}" + + DATABASE_URL = "postgresql://tiptop_ci:tiptop_ci_password@${CI_DATABASE}:5432/the_tip_top_ci" } stages { @@ -27,6 +26,42 @@ pipeline { } } + stage('Préparer environnement') { + steps { + script { + env.IMAGE_TAG = "${env.BRANCH_NAME}-${env.BUILD_NUMBER}" + + if (env.BRANCH_NAME == 'main') { + env.DEPLOY_ENABLED = 'true' + env.DEPLOY_ENV = 'DEV' + env.COMPOSE_FILE = 'deploy/dev/docker-compose.yml' + env.COMPOSE_PROJECT = 'tiptop-dev' + env.DEPLOY_NETWORK = 'tiptop-dev' + env.FRONTEND_API_URL = 'http://192.168.1.23:5001' + } else if (env.BRANCH_NAME == 'develop') { + env.DEPLOY_ENABLED = 'true' + env.DEPLOY_ENV = 'PREPROD' + env.COMPOSE_FILE = 'deploy/preprod/docker-compose.yml' + env.COMPOSE_PROJECT = 'tiptop-preprod' + env.DEPLOY_NETWORK = 'tiptop-preprod' + env.FRONTEND_API_URL = 'http://192.168.1.23:5002' + } else { + env.DEPLOY_ENABLED = 'false' + env.DEPLOY_ENV = 'CI uniquement' + env.COMPOSE_FILE = '' + env.COMPOSE_PROJECT = '' + env.DEPLOY_NETWORK = '' + env.FRONTEND_API_URL = '' + } + + echo "Branche : ${env.BRANCH_NAME}" + echo "Tag Docker : ${env.IMAGE_TAG}" + echo "Environnement : ${env.DEPLOY_ENV}" + echo "Déploiement activé : ${env.DEPLOY_ENABLED}" + } + } + } + stage('Vérification du workspace') { steps { sh ''' @@ -34,9 +69,10 @@ pipeline { 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 "Tag Docker : ${IMAGE_TAG}" + if [ "${DEPLOY_ENABLED}" = "true" ]; then + test -f "${COMPOSE_FILE}" + fi ''' } } @@ -54,12 +90,12 @@ pipeline { -e POSTGRES_DB=the_tip_top_ci \ postgres:16-alpine - echo "Attente de PostgreSQL..." + echo "Attente de PostgreSQL CI..." 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." + echo "PostgreSQL CI est prêt." break fi @@ -124,70 +160,85 @@ pipeline { } stage('Construction des images Docker') { + when { + expression { + env.DEPLOY_ENABLED == 'true' + } + } + 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 \ + --build-arg VITE_API_URL="${FRONTEND_API_URL}" \ -t "${FRONTEND_IMAGE}:${IMAGE_TAG}" \ - -t "${FRONTEND_IMAGE}:latest" \ frontend ''' } } stage('Publication dans le Registry') { + when { + expression { + env.DEPLOY_ENABLED == 'true' + } + } + 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') { + stage('Déploiement') { + when { + expression { + env.DEPLOY_ENABLED == 'true' + } + } + steps { sh ''' + echo "Déploiement de ${BRANCH_NAME} vers ${DEPLOY_ENV}" + REGISTRY="${REGISTRY}" \ IMAGE_TAG="${IMAGE_TAG}" \ docker compose \ - -p tiptop-dev \ - -f deploy/dev/docker-compose.yml \ + -p "${COMPOSE_PROJECT}" \ + -f "${COMPOSE_FILE}" \ up -d \ --pull always \ --remove-orphans - echo "Attente du backend DEV..." + echo "Attente du backend ${DEPLOY_ENV}..." for i in $(seq 1 30); do if docker run --rm \ - --network tiptop-dev \ + --network "${DEPLOY_NETWORK}" \ curlimages/curl:8.12.1 \ -fsS http://backend:5000/ >/dev/null; then - echo "Backend DEV opérationnel." + echo "Backend ${DEPLOY_ENV} opérationnel." break fi if [ "$i" -eq 30 ]; then - echo "Le backend DEV ne répond pas." + echo "Le backend ${DEPLOY_ENV} ne répond pas." docker compose \ - -p tiptop-dev \ - -f deploy/dev/docker-compose.yml \ + -p "${COMPOSE_PROJECT}" \ + -f "${COMPOSE_FILE}" \ ps docker compose \ - -p tiptop-dev \ - -f deploy/dev/docker-compose.yml \ - logs --tail=100 + -p "${COMPOSE_PROJECT}" \ + -f "${COMPOSE_FILE}" \ + logs --tail=150 exit 1 fi @@ -195,14 +246,14 @@ pipeline { sleep 5 done - echo "Vérification du frontend DEV..." + echo "Vérification du frontend ${DEPLOY_ENV}..." docker run --rm \ - --network tiptop-dev \ + --network "${DEPLOY_NETWORK}" \ curlimages/curl:8.12.1 \ -fsS http://frontend/ >/dev/null - echo "Frontend DEV opérationnel." + echo "Frontend ${DEPLOY_ENV} opérationnel." ''' } } @@ -217,11 +268,11 @@ pipeline { } success { - echo "Pipeline CI/CD réussi. Version DEV déployée : ${IMAGE_TAG}" + echo "Pipeline réussi pour ${BRANCH_NAME}. Environnement : ${DEPLOY_ENV}. Version : ${IMAGE_TAG}" } failure { - echo "Pipeline CI/CD en échec. Consulte la Console Output." + echo "Pipeline en échec pour ${BRANCH_NAME}. Consulte la Console Output." } } } -- 2.49.1 From 466655f52d4ae3341aee1597114c3e8f139c56fb Mon Sep 17 00:00:00 2001 From: Andil Date: Tue, 4 Aug 2026 17:54:09 +0000 Subject: [PATCH 3/4] feat: add production deployment flow --- Jenkinsfile | 31 +++++++++---- deploy/prod/docker-compose.yml | 80 ++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 9 deletions(-) create mode 100644 deploy/prod/docker-compose.yml diff --git a/Jenkinsfile b/Jenkinsfile index 1434d2b..5063b6b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -45,6 +45,13 @@ pipeline { env.COMPOSE_PROJECT = 'tiptop-preprod' env.DEPLOY_NETWORK = 'tiptop-preprod' env.FRONTEND_API_URL = 'http://192.168.1.23:5002' + } else if (env.BRANCH_NAME.startsWith('release-')) { + env.DEPLOY_ENABLED = 'true' + env.DEPLOY_ENV = 'PROD' + env.COMPOSE_FILE = 'deploy/prod/docker-compose.yml' + env.COMPOSE_PROJECT = 'tiptop-prod' + env.DEPLOY_NETWORK = 'tiptop-prod' + env.FRONTEND_API_URL = 'http://192.168.1.23:5003' } else { env.DEPLOY_ENABLED = 'false' env.DEPLOY_ENV = 'CI uniquement' @@ -195,6 +202,21 @@ pipeline { } } + stage('Validation production') { + when { + expression { + env.DEPLOY_ENV == 'PROD' + } + } + + steps { + timeout(time: 15, unit: 'MINUTES') { + input message: "Déployer ${IMAGE_TAG} en production ?", + ok: "Déployer" + } + } + } + stage('Déploiement') { when { expression { @@ -228,13 +250,6 @@ pipeline { fi if [ "$i" -eq 30 ]; then - echo "Le backend ${DEPLOY_ENV} ne répond pas." - - docker compose \ - -p "${COMPOSE_PROJECT}" \ - -f "${COMPOSE_FILE}" \ - ps - docker compose \ -p "${COMPOSE_PROJECT}" \ -f "${COMPOSE_FILE}" \ @@ -246,8 +261,6 @@ pipeline { sleep 5 done - echo "Vérification du frontend ${DEPLOY_ENV}..." - docker run --rm \ --network "${DEPLOY_NETWORK}" \ curlimages/curl:8.12.1 \ diff --git a/deploy/prod/docker-compose.yml b/deploy/prod/docker-compose.yml new file mode 100644 index 0000000..beeda63 --- /dev/null +++ b/deploy/prod/docker-compose.yml @@ -0,0 +1,80 @@ +services: + postgres: + image: postgres:16-alpine + restart: unless-stopped + + environment: + POSTGRES_USER: tiptop_prod + POSTGRES_PASSWORD: tiptop_prod_password + POSTGRES_DB: the_tip_top_prod + + volumes: + - tiptop_prod_postgres_data:/var/lib/postgresql/data + + healthcheck: + test: + [ + "CMD-SHELL", + "pg_isready -U tiptop_prod -d the_tip_top_prod" + ] + interval: 10s + timeout: 5s + retries: 10 + + networks: + - tiptop-prod + + backend: + image: ${REGISTRY}/the-tip-top/backend:${IMAGE_TAG} + restart: unless-stopped + + depends_on: + postgres: + condition: service_healthy + + environment: + PORT: 5000 + NODE_ENV: production + DATABASE_URL: postgresql://tiptop_prod:tiptop_prod_password@postgres:5432/the_tip_top_prod + JWT_SECRET: prod_secret_change_me + APP_URL: http://192.168.1.23:5003 + + MAIL_HOST: smtp.gmail.com + MAIL_PORT: 587 + MAIL_USER: "" + MAIL_PASS: "" + MAIL_FROM: "The Tip Top " + + command: > + sh -c " + npx prisma migrate deploy && + npm run init:db && + npm start + " + + ports: + - "5003:5000" + + networks: + - tiptop-prod + + frontend: + image: ${REGISTRY}/the-tip-top/frontend:${IMAGE_TAG} + restart: unless-stopped + + depends_on: + - backend + + ports: + - "5175:80" + + networks: + - tiptop-prod + +volumes: + tiptop_prod_postgres_data: + name: tiptop_prod_postgres_data + +networks: + tiptop-prod: + name: tiptop-prod -- 2.49.1 From 803a78cd7118607c202f2a84394223c4c7d885c7 Mon Sep 17 00:00:00 2001 From: Andil Date: Tue, 4 Aug 2026 20:43:14 +0000 Subject: [PATCH 4/4] refactor: align branches with dev preprod and production --- Jenkinsfile | 75 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 11 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 5063b6b..e413def 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -31,30 +31,49 @@ pipeline { script { env.IMAGE_TAG = "${env.BRANCH_NAME}-${env.BUILD_NUMBER}" - if (env.BRANCH_NAME == 'main') { + /* + * Stratégie de branches : + * + * feature/* -> CI uniquement + * develop -> DEV automatique + * release-* -> PREPROD automatique + * main -> PROD avec validation manuelle + */ + + if (env.BRANCH_NAME == 'develop') { env.DEPLOY_ENABLED = 'true' env.DEPLOY_ENV = 'DEV' + env.COMPOSE_FILE = 'deploy/dev/docker-compose.yml' env.COMPOSE_PROJECT = 'tiptop-dev' env.DEPLOY_NETWORK = 'tiptop-dev' + env.FRONTEND_API_URL = 'http://192.168.1.23:5001' - } else if (env.BRANCH_NAME == 'develop') { + + } else if (env.BRANCH_NAME.startsWith('release-')) { env.DEPLOY_ENABLED = 'true' env.DEPLOY_ENV = 'PREPROD' + env.COMPOSE_FILE = 'deploy/preprod/docker-compose.yml' env.COMPOSE_PROJECT = 'tiptop-preprod' env.DEPLOY_NETWORK = 'tiptop-preprod' + env.FRONTEND_API_URL = 'http://192.168.1.23:5002' - } else if (env.BRANCH_NAME.startsWith('release-')) { + + } else if (env.BRANCH_NAME == 'main') { env.DEPLOY_ENABLED = 'true' env.DEPLOY_ENV = 'PROD' + env.COMPOSE_FILE = 'deploy/prod/docker-compose.yml' env.COMPOSE_PROJECT = 'tiptop-prod' env.DEPLOY_NETWORK = 'tiptop-prod' + env.FRONTEND_API_URL = 'http://192.168.1.23:5003' + } else { env.DEPLOY_ENABLED = 'false' env.DEPLOY_ENV = 'CI uniquement' + env.COMPOSE_FILE = '' env.COMPOSE_PROJECT = '' env.DEPLOY_NETWORK = '' @@ -101,12 +120,16 @@ pipeline { for i in $(seq 1 30); do if docker exec "${CI_DATABASE}" \ - pg_isready -U tiptop_ci -d the_tip_top_ci; then + pg_isready \ + -U tiptop_ci \ + -d the_tip_top_ci; then + echo "PostgreSQL CI est prêt." break fi if [ "$i" -eq 30 ]; then + echo "PostgreSQL CI ne répond pas." docker logs "${CI_DATABASE}" exit 1 fi @@ -211,8 +234,10 @@ pipeline { steps { timeout(time: 15, unit: 'MINUTES') { - input message: "Déployer ${IMAGE_TAG} en production ?", - ok: "Déployer" + input( + message: "Déployer ${IMAGE_TAG} en production ?", + ok: "Déployer" + ) } } } @@ -227,6 +252,9 @@ pipeline { steps { sh ''' echo "Déploiement de ${BRANCH_NAME} vers ${DEPLOY_ENV}" + echo "Image backend : ${BACKEND_IMAGE}:${IMAGE_TAG}" + echo "Image frontend : ${FRONTEND_IMAGE}:${IMAGE_TAG}" + echo "Compose : ${COMPOSE_FILE}" REGISTRY="${REGISTRY}" \ IMAGE_TAG="${IMAGE_TAG}" \ @@ -243,17 +271,27 @@ pipeline { if docker run --rm \ --network "${DEPLOY_NETWORK}" \ curlimages/curl:8.12.1 \ - -fsS http://backend:5000/ >/dev/null; then + -fsS \ + http://backend:5000/ \ + >/dev/null; then echo "Backend ${DEPLOY_ENV} opérationnel." break fi if [ "$i" -eq 30 ]; then + echo "Le backend ${DEPLOY_ENV} ne répond pas." + docker compose \ -p "${COMPOSE_PROJECT}" \ -f "${COMPOSE_FILE}" \ - logs --tail=150 + ps + + docker compose \ + -p "${COMPOSE_PROJECT}" \ + -f "${COMPOSE_FILE}" \ + logs \ + --tail=150 exit 1 fi @@ -261,10 +299,14 @@ pipeline { sleep 5 done + echo "Vérification du frontend ${DEPLOY_ENV}..." + docker run --rm \ --network "${DEPLOY_NETWORK}" \ curlimages/curl:8.12.1 \ - -fsS http://frontend/ >/dev/null + -fsS \ + http://frontend/ \ + >/dev/null echo "Frontend ${DEPLOY_ENV} opérationnel." ''' @@ -281,11 +323,22 @@ pipeline { } success { - echo "Pipeline réussi pour ${BRANCH_NAME}. Environnement : ${DEPLOY_ENV}. Version : ${IMAGE_TAG}" + echo """ + Pipeline réussi. + + Branche : ${BRANCH_NAME} + Environnement : ${DEPLOY_ENV} + Version : ${IMAGE_TAG} + """ } failure { - echo "Pipeline en échec pour ${BRANCH_NAME}. Consulte la Console Output." + echo """ + Pipeline en échec. + + Branche : ${BRANCH_NAME} + Environnement : ${DEPLOY_ENV} + """ } } } -- 2.49.1