Environnements & CI/CD — DYNORS¶
Nomenclature (ADR-0016 / ADR-0019)
Cible : LOCAL → DEV → INT → RMOA → PROD. Les libellés RMOA DYNORS / RMOA CLIENT et les fichiers sirrat.config.yml dans le repo app sont legacy — voir SIRRAT — concept et Structure Git.
Guide pratique pour mettre en place une plateforme DevOps reproduisant la chaîne locale → dev → int → rmoa → prod.
Principe : environnements et pipeline (cible)¶
Local ──► DEV ──► INT ──► RMOA ──► PROD
(dev) (auto CI) (qualif) (métier) (CTO + PV)
En local : docker-compose.local.yml + .env.local uniquement. Hors local, URLs et secrets sont injectés par SIRRAT Forge — pas de .env.dev / .env.prod versionnés dans le repo app.
Stack CI/CD gratuite recommandée¶
DYNORS utilise déjà GitLab (gitlab.com). La solution la plus simple et gratuite est d'utiliser GitLab CI + runners auto-hébergés sur un petit VPS.
| Composant | Outil | Coût | Pourquoi |
|---|---|---|---|
| Code + pipeline | GitLab CI | Gratuit (gitlab.com) | Déjà utilisé |
| Runners CI | GitLab Runner self-hosted | Gratuit (VPS 10–15 €/mois) | Contrôle total |
| Registry Docker | GitLab Container Registry | Gratuit | Intégré à GitLab |
| Secrets / variables | GitLab CI/CD Variables | Gratuit | Protégées, masquées |
| Notifications | Slack (plan gratuit) | Gratuit | Webhooks CI |
| Monitoring | Grafana + Prometheus | Gratuit (self-hosted) | Stack standard |
| Logs | Loki + Grafana | Gratuit (self-hosted) | Intégré à Grafana |
Alternative si pas de GitLab : Woodpecker CI — open source, Docker-based, compatible GitHub/Gitea/Forgejo.
Installation d'un runner GitLab self-hosted¶
# Sur un VPS Ubuntu/Debian
# 1. Installer Docker
curl -fsSL https://get.docker.com | sh
# 2. Installer GitLab Runner
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt-get install gitlab-runner
# 3. Enregistrer le runner (token depuis GitLab → Settings → CI/CD → Runners)
sudo gitlab-runner register \
--url https://gitlab.com/ \
--registration-token YOUR_TOKEN \
--executor docker \
--docker-image "docker:latest" \
--description "dynors-runner-prod" \
--tag-list "dynors-runner" \
--docker-privileged
Un runner peut servir tous vos projets GitLab.
Structure des fichiers par projet¶
dynors-projects/clients/mon-projet/
├── .gitlab-ci.yml # Pipeline CI/CD
├── docker-compose.local.yml # Stack locale (dev machine) — seul compose app obligatoire
├── .env.example # Template (commité, sans secrets)
├── .env.local # LOCAL (gitignored, SIRRAT_ENABLED=false)
├── backend/
│ └── src/main/resources/
│ ├── application.yml # Config commune (placeholders)
│ └── application-local.yml # Profil local
Legacy — ne plus ajouter
sirrat.config.yml→ SIRRAT Forgedocker-compose.dev.yml+.env.dev→ déploiement injecté par SIRRATapplication-rmoa-*.yml→ profils gérés plateforme
Archive — arborescence historique multi-env (lecture seule)
└── scripts/
├── deploy-dev.sh
├── deploy-rmoa-dynors.sh
├── deploy-rmoa-client.sh
├── deploy-prod.sh
├── backup-prod.sh
└── rollback.sh
Template docker-compose.local.yml (seul compose app)¶
services:
backend:
build: ./backend
env_file: .env.local
ports:
- "8080:8080"
depends_on:
- postgres
- redis
postgres:
image: postgres:15
environment:
POSTGRES_DB: ${DB_NAME:-app_local}
POSTGRES_USER: ${DB_USER:-app}
POSTGRES_PASSWORD: ${DB_PASSWORD:-local}
volumes:
- postgres_local_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
volumes:
postgres_local_data:
Hors local, le déploiement (images, env, URLs couloir SLY) est piloté par SIRRAT — pas de docker-compose.dev.yml dans le repo app.
Archive — template `docker-compose.dev.yml` (legacy, ne plus ajouter)
version: "3.8"
services:
backend:
image: ${CI_REGISTRY_IMAGE}/backend:dev-${CI_COMMIT_SHORT_SHA}
env_file: .env.dev
ports:
- "8080:8080"
depends_on:
- postgres
- redis
# … frontend, postgres, redis — voir historique Git si besoin
Template .env.example (local uniquement)¶
# ─── Local dev uniquement ───────────────────────────────
# Hors local : secrets et URLs injectés par SIRRAT Forge + Vault (ESO)
SIRRAT_ENABLED=false
LOG_LEVEL=DEBUG
# SLY local (gateway)
SLY_BASE_URL=http://localhost:8090
SLY_FORWARD_SECRET=local-sly-secret
DB_HOST=localhost
DB_PORT=5432
DB_NAME=
DB_USER=
DB_PASSWORD=
# Mocks dev
PAYMENT_PROVIDER=mock
EMAIL_PROVIDER=mock
STORAGE_PROVIDER=filesystem
Interdit dans le repo app
Pas de .env.dev, .env.rmoa-*, .env.prod versionnés. Pas de SIRRAT_API_TOKEN côté app — injecté par la CI/plateforme au déploiement.
Archive — `.env.example` multi-env (legacy)
ENVIRONMENT= # local | dev | rmoa-dynors | rmoa-client | prod ← déprécié
SIRRAT_ENABLED=
SIRRAT_API_URL=
SIRRAT_PROJECT_ID=
SIRRAT_API_TOKEN= # jamais dans Git
# … voir historique
Pipeline GitLab CI — structure (cible)¶
Stages typiques alignés ADR-0016 :
stages:
- build
- test
- publish
- notify-sirrat
# deploy-* : déclenchés par SIRRAT / manuel selon env (DEV auto, INT/RMOA/PROD manuel)
Extrait minimal (Java 21, notify SIRRAT après publish) :
variables:
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
SIRRAT_API_URL: "https://sirrat.dynors.com/api"
build:backend:
stage: build
image: eclipse-temurin:21-jdk
script:
- cd backend && ./gradlew clean bootJar -x test
artifacts:
paths: [backend/build/libs/*.jar]
tags: [dynors-runner]
test:unit:
stage: test
image: eclipse-temurin:21-jdk
services: [postgres:15, redis:7]
script:
- cd backend && ./gradlew test jacocoTestReport
tags: [dynors-runner]
notify:sirrat:
stage: notify-sirrat
script:
- |
curl -sf -X POST "$SIRRAT_API_URL/projects/$SIRRAT_PROJECT_ID/artifact-ready" \
-H "Authorization: Bearer $SIRRAT_API_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"environment\":\"dev\",\"version\":\"$CI_COMMIT_SHORT_SHA\"}" \
|| echo "SIRRAT notify skipped"
allow_failure: true
only: [develop, main]
tags: [dynors-runner]
Voir GitLab — intégration CI / notify SIRRAT.
Archive — pipeline complet RMOA DYNORS/CLIENT (legacy)
Anciens stages `deploy-rmoa-dynors`, `deploy-rmoa-client`, SSH + `docker-compose.dev.yml`, URLs `dev-$CI_PROJECT_NAME.dynors.com`, image `gradle:8.5-jdk17` — **dépréciés** (ADR-0018 : hors-prod via SLY couloir `sly-{env}-{lane}.hp.intranet.dynors.com/{app}/…`).# Extrait historique — ne pas copier tel quel
stages: [build, test, deploy-dev, deploy-rmoa-dynors, deploy-rmoa-client, deploy-prod]
deploy:rmoa-dynors: { stage: deploy-rmoa-dynors, when: manual }
deploy:rmoa-client: { stage: deploy-rmoa-client, when: manual }
Variables CI/CD GitLab à configurer¶
Dans GitLab → Settings → CI/CD → Variables (protégées + masquées) :
# SIRRAT (notify CI — pas dans le repo app)
SIRRAT_API_TOKEN
SIRRAT_PROJECT_ID
# Registry / build
GITLAB_TOKEN # Package Registry com.dynors.*
CI_REGISTRY_USER
CI_REGISTRY_PASSWORD
# Runners uniquement si besoin de smoke tests inter-app
SLY_FORWARD_SECRET # injecté aussi par SIRRAT au déploiement — Vault en prod
# Notifications
SLACK_WEBHOOK
Secrets applicatifs (DB, JWT, PSP) : Vault → ESO → env au déploiement — pas de DB_RMOA_*_PASSWORD dupliqués dans GitLab « par confort ». Voir Vault — stratégie.
INT & RMOA — alignement pré-prod / prod¶
Objectif : INT (qualif technique) et RMOA (validation métier) aussi proches que possible de PROD :
| Aspect | INT / RMOA | PROD | Comment aligner |
|---|---|---|---|
| Base de données | PostgreSQL 15 | PostgreSQL 15 | ✅ même version |
| SSL | Requis | Requis | ✅ même config |
| Storage | MinIO (compatible S3) | S3 ou MinIO | ✅ même API |
| Paiements | Sandbox / mock | Production | ⚠ Tester les cas limites avant PROD |
| SLY (hors-prod) | sly-{env}-{lane}.hp.intranet.dynors.com/{app}/… |
Domaines marque propres | ADR-0018 |
| SLY (inter-app Bus) | actif | actif | même stack |
SLY_FORWARD_SECRET |
Vault cercle | Vault prod | ✅ policies moindre privilège |
| Redis | Oui | Oui | ✅ |
| Sentry | Activé (env int/rmoa) | Activé (prod) | projets séparés |
Branches Git (GitFlow adapté DYNORS)¶
main # 😇 PRODUCTION
develop # 🔥 DEV (CI + notify SIRRAT)
release/v1.3.0 # 🌫 INT puis RMOA (gates SIRRAT)
feature/nom-feature # 😈 En dev
hotfix/correctif-critique # 🚨 Urgence prod
Legacy
Branches release/v1.3.0-internal (RMOA DYNORS) et distinction RMOA CLIENT — remplacées par INT + RMOA avec attributs SIRRAT (acceptance, operated_by — ADR-0019).
Protections GitLab (Settings → Repository → Protected branches) :
main:
push: No one
merge: Maintainers
force_push: false
develop:
push: Developers + Maintainers
merge: Developers + Maintainers
release/*:
push: Maintainers only
merge: Maintainers only
Checklist nouveau projet¶
☐ 1. Créer le repo GitLab dans dynors-projects/
☐ 2. Copier template .gitlab-ci.yml + adapter les stages
☐ 3. Déclarer l'app dans **SIRRAT Forge** (pas de `sirrat.config.yml` dans le repo)
☐ 4. Créer **`docker-compose.local.yml`** + **`.env.local`** (SIRRAT_ENABLED=false)
☐ 5. Créer **`.env.example`** (template local, sans secrets)
☐ 6. Configurer les branches protégées GitLab
☐ 7. Ajouter les variables CI/CD GitLab (cf. liste § 4)
☐ 8. Déclarer le projet dans SIRRAT
☐ 9. Configurer les canaux Slack (#dev-X, #qa-X, #prod-alerts)
☐ 10. Premier push → vérifier pipeline **build + test + notify SIRRAT**