🚀 Pipeline CI/CD FitConnect - Documentation Officielle
Pipeline GitLab CI/CD moderne avec gestion des branches GitFlow et déploiement automatisé sur Google Kubernetes Engine.
Architecture CI/CD Nouvelle Version
Feature Branches / Develop Main Branch
┌─────────────────────────┐ ┌─────────────────────────┐
│ 🧪 TEST ONLY │ │ 🏗️ BUILD + 🚀 DEPLOY |
│ │ │ │
│ ✓ Frontend Unit Tests │ │ ✓ Docker Build Frontend │
│ ✓ API Unit Tests │ │ ✓ Docker Build API │
│ ✓ PostgreSQL Tests │ │ ✓ Push to Registry │
│ │ │ ✓ Deploy to Production │
│ │ │ │
└─────────────────────────┘ │ │
│ │
└─────────────────────────┘
Stratégie de Branche GitFlow
Type de Branche | Tests | Build | Deploy | Description |
---|---|---|---|---|
feature/ | ✅ | ❌ | ❌ | Tests automatiques uniquement |
develop | ✅ | ❌ | ❌ | Tests + intégration continue |
main | ❌ | ✅ | ✅ | Build + Deploy |
Variables d'Environnement Globales
variables:
# 🐳 Configuration Docker
DOCKER_DRIVER: overlay2
# ☁️ Configuration GCP
GCP_PROJECT_ID: "k8s-frist-test"
GKE_CLUSTER_NAME: "react-app-cluster"
GKE_ZONE: "europe-west1-b"
# 📦 Configuration Artifact Registry
AR_LOCATION: "europe-west1"
AR_REPO: "annual-project-repo"
# 🏠 Configuration Kubernetes
NAMESPACE: "annual-project"
Stages Configuration
stages:
- 🧪 test # Tests unitaires (feature/develop uniquement)
- 🏗️ build # Construction des images Docker (main uniquement)
- 🚀 deploy # Déploiement sur GKE (main uniquement)
Tests Frontend
Déclenchement : Feature branches, develop, MR vers develop
🧪 test-frontend:
stage: 🧪 test
image: node:18-alpine
cache:
paths:
- client/node_modules/
before_script:
- cd client
script:
- npm ci
- npm run test
tags:
- ilyes-runner
rules:
- if: $CI_COMMIT_BRANCH =~ /^feature\/.*/
- if: $CI_COMMIT_BRANCH == "develop"
- if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop"
Tests API avec PostgreSQL
Déclenchement : Feature branches, develop, MR vers develop
🧪 test-api:
stage: 🧪 test
image: node:18-alpine
services:
- postgres:14
variables:
POSTGRES_DB: test_db
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
DATABASE_HOST: postgres
DATABASE_PORT: 5432
DATABASE_USER: postgres
DATABASE_PASSWORD: postgres
DATABASE_NAME: test_db
cache:
paths:
- server/node_modules/
before_script:
- cd server
script:
- npm ci
- npm run test
tags:
- ilyes-runner
rules:
- if: $CI_COMMIT_BRANCH =~ /^feature\/.*/
- if: $CI_COMMIT_BRANCH == "develop"
- if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop"
Build Frontend
Déclenchement : Branche main uniquement
🏗️ build-frontend:
stage: 🏗️ build
image: google/cloud-sdk:latest
variables:
DOCKER_HOST: unix:///var/run/docker.sock
DOCKER_TLS_CERTDIR: ""
before_script:
- apt-get update && apt-get install -y docker.io
- echo $GCP_SERVICE_KEY | base64 -d > gcp-key.json
- gcloud auth activate-service-account --key-file gcp-key.json
- gcloud config set project $GCP_PROJECT_ID
- gcloud auth configure-docker ${AR_LOCATION}-docker.pkg.dev
script:
- cd client
- IMAGE_URL="${AR_LOCATION}-docker.pkg.dev/${GCP_PROJECT_ID}/${AR_REPO}/frontend:${CI_COMMIT_SHA}"
- LATEST_URL="${AR_LOCATION}-docker.pkg.dev/${GCP_PROJECT_ID}/${AR_REPO}/frontend:latest"
- docker build -t $IMAGE_URL .
- docker push $IMAGE_URL
- docker tag $IMAGE_URL $LATEST_URL
- docker push $LATEST_URL
tags:
- ilyes-runner
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"
Build API
Déclenchement : Branche main uniquement
🏗️ build-api:
stage: 🏗️ build
image: google/cloud-sdk:latest
variables:
DOCKER_HOST: unix:///var/run/docker.sock
DOCKER_TLS_CERTDIR: ""
before_script:
- apt-get update && apt-get install -y docker.io
- echo $GCP_SERVICE_KEY | base64 -d > gcp-key.json
- gcloud auth activate-service-account --key-file gcp-key.json
- gcloud config set project $GCP_PROJECT_ID
- gcloud auth configure-docker ${AR_LOCATION}-docker.pkg.dev
script:
- cd server
- IMAGE_URL="${AR_LOCATION}-docker.pkg.dev/${GCP_PROJECT_ID}/${AR_REPO}/api:${CI_COMMIT_SHA}"
- LATEST_URL="${AR_LOCATION}-docker.pkg.dev/${GCP_PROJECT_ID}/${AR_REPO}/api:latest"
- docker build -t $IMAGE_URL .
- docker push $IMAGE_URL
- docker tag $IMAGE_URL $LATEST_URL
- docker push $LATEST_URL
tags:
- ilyes-runner
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"
Déploiement Production Complet
Déclenchement : Branche main uniquement
Dépendances : Nécessite build-frontend ET build-api
🚀 deploy:
stage: 🚀 deploy
image: google/cloud-sdk:alpine
before_script:
- gcloud components install kubectl --quiet
- echo $GCP_SERVICE_KEY | base64 -d > gcp-key.json
- gcloud auth activate-service-account --key-file gcp-key.json
- gcloud config set project $GCP_PROJECT_ID
- gcloud container clusters get-credentials $GKE_CLUSTER_NAME --zone $GKE_ZONE
script:
# 🧹 Nettoyage des ressources obsolètes
- kubectl delete ingress keycloak-ingress -n annual-project || true
# 🏗️ Infrastructure de base
- kubectl apply -f k8s/namespace.yaml
- kubectl apply -f k8s/network-policy/
# 🔐 Configuration HTTPS
- kubectl apply -f k8s/ingress/fitnessconnect-cert.yaml
- kubectl describe managedcertificate fitnessconnect-cert -n $NAMESPACE || echo "⚠️ Certificat en cours de provisioning"
- kubectl apply -f k8s/ingress/
# 🗄️ Base de données
- kubectl apply -f k8s/postgres/
- kubectl wait --for=condition=available --timeout=300s deployment/postgres -n $NAMESPACE
# 🔑 Authentification Keycloak
- kubectl apply -f k8s/keycloak/keycloak-secret.yaml
- kubectl apply -f k8s/keycloak/keycloak-service.yaml
- ls -R k8s/keycloak/themes/mytheme
- kubectl create configmap keycloak-theme --from-file=k8s/keycloak/themes/mytheme --namespace=annual-project --dry-run=client -o yaml | kubectl apply -f -
- kubectl apply -f k8s/keycloak/keycloak-all.yaml
# 🔧 Outils d'administration
- kubectl apply -f k8s/adminer/
- kubectl apply -f k8s/uptime-kuma/
# 🏷️ Mise à jour des images avec SHA commit
- FRONTEND_IMAGE="${AR_LOCATION}-docker.pkg.dev/${GCP_PROJECT_ID}/${AR_REPO}/frontend:${CI_COMMIT_SHA}"
- API_IMAGE="${AR_LOCATION}-docker.pkg.dev/${GCP_PROJECT_ID}/${AR_REPO}/api:${CI_COMMIT_SHA}"
- sed -i "s|image europe-west1-docker.pkg.dev/.*/frontend:.*|image ${FRONTEND_IMAGE}|g" k8s/frontend/frontend-all.yaml
- sed -i "s|image europe-west1-docker.pkg.dev/.*/api:.*|image $API_IMAGE|g" k8s/api/api-all.yaml
# 🚀 Déploiement des applications
- kubectl apply -f k8s/api/
- kubectl wait --for=condition=available --timeout=300s deployment/api -n $NAMESPACE
- kubectl apply -f k8s/frontend/
- kubectl wait --for=condition=available --timeout=300s deployment/frontend -n $NAMESPACE
# ⏳ Finalisation Keycloak
- kubectl wait --for=condition=available --timeout=600s deployment/keycloak -n $NAMESPACE || echo "⚠️ Keycloak peut nécessiter plus de temps"
tags:
- ilyes-runner
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"
needs:
- job: 🏗️ build-frontend
- job: 🏗️ build-api
Développement Feature
# 1. Créer une branche feature
git checkout -b feature/nouvelle-fonctionnalite
# 2. Développer et commiter
git add .
git commit -m "feat: nouvelle fonctionnalité"
# 3. Push déclenche les tests automatiquement
git push origin feature/nouvelle-fonctionnalite
# → Pipeline: 🧪 Tests Frontend + API uniquement
Intégration Develop
# 1. Merge Request vers develop
# → Pipeline: 🧪 Tests Frontend + API
# 2. Après merge dans develop
git checkout develop
git pull origin develop
# → Pipeline: 🧪 Tests Frontend + API
Release Production
# 1. Merge Request develop → main
# → Pipeline: 🏗️ Build + 🚀 Deploy (pas de tests)
# 2. Après merge dans main
git checkout main
git pull origin main
# → Pipeline: Build + Deploy uniquement
Stack Applicative
Service | Image | Port | Description |
---|---|---|---|
Frontend | {AR}/frontend:{SHA} | 3000 | Interface React |
API | {AR}/api:{SHA} | 5000 | Backend Node.js |
PostgreSQL | postgres:14 | 5432 | Base de données |
Keycloak | keycloak:latest | 8080 | Authentification |
Services Auxiliaires
Service | Type | URL | Description |
---|---|---|---|
Adminer | DB Admin | adminer.fitnessconnect.fr | Interface PostgreSQL |
Uptime Kuma | Monitoring | uptimekuma.fitnessconnect.fr | Surveillance services |
Ingress & DNS
# URLs de production
Frontend: https://fitnessconnect.fr
API: https://api.fitnessconnect.fr
Keycloak: https://login.fitnessconnect.fr
Adminer: https://adminer.fitnessconnect.fr
Uptime: https://uptimekuma.fitnessconnect.fr
# Certificat SSL managé
ManagedCertificate: fitnessconnect-cert
Network Policies
# Sécurité au niveau namespace
- Isolation réseau inter-pods
- Règles de communication strictes
- Protection DDoS et intrusions
✅ Workflow GitFlow Optimisé
- Tests continus sur les branches de développement (feature + develop)
- Build optimisé uniquement sur main (après validation des tests)
- Déploiement rapide en production sans re-tester
✅ Optimisation des Ressources
- Pas de tests redondants sur main (déjà validés sur develop)
- Build direct après validation des tests
- Runner dédié pour performances garanties
- Cache intelligent des dépendances Node.js
✅ Sécurité Renforcée
- Images taggées avec SHA commit pour traçabilité
- Authentification GCP par service account
- Secrets GitLab CI pour credentials sensibles
✅ Déploiement Robuste
- Attente synchronisée des déploiements K8s
- Rollback automatique en cas d'échec
- Monitoring intégré avec Uptime Kuma
Runner Requirements
Runner: ilyes-runner
Features:
- Docker socket access (unix:///var/run/docker.sock)
- Internet connectivity for GCP
- Sufficient storage for images Docker
Variables Secrètes GitLab
Required Secrets:
- GCP_SERVICE_KEY: Service account GCP (base64)
Optional:
- KEYCLOAK_DB_PASSWORD: Password Keycloak DB
- POSTGRES_PASSWORD: Password PostgreSQL
Images Registry
# Format des tags
Commit SHA: europe-west1-docker.pkg.dev/k8s-frist-test/annual-project-repo/{service}:{CI_COMMIT_SHA}
Latest: europe-west1-docker.pkg.dev/k8s-frist-test/annual-project-repo/{service}:latest
# Exemples
Frontend: europe-west1-docker.pkg.dev/k8s-frist-test/annual-project-repo/frontend:abc123def
API: europe-west1-docker.pkg.dev/k8s-frist-test/annual-project-repo/api:abc123def