Aller au contenu
Culture DevOps high

CI/CD : automatiser le chemin du code à la production

27 min de lecture

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.

  • 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.

Vue d'ensemble d'un pipeline CI/CD avec les étapes de build, test, sécurité et déploiement

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.

Comparaison entre Continuous Integration, Continuous Delivery et Continuous Deployment

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 :

  1. Un développeur pousse son code sur Git
  2. Un serveur CI (Jenkins, GitLab CI, GitHub Actions...) détecte le changement
  3. Le code est compilé automatiquement
  4. Les tests unitaires et d'intégration s'exécutent
  5. Des analyses de qualité et de sécurité sont lancées
  6. Si tout passe : le code est validé
  7. Si quelque chose échoue : l'équipe est alertée immédiatement

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)

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

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.

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énementQuand l'utiliser
Push sur une brancheTests à chaque modification
Pull Request / Merge RequestValidation avant fusion
Tag / ReleaseDéploiement d'une version
Cron (planifié)Tests nocturnes, scans de sécurité
ManuelDéploiements contrôlés
# Exemple GitHub Actions
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 2 * * *' # Tous les jours à 2h

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/

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.

  1. Tests unitaires : vérifient les fonctions isolément (millisecondes).

  2. Tests d'intégration : vérifient les interactions entre composants (secondes).

  3. 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

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'analyseCe qu'il détecteOutils
LintingStyle, conventionsESLint, Ruff, Pylint
SASTVulnérabilités dans le codeSonarQube, Semgrep, CodeQL
SecretsCredentials exposésGitLeaks, TruffleHog
DépendancesCVE dans les packagesDependabot, Snyk, Trivy
SBOMInventaire des composantsSyft, 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

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 }}

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 }}

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.

Comparaison des stratégies de déploiement : Rolling Update, Blue/Green, Canary et Feature Flags

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 :

  1. Vous avez 4 serveurs avec la version 1.0
  2. Le déploiement arrête le serveur 1, le met à jour en 2.0, le redémarre
  3. Puis le serveur 2, puis 3, puis 4
  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 Update
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 1 pod en plus pendant la mise à jour
maxUnavailable: 0 # Aucun pod indisponible

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 :

  1. Blue = production actuelle (version 1.0)
  2. Green = nouvelle version (2.0) déployée en parallèle
  3. Tests sur Green sans impact utilisateur
  4. Changement DNS : le trafic bascule de Blue vers Green
  5. 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 green
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
version: green # Bascule ici

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 :

  1. 5 % du trafic vers la nouvelle version
  2. Monitoring des métriques (erreurs, latence, satisfaction)
  3. Si tout va bien : 25 % puis 50 % puis 100 %
  4. 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 VirtualService
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
spec:
http:
- route:
- destination:
host: myapp
subset: stable
weight: 95
- destination:
host: myapp
subset: canary
weight: 5

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 :

  1. Le code de la nouvelle fonctionnalité est déployé mais caché
  2. Un système de configuration (LaunchDarkly, Unleash, ou solution maison) contrôle son activation
  3. 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 flag
from 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 actuelle

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 Canary

L'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.

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.

Ces pratiques concernent la partie intégration continue du pipeline : elles visent un feedback le plus rapide et le plus fiable possible à chaque commit.

  1. Un commit = un build : chaque push déclenche le pipeline, sans exception.

  2. 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.

  3. Fail fast : les étapes les plus rapides en premier (lint avant tests, tests unitaires avant E2E).

  4. Cache agressif : dépendances, images Docker, résultats de build.

  5. Feedback visible : status checks sur les PR, notifications Slack ou Teams.

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.

  1. Infrastructure as Code : toute configuration d'environnement est versionnée, jamais modifiée à la main sur le serveur.

  2. Environnements identiques : le staging doit être le plus proche possible de la production, sinon les tests y perdent leur valeur prédictive.

  3. Rollback automatisable : pouvoir revenir en arrière en moins de 5 minutes.

  4. Feature flags : découpler déploiement et activation des fonctionnalités.

  5. Monitoring proactif : alertes sur les métriques clés (erreurs, latence, saturation).

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étriqueObjectifPourquoi
Temps de build< 10 minFeedback rapide
Fréquence de déploiementQuotidienne minimumPetits changements, moins de risque
Lead time< 1 jourDu commit à la production
Change Failure Rate< 15 %Qualité des déploiements
MTTR< 1 heureTemps de récupération après incident

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ômeCause probableSolution
Build aléatoirement casséTests flakyIdentifier et corriger les tests non déterministes
Pipeline lentPas de cacheConfigurer le cache pour dépendances et builds
Échec au déploiementSecrets manquantsVérifier les variables d'environnement
Tests passent localement, échouent en CIEnvironnement différentUtiliser des conteneurs pour reproduire l'environnement CI
Déploiement bloquéApprobation en attenteVérifier les reviewers et les environnements protégés
  • 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.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn