Netflix orchestre plusieurs milliers de déploiements par jour grâce à son outil interne Spinnaker. En 2011 déjà, Amazon annonçait un déploiement en production toutes les 11,6 secondes en moyenne. Pendant ce temps, certaines équipes attendent encore des semaines pour livrer une simple correction. La différence tient à un seul mot : l'automatisation CI/CD.
Ce guide explique, pour un lecteur qui n'a jamais configuré de pipeline, ce que sont réellement l'intégration continue et le déploiement continu, comment un pipeline est construit étape par étape, quelles stratégies de déploiement choisir (Rolling Update, Blue/Green, Canary, Feature Flags) et comment mesurer vos progrès avec les métriques DORA. L'objectif : livrer plus vite, avec moins de bugs et moins de stress, quelle que soit la taille de votre équipe.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Distinguer clairement Continuous Integration, Continuous Delivery et Continuous Deployment
- Décomposer les étapes d'un pipeline CI/CD : déclenchement, build, tests, sécurité, publication, déploiement
- Choisir une stratégie de déploiement adaptée à votre contexte (Rolling Update, Blue/Green, Canary, Feature Flags)
- Appliquer les bonnes pratiques qui évitent les pipelines lents ou fragiles
- Suivre les métriques DORA pour objectiver la performance de vos livraisons
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 est assemblée à la main, du début à la fin, par des artisans. Le processus prend des semaines et chaque véhicule est légèrement différent du précédent.
Puis arrive la chaîne de montage : chaque étape est standardisée, automatisée, et vérifiée avant de passer à la suivante. Résultat, davantage 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, celui-ci 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 source de confusion permanente car il désigne deux pratiques différentes derrière le même sigle. Clarifions une bonne fois pour toutes ce que chacune implique concrètement, avant de détailler leur fonctionnement.
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 à chaque ajout.
Analogie : imaginez une équipe qui écrit un livre ensemble. Au lieu que chacun rédige 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 de sécurité sont lancées
- Si tout passe : le code est validé
- Si quelque chose échoue : l'équipe est alertée immédiatement
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 fortement 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 une excellente couverture de tests
- Équipes matures avec une forte culture qualité
- Systèmes avec rollback automatique
- Microservices indépendants les uns des autres
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. Chaque étape ne démarre que si la précédente a réussi : c'est ce qui garantit qu'un code défaillant ne progresse jamais jusqu'à la production. 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 sur le dépôt Git. Choisir le bon déclencheur évite deux écueils opposés : lancer le pipeline trop souvent (gaspillage de ressources) ou pas assez (feedback trop tardif).
| É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 build transforme le code source en un artefact exécutable, c'est-à-dire le livrable final que l'on va tester puis déployer : une image Docker, un binaire compilé ou un paquet de dépendances. Cette étape doit être reproductible : deux builds du même commit doivent produire un résultat strictement identique.
- 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 »Un pipeline exécute plusieurs niveaux de tests, du plus rapide au plus lent, pour donner un feedback progressif. L'idée : détecter les régressions évidentes en quelques secondes, avant de lancer les vérifications les plus coûteuses.
-
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).
Pour approfondir la construction d'une pyramide de tests équilibrée, consultez le guide sur les stratégies de tests.
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é »Avant de publier un artefact, le pipeline le scanne pour détecter les vulnérabilités et les erreurs de configuration. Cette étape incarne le principe du shift-left : détecter les problèmes de sécurité le plus tôt possible, quand ils coûtent le moins cher à corriger. Le guide dédié au shift-left détaille cette approche.
| 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@57a97c7 # v0.35.0, pinné par SHA 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 »Une fois validé, l'artefact est publié dans un registre, un serveur qui stocke et distribue les versions numérotées de vos livrables. C'est ce registre que l'étape de déploiement viendra interroger pour récupérer la bonne version à installer.
- 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 »Le déploiement installe l'artefact publié sur l'environnement cible, typiquement d'abord un environnement de staging (réplique de la production pour valider sans risque), puis la production. Beaucoup d'équipes matures remplacent les commandes kubectl impératives ci-dessous par une approche déclarative : le guide GitOps explique pourquoi et comment.
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 de déploiement existent, chacune avec ses avantages et son niveau de complexité opérationnelle.
Rolling Update (mise à jour progressive)
Section intitulée « Rolling Update (mise à jour progressive) »Principe : remplacer les instances une par une, ce qui permet de mettre à jour l'application sans jamais tout arrêter d'un coup. C'est la stratégie par défaut de la plupart des orchestrateurs de conteneurs.
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 de l'un vers l'autre en une seule opération, ce qui rend le rollback instantané puisque l'ancien environnement reste disponible.
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 secours
Avantages :
- Rollback instantané (rebascule vers Blue)
- Test en conditions réelles avant mise en production
- Pas de versions mixtes
Inconvénients :
- Coût infrastructure doublé
- 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 si aucun signal négatif n'apparaît. 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 groupe pilote rencontre des problèmes, on stoppe le déploiement.
Comment ça marche :
- 5 % du trafic vers la nouvelle version
- Monitoring des métriques (erreurs, latence, satisfaction)
- Si tout va bien : 25 % puis 50 % puis 100 %
- Si problème : rollback immédiat (seuls 5 % impactés)
Avantages :
- Risque limité (un petit pourcentage 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. Cette approche découple deux décisions habituellement liées : quand le code arrive en production, et quand la fonctionnalité devient visible.
Comment ça marche :
- Le code de la nouvelle fonctionnalité est déployé mais caché
- Un système de configuration (LaunchDarkly, Unleash, ou solution 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 qui enchaîne les bonnes pratiques vues plus haut : les jobs de la partie CI (lint, test, security) s'exécutent en parallèle, puis build ne démarre que si les trois réussissent grâce à la clé needs. La partie CD suit le même principe de chaînage jusqu'à la production, avec une porte d'approbation sur l'environnement production.
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@57a97c7 # v0.35.0, pinné par SHA 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 CanaryL'environnement production avec sa clé environment: déclenche, côté GitHub, une règle de protection configurable : approbation manuelle, restriction de branche, ou délai d'attente. C'est ce mécanisme qui transforme un Continuous Deployment en Continuous Delivery pour la dernière étape, sans dupliquer le pipeline.
Bonnes pratiques CI/CD
Section intitulée « Bonnes pratiques CI/CD »Un pipeline mal réglé décourage vite l'équipe : trop lent, il devient un frein plutôt qu'une aide ; trop permissif, il laisse passer des régressions. Les pratiques suivantes, séparées entre CI et CD, évitent les pièges les plus courants.
Pour la CI
Section intitulée « Pour la CI »Ces pratiques concernent la partie intégration continue du pipeline : elles visent un feedback le plus rapide et le plus fiable possible à chaque commit.
-
Un commit = un build : chaque push déclenche le pipeline, sans exception.
-
Build rapide : visez moins de 10 minutes. Au-delà, les développeurs n'attendent plus le feedback et enchaînent d'autres tâches, ce qui retarde la correction des erreurs.
-
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 ou Teams.
Pour le CD
Section intitulée « Pour le CD »Ces pratiques concernent la partie livraison et déploiement du pipeline : elles limitent le risque au moment où le code atteint réellement les utilisateurs.
-
Infrastructure as Code : toute configuration d'environnement est versionnée, jamais modifiée à la main sur le serveur.
-
Environnements identiques : le staging doit être le plus proche possible de la production, sinon les tests y perdent leur valeur prédictive.
-
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 »Mesurer objectivement la performance d'un pipeline évite de se fier à des impressions. Les métriques ci-dessous sont des repères pratiques à surveiller au quotidien, avant de passer à un cadre plus complet comme DORA.
| 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 production |
| 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 »Certains symptômes reviennent fréquemment dans les équipes qui démarrent avec un pipeline CI/CD. Les reconnaître rapidement évite de perdre des heures à chercher une cause déjà bien documentée.
| 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 % automatique).
- Le pipeline est votre gardien : s'il passe, le code est déployable ; s'il échoue, on corrige avant tout le reste.
- Épinglez vos actions par SHA de commit, pas par tag ni par branche : l'incident trivy-action de mars 2026 a montré qu'un tag reste modifiable.
- Commencez simple : Rolling Update d'abord, puis évoluez vers Blue/Green ou Canary selon vos besoins.
- Mesurez pour améliorer : les métriques DORA, désormais organisées en percentiles et archétypes, guident vos efforts d'optimisation.
- L'automatisation libère : moins de tâches manuelles signifie moins d'erreurs humaines et plus de temps pour créer de la valeur.