Netflix déploie des milliers de fois par jour. Amazon pousse du code en production toutes les 11,7 secondes. Pendant ce temps, certaines entreprises attendent des semaines, voire des mois, pour mettre à jour leurs applications. La différence ? L’automatisation CI/CD.
L’intégration continue et le déploiement continu ne sont pas des gadgets pour les géants de la tech — ce sont des pratiques fondamentales qui permettent à n’importe quelle équipe de livrer plus vite, avec moins de bugs et moins de stress.
Ce guide vous explique ces concepts de A à Z, même si vous n’avez jamais configuré de pipeline.
Qu’est-ce que CI/CD ? L’analogie de la chaîne de montage
Section intitulée « Qu’est-ce que CI/CD ? L’analogie de la chaîne de montage »Imaginez une usine automobile. Avant l’industrialisation, chaque voiture était assemblée à la main, du début à la fin, par des artisans. Le processus prenait des semaines et chaque véhicule était différent.
Puis est arrivée la chaîne de montage : chaque étape est standardisée, automatisée, et vérifie la qualité avant de passer à la suivante. Résultat : plus de voitures, de meilleure qualité, en moins de temps.
CI/CD, c’est la chaîne de montage du logiciel.
-
CI (Continuous Integration) : Chaque fois qu’un développeur pousse du code, il est automatiquement compilé, testé et vérifié. Comme un contrôle qualité après chaque étape de la chaîne.
-
CD (Continuous Delivery/Deployment) : Le code validé est automatiquement préparé (ou déployé) pour la production. Comme une voiture qui sort de la chaîne prête à être livrée.
CI vs CD vs CD : ne confondez plus
Section intitulée « CI vs CD vs CD : ne confondez plus »Le terme “CD” est souvent source de confusion car il désigne deux choses différentes. Clarifions une fois pour toutes.
Continuous Integration (CI) — Intégration Continue
Section intitulée « Continuous Integration (CI) — Intégration Continue »Ce que c’est : La pratique de fusionner fréquemment le code de tous les développeurs dans une branche principale, avec vérification automatique.
Analogie : Imaginez une équipe qui écrit un livre ensemble. Au lieu que chacun écrive son chapitre dans son coin pendant des mois (et découvre ensuite que les chapitres ne s’accordent pas), tout le monde ajoute régulièrement ses paragraphes au manuscrit commun. Un correcteur automatique vérifie à chaque ajout que le texte reste cohérent.
Ce qui se passe concrètement :
- Un développeur pousse son code sur Git
- Un serveur CI (Jenkins, GitLab CI, GitHub Actions…) détecte le changement
- Le code est compilé automatiquement
- Les tests unitaires et d’intégration s’exécutent
- Des analyses de qualité et sécurité sont lancées
- Si tout passe : le code est validé ✅
- Si quelque chose échoue : l’équipe est alertée ❌
Continuous Delivery — Livraison Continue
Section intitulée « Continuous Delivery — Livraison Continue »Ce que c’est : L’extension de la CI où le code est automatiquement préparé pour être déployé en production, mais un humain appuie sur le bouton pour le déploiement final.
Analogie : La voiture sort de la chaîne de montage, passe tous les contrôles qualité, et attend dans le parking. Le concessionnaire décide quand la livrer au client.
Quand l’utiliser :
- Applications critiques nécessitant une validation métier
- Secteurs réglementés (finance, santé)
- Équipes en transition vers le DevOps
- Changements impactant les utilisateurs (UI, fonctionnalités majeures)
Continuous Deployment — Déploiement Continu
Section intitulée « Continuous Deployment — Déploiement Continu »Ce que c’est : La version ultime où tout est automatique : dès que le code passe les tests, il est déployé en production sans intervention humaine.
Analogie : La voiture sort de la chaîne de montage et est immédiatement livrée au client, sans passer par le parking.
Quand l’utiliser :
- Applications avec excellente couverture de tests
- Équipes matures avec forte culture qualité
- Systèmes avec rollback automatique
- Microservices indépendants
Anatomie d’un pipeline CI/CD
Section intitulée « Anatomie d’un pipeline CI/CD »Un pipeline est une séquence d’étapes automatisées qui transforme le code source en application déployée. Voyons chaque étape en détail.
Étape 1 : Déclenchement (Trigger)
Section intitulée « Étape 1 : Déclenchement (Trigger) »Le pipeline démarre quand un événement se produit :
| Événement | Quand l’utiliser |
|---|---|
| Push sur une branche | Tests à chaque modification |
| Pull Request / Merge Request | Validation avant fusion |
| Tag / Release | Déploiement d’une version |
| Cron (planifié) | Tests nocturnes, scans de sécurité |
| Manuel | Déploiements contrôlés |
# Exemple GitHub Actionson: push: branches: [main, develop] pull_request: branches: [main] schedule: - cron: '0 2 * * *' # Tous les jours à 2hÉtape 2 : Build (Compilation)
Section intitulée « Étape 2 : Build (Compilation) »Le code source est transformé en artefact exécutable :
- Application compilée (Java, Go, Rust…)
- Image Docker (conteneurs)
- Bundle optimisé (JavaScript, TypeScript)
- Package (pip, npm, nuget…)
build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm'
- name: Install dependencies run: npm ci
- name: Build application run: npm run build
- name: Upload artifact uses: actions/upload-artifact@v4 with: name: build-output path: dist/Étape 3 : Tests
Section intitulée « Étape 3 : Tests »Trois niveaux de tests, du plus rapide au plus lent :
-
Tests unitaires : Vérifient les fonctions isolément (millisecondes)
-
Tests d’intégration : Vérifient les interactions entre composants (secondes)
-
Tests End-to-End : Vérifient les parcours utilisateurs complets (minutes)
test: needs: build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Run unit tests run: npm run test:unit -- --coverage
- name: Run integration tests run: npm run test:integration
- name: Upload coverage uses: codecov/codecov-action@v4Étape 4 : Analyse de qualité et sécurité
Section intitulée « Étape 4 : Analyse de qualité et sécurité »Le code est scanné pour détecter :
| Type d’analyse | Ce qu’il détecte | Outils |
|---|---|---|
| Linting | Style, conventions | ESLint, Ruff, Pylint |
| SAST | Vulnérabilités dans le code | SonarQube, Semgrep, CodeQL |
| Secrets | Credentials exposés | GitLeaks, TruffleHog |
| Dépendances | CVE dans les packages | Dependabot, Snyk, Trivy |
| SBOM | Inventaire des composants | Syft, CycloneDX |
security: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: scan-type: 'fs' severity: 'CRITICAL,HIGH' exit-code: '1'
- name: Check for secrets uses: gitleaks/gitleaks-action@v2Étape 5 : Publication de l’artefact
Section intitulée « Étape 5 : Publication de l’artefact »L’artefact validé est publié dans un registre :
- Docker Registry (Docker Hub, GitHub Container Registry, Harbor)
- Package Registry (npm, PyPI, Maven Central)
- Artifact Storage (S3, GCS, Artifactory)
publish: needs: [test, security] runs-on: ubuntu-latest steps: - name: Login to Container Registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image uses: docker/build-push-action@v5 with: push: true tags: ghcr.io/${{ github.repository }}:${{ github.sha }}Étape 6 : Déploiement
Section intitulée « Étape 6 : Déploiement »L’artefact est déployé sur l’environnement cible :
Déploiement automatique après chaque merge sur main :
deploy-staging: needs: publish runs-on: ubuntu-latest environment: staging steps: - name: Deploy to staging run: | kubectl set image deployment/myapp \ myapp=ghcr.io/${{ github.repository }}:${{ github.sha }}Déploiement manuel avec approbation :
deploy-production: needs: deploy-staging runs-on: ubuntu-latest environment: name: production url: https://myapp.example.com steps: - name: Deploy to production run: | kubectl set image deployment/myapp \ myapp=ghcr.io/${{ github.repository }}:${{ github.sha }}Stratégies de déploiement
Section intitulée « Stratégies de déploiement »Comment mettre à jour une application en production sans interrompre le service ? Plusieurs stratégies existent, chacune avec ses avantages.
Rolling Update (mise à jour progressive)
Section intitulée « Rolling Update (mise à jour progressive) »Principe : Remplacer les instances une par une.
Comment ça marche :
- Vous avez 4 serveurs avec la version 1.0
- Le déploiement arrête le serveur 1, le met à jour en 2.0, le redémarre
- Puis le serveur 2, puis 3, puis 4
- À chaque instant, au moins 3 serveurs sont disponibles
Avantages :
- Zero downtime
- Utilise l’infrastructure existante
- Rollback possible (mais lent)
Inconvénients :
- Période avec versions mixtes (1.0 et 2.0 en parallèle)
- Problème si l’ancienne et la nouvelle version sont incompatibles (API, base de données)
# Kubernetes Rolling Updatespec: strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 # 1 pod en plus pendant la mise à jour maxUnavailable: 0 # Aucun pod indisponibleBlue/Green (environnements jumeaux)
Section intitulée « Blue/Green (environnements jumeaux) »Principe : Maintenir deux environnements identiques et basculer le trafic.
Comment ça marche :
- Blue = production actuelle (version 1.0)
- Green = nouvelle version (2.0) déployée en parallèle
- Tests sur Green sans impact utilisateur
- Changement DNS : le trafic bascule de Blue vers Green
- Blue devient l’environnement de backup
Avantages :
- Rollback instantané (rebascule vers Blue)
- Test en conditions réelles avant mise en prod
- Pas de versions mixtes
Inconvénients :
- Coût infrastructure x2
- Complexité pour les migrations de base de données
# Exemple avec labels Kubernetes# 1. Déployer la nouvelle version avec label version: green# 2. Mettre à jour le Service pour pointer vers greenapiVersion: v1kind: Servicemetadata: name: myappspec: selector: app: myapp version: green # Bascule iciCanary (déploiement progressif)
Section intitulée « Canary (déploiement progressif) »Principe : Déployer la nouvelle version pour un petit pourcentage d’utilisateurs, puis augmenter progressivement.
Pourquoi “Canary” ? Le nom vient des canaris utilisés dans les mines de charbon. Si le canari mourait, les mineurs savaient que l’air était toxique. Ici, si le “canary” (petit groupe d’utilisateurs) rencontre des problèmes, on stoppe le déploiement.
Comment ça marche :
- 5% du trafic → nouvelle version
- Monitoring des métriques (erreurs, latence, satisfaction)
- Si tout va bien : 25% → 50% → 100%
- Si problème : rollback immédiat (seuls 5% impactés)
Avantages :
- Risque limité (seul un petit % d’utilisateurs impacté)
- Feedback réel en production
- Détection précoce des problèmes
Inconvénients :
- Nécessite un monitoring sophistiqué
- Plus complexe à configurer
# Istio Canary avec VirtualServiceapiVersion: networking.istio.io/v1alpha3kind: VirtualServicespec: http: - route: - destination: host: myapp subset: stable weight: 95 - destination: host: myapp subset: canary weight: 5Feature Flags (drapeaux de fonctionnalités)
Section intitulée « Feature Flags (drapeaux de fonctionnalités) »Principe : Déployer le code en production mais garder les fonctionnalités désactivées, puis les activer progressivement.
Comment ça marche :
- Le code de la nouvelle fonctionnalité est déployé mais “caché”
- Un système de configuration (LaunchDarkly, Unleash, maison) contrôle son activation
- Activation progressive : d’abord les employés, puis 10% des utilisateurs, puis tous
Avantages :
- Découplage déploiement / activation
- A/B testing facile
- Rollback instantané (désactiver le flag)
- Pas besoin de re-déployer
Inconvénients :
- Code plus complexe (conditions if/else)
- Risque de dette technique (flags oubliés)
- Nécessite une gestion rigoureuse
# Exemple avec feature flagfrom feature_flags import is_enabled
def get_recommendations(user): if is_enabled("new_recommendation_algorithm", user): return new_algorithm(user) # Nouvelle version else: return legacy_algorithm(user) # Version actuelleExemple complet de pipeline
Section intitulée « Exemple complet de pipeline »Voici un pipeline GitHub Actions complet intégrant toutes les bonnes pratiques :
name: CI/CD Pipeline
on: push: branches: [main] pull_request: branches: [main]
env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }}
jobs: # ===== CONTINUOUS INTEGRATION =====
lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - run: npm ci - run: npm run lint
test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - run: npm ci - run: npm run test -- --coverage - uses: codecov/codecov-action@v4
security: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Run Trivy uses: aquasecurity/trivy-action@master with: scan-type: 'fs' severity: 'CRITICAL,HIGH' - name: Check secrets uses: gitleaks/gitleaks-action@v2
build: needs: [lint, test, security] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 - uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: docker/build-push-action@v5 with: push: ${{ github.event_name != 'pull_request' }} tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max
# ===== CONTINUOUS DELIVERY =====
deploy-staging: if: github.ref == 'refs/heads/main' needs: build runs-on: ubuntu-latest environment: staging steps: - name: Deploy to staging run: | echo "Déploiement sur staging..." # kubectl, ArgoCD, ou autre outil de déploiement
integration-tests: needs: deploy-staging runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Run E2E tests on staging run: npm run test:e2e env: BASE_URL: https://staging.example.com
deploy-production: needs: integration-tests runs-on: ubuntu-latest environment: name: production url: https://example.com steps: - name: Deploy to production run: | echo "Déploiement en production..." # Déploiement avec stratégie Blue/Green ou CanaryBonnes pratiques CI/CD
Section intitulée « Bonnes pratiques CI/CD »Pour la CI
Section intitulée « Pour la CI »-
Un commit = un build : Chaque push déclenche le pipeline. Pas d’exceptions.
-
Build rapide : Visez moins de 10 minutes. Au-delà, les développeurs n’attendent pas le feedback.
-
Fail fast : Les étapes les plus rapides en premier (lint avant tests, tests unitaires avant E2E).
-
Cache agressif : Dépendances, images Docker, résultats de build.
-
Feedback visible : Status checks sur les PR, notifications Slack/Teams.
Pour le CD
Section intitulée « Pour le CD »-
Infrastructure as Code : Toute configuration d’environnement est versionnée.
-
Environnements identiques : Staging doit être le plus proche possible de la production.
-
Rollback automatisable : Pouvoir revenir en arrière en moins de 5 minutes.
-
Feature flags : Découpler déploiement et activation des fonctionnalités.
-
Monitoring proactif : Alertes sur les métriques clés (erreurs, latence, saturation).
Métriques à suivre
Section intitulée « Métriques à suivre »| Métrique | Objectif | Pourquoi |
|---|---|---|
| Temps de build | < 10 min | Feedback rapide |
| Fréquence de déploiement | Quotidienne minimum | Petits changements = moins de risque |
| Lead time | < 1 jour | Du commit à la prod |
| Change Failure Rate | < 15% | Qualité des déploiements |
| MTTR | < 1 heure | Temps de récupération après incident |
Dépannage des pipelines
Section intitulée « Dépannage des pipelines »| Symptôme | Cause probable | Solution |
|---|---|---|
| Build aléatoirement cassé | Tests flaky | Identifier et corriger les tests non déterministes |
| Pipeline lent | Pas de cache | Configurer le cache pour dépendances et builds |
| Échec au déploiement | Secrets manquants | Vérifier les variables d’environnement |
| Tests passent localement, échouent en CI | Environnement différent | Utiliser des conteneurs pour reproduire l’environnement CI |
| Déploiement bloqué | Approbation en attente | Vérifier les reviewers et les environnements protégés |
À retenir
Section intitulée « À retenir »-
CI = intégrer fréquemment : Chaque commit est automatiquement buildé, testé et validé.
-
CD = déployer continuellement : Delivery (bouton manuel) ou Deployment (100% auto).
-
Le pipeline est votre gardien : S’il passe, le code est déployable. S’il échoue, on corrige avant tout.
-
Commencez simple : Rolling Update d’abord, puis évoluez vers Blue/Green ou Canary selon vos besoins.
-
Mesurez pour améliorer : Les métriques DORA guident vos efforts d’optimisation.
-
L’automatisation libère : Moins de tâches manuelles = moins d’erreurs humaines = plus de temps pour créer de la valeur.