🏗️ Architecture

🔄 CI/CD & Déploiement

🚀 Pipeline CI/CD FitConnect - Documentation Officielle

Pipeline GitLab CI/CD moderne avec gestion des branches GitFlow et déploiement automatisé sur Google Kubernetes Engine.

🎯 Vue d'Ensemble du Pipeline

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 BrancheTestsBuildDeployDescription
feature/Tests automatiques uniquement
developTests + intégration continue
mainBuild + Deploy

📋 Configuration GitLab CI

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)

Stage: Tests

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"

Stage: Build

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"

🚀 Stage: Deploy

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

🔄 Workflow GitFlow

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

📦 Services Déployés

Stack Applicative

ServiceImagePortDescription
Frontend{AR}/frontend:{SHA}3000Interface React
API{AR}/api:{SHA}5000Backend Node.js
PostgreSQLpostgres:145432Base de données
Keycloakkeycloak:latest8080Authentification

Services Auxiliaires

ServiceTypeURLDescription
AdminerDB Adminadminer.fitnessconnect.frInterface PostgreSQL
Uptime KumaMonitoringuptimekuma.fitnessconnect.frSurveillance services

🌐 Configuration Réseau & Sécurité

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

🎯 Avantages de la Nouvelle Pipeline

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

🔧 Configuration Technique

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

📊 Monitoring & Observabilité

Outils Intégrés

  • Uptime Kuma : Surveillance temps réel des services
  • Adminer : Interface d'administration PostgreSQL
  • GitLab CI : Logs et métriques des pipelines
  • Google Cloud : Monitoring infrastructure K8s

Métriques Clés

  • Temps de build : ~5-10 minutes par composant
  • Temps de déploiement : ~15-20 minutes complet
  • Disponibilité : Monitoring 24/7 via Uptime Kuma
  • Performances : Métriques GKE et Load Balancer