Objectifs pédagogiques
- Expliquer l'utilité d'une pipeline et distinguer CI, Continuous Delivery et Continuous Deployment.
- Décrire le cycle de vie d'une release, du développement au déploiement, en passant par les niveaux de recette.
- Comparer les stratégies de déploiement modernes (rolling, blue/green, canary, feature flags).
- Comprendre les architectures actif/passif et actif/actif et leur lien avec la livraison.
- Situer les méthodes de développement actuelles et mesurer la performance via les métriques DORA.
1.1 Le problème que la CI/CD résout
Imaginez une équipe de développement il y a une vingtaine d'années. Dix développeurs travaillent chacun de leur côté pendant trois mois sur leur propre copie du code. Arrive le jour fatidique de l'intégration : on rassemble tout le travail de tout le monde. C'est ce qu'on appelait, sans rire, l'integration hell, l'enfer de l'intégration. Des milliers de lignes en conflit, des comportements incompatibles, des fonctionnalités qui marchaient isolément et qui s'effondrent une fois réunies. La mise en production se faisait un vendredi soir, à plusieurs, en croisant les doigts.
Ce modèle a un coût énorme :
- Le coût du délai : entre le moment où une fonctionnalité est codée et celui où elle apporte de la valeur à l'utilisateur, il peut s'écouler des mois.
- Le coût du risque : plus on accumule de changements avant de livrer, plus la livraison est grosse, plus elle est risquée. Un gros déploiement qui échoue est très difficile à diagnostiquer, quelle modification, parmi les centaines embarquées, a causé la panne ?
- Le coût humain : la peur de déployer. Quand déployer fait peur, on déploie moins souvent, donc les lots grossissent, donc le risque augmente, donc la peur augmente. Un cercle vicieux.
La CI/CD est la réponse d'ingénierie à ce cercle vicieux. L'idée fondatrice tient en une phrase : si quelque chose fait mal, faites-le plus souvent. L'intégration fait mal ? Intégrez en continu, plusieurs fois par jour, par tout petits incréments. Le déploiement fait peur ? Déployez si souvent, et de façon si automatisée, que cela devienne un non-événement.
1.2 Les trois sigles à ne pas confondre
On parle de « CI/CD » comme d'un bloc, mais il y a en réalité trois concepts distincts, et leur distinction est au cœur de ce cours.
| Sigle | Nom | Définition courte |
|---|---|---|
| CI | Continuous Integration (Intégration continue) | Chaque modification de code est fusionnée fréquemment dans une branche commune, puis automatiquement compilée et testée. |
| CDel | Continuous Delivery (Livraison continue) | Tout code qui passe la CI est automatiquement amené dans un état déployable. La mise en production reste déclenchée par un humain (un clic). |
| CDep | Continuous Deployment (Déploiement continu) | Tout code qui passe l'ensemble des tests est déployé en production automatiquement, sans intervention humaine. |
La différence entre Delivery et Deployment est subtile mais structurante : c'est la présence ou l'absence d'un bouton humain avant la production. En Continuous Delivery, l'artefact est prêt, validé, à un clic de la prod, mais c'est une personne qui décide du moment. En Continuous Deployment, il n'y a plus de clic : le pipeline va jusqu'au bout tout seul.
1.3 Objectifs pédagogiques
À la fin de ce cours, vous saurez : expliquer l'utilité d'une pipeline et distinguer CI / Delivery / Deployment ; décrire le cycle de vie d'une release ; comparer les stratégies de déploiement modernes ; comprendre les architectures actif/passif et actif/actif ; et mesurer une démarche CI/CD avec les métriques DORA.
2.1 Qu'est-ce qu'une release ?
Une release (ou « mise en production », ou « livraison ») est un ensemble cohérent de modifications du logiciel, identifié par une version, qui franchit une série d'étapes de validation avant d'être mis à disposition des utilisateurs finaux. Le mot-clé est cohérent : une release n'est pas « le code à un instant T », c'est un lot qu'on a décidé de faire avancer ensemble, tester ensemble, et déployer ensemble.
2.2 Les environnements
Le code ne passe jamais directement de la machine du développeur à la production. Il traverse une succession d'environnements, chacun étant une copie de l'application de plus en plus proche des conditions réelles.
| Environnement | Rôle | Qui l'utilise |
|---|---|---|
| DEV | Là où le code est écrit et testé pendant son écriture. | Les développeurs |
| Intégration / CI | Environnement éphémère où la pipeline assemble et teste automatiquement chaque modification. | La pipeline |
| Recette interne (staging) | Environnement stable où l'équipe valide les fonctionnalités avant de les montrer au client. | QA, équipe projet |
| Recette externe (UAT) | Environnement où le client / les utilisateurs métier valident que le produit répond au besoin. | Client, utilisateurs clés |
| Pré-production | Réplique aussi fidèle que possible de la production. Tests techniques finaux. | Ops, équipe technique |
| PROD | L'environnement réel, utilisé par les vrais utilisateurs. | Tout le monde |
Un principe essentiel : la configuration doit être externalisée du code. Le même artefact doit pouvoir tourner sur n'importe quel environnement, la seule chose qui change étant la configuration injectée (URL de base de données, clés d'API, niveaux de log…). C'est le principe « build once, deploy anywhere » : on construit l'artefact une seule fois, et c'est exactement cet artefact-là, déjà testé, qu'on promeut d'environnement en environnement. Recompiler à chaque étape reviendrait à tester un objet et à en déployer un autre.
2.3 Le cheminement d'une release
Voici le parcours type d'une modification, du clavier du développeur jusqu'à l'utilisateur :
Développement
│ le développeur écrit le code et ses tests
▼
Tests dev
│ tests unitaires et d'intégration (poste / CI)
▼
Recette interne
│ validation fonctionnelle par la QA
▼
Recette externe (UAT)
│ validation par le client / les utilisateurs métier
▼
Déploiement en production
│ mise à disposition des utilisateurs finaux
▼
Run / exploitation
supervision, support, mesure
Chaque flèche est une porte de qualité (quality gate) : on ne franchit l'étape suivante que si la précédente est validée. La pipeline CI/CD (module 3) est l'outil qui automatise et fait respecter ces portes.
Recette interne vs recette externe
C'est une distinction qu'on confond souvent. Les deux sont des phases de validation, mais ne répondent pas à la même question :
- La recette interne répond à : « Avons-nous bien construit le produit ? » Le logiciel est-il conforme aux spécifications, sans régression, stable ? C'est l'équipe (la QA) qui juge.
- La recette externe (UAT) répond à : « Avons-nous construit le bon produit ? » Le logiciel répond-il réellement au besoin métier ? C'est le client / l'utilisateur final qui juge.
On peut parfaitement avoir un logiciel qui passe la recette interne (zéro bug, conforme au cahier des charges) mais qui échoue la recette externe, parce que le cahier des charges lui-même ne correspondait pas au vrai besoin.
2.4 Le versionnement : semantic versioning
Pour identifier une release, on lui donne un numéro de version. La convention la plus répandue est le Semantic Versioning (SemVer), au format MAJEUR.MINEUR.CORRECTIF, par exemple 2.4.1.
- MAJEUR : changement incompatible avec les versions précédentes (breaking change).
- MINEUR : ajout d'une fonctionnalité rétrocompatible.
- CORRECTIF : correction de bug rétrocompatible.
En lisant 2.4.1 → 3.0.0, un intégrateur sait immédiatement qu'il y a un risque d'incompatibilité ; en lisant 2.4.1 → 2.4.2, il sait que c'est un correctif sans danger. Le numéro de version communique une intention.
2.5 La couche de gouvernance : ITIL
Jusqu'ici nous avons décrit le parcours technique d'une release. Mais dans une organisation, surtout une grande, une banque, un opérateur, ce parcours est encadré par une couche de gouvernance. Le référentiel le plus connu est ITIL (Information Technology Infrastructure Library), un ensemble de bonnes pratiques pour la gestion des services informatiques. Il est bien plus large que la CI/CD ; deux pratiques nous intéressent ici directement.
La gestion des changements
Tout changement apporté à un système en production est potentiellement risqué. La gestion des changements ITIL vise à ce que chaque changement soit évalué, autorisé et tracé. ITIL distingue trois types de changements :
- Changement standard : faible risque, pré-autorisé, répétitif et bien connu. Pas d'autorisation au cas par cas.
- Changement normal : doit être évalué et autorisé, souvent par un CAB (Change Advisory Board).
- Changement urgent : à appliquer en urgence (ex. correctif d'une faille critique), avec une procédure d'autorisation accélérée.
La gestion des mises en production
Cette pratique ITIL planifie, coordonne et supervise la construction, le test et le déploiement des releases : que met-on dans la release, quand la déploie-t-on, comment communique-t-on, quel est le plan de retour arrière. À retenir : la pipeline CI/CD est la mise en œuvre technique ; ITIL est le cadre organisationnel. Une pipeline sans gouvernance, c'est de la vitesse sans direction ; une gouvernance sans pipeline, c'est de la lourdeur sans bénéfice.
3.1 Qu'est-ce qu'une pipeline ?
Une pipeline (ou « chaîne ») CI/CD est une suite automatisée d'étapes que tout changement de code doit traverser, du commit jusqu'au déploiement. C'est la matérialisation, sous forme de code et d'automatisation, des portes de qualité vues au module 2. Le vocabulaire est globalement partagé entre les outils :
- Trigger (déclencheur) : l'événement qui démarre la pipeline (un push, une merge request, une planification, un déclenchement manuel…).
- Stage (étape) : un regroupement logique de travail (
build,test,deploy…), exécuté en général séquentiellement. - Job (tâche) : une unité de travail dans un stage. Plusieurs jobs d'un même stage peuvent s'exécuter en parallèle.
- Step / script : une commande élémentaire exécutée dans un job.
- Runner / agent : la machine (souvent un conteneur) qui exécute concrètement les jobs.
- Artefact : le produit d'un stage, conservé et transmis aux stages suivants (binaire, image conteneur, rapport de tests…).
3.2 Anatomie d'une pipeline : les quatre grandes étapes
┌──────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │ BUILD │──▶│ TESTS │──▶ │ TESTS │──▶│ DÉPLOIEMENT│ │ │ │ FONCTIONNELS│ │ TECHNIQUES │ │ │ └──────────┘ └──────────────┘ └──────────────┘ └─────────────┘ compile & unitaires, charge, vers les produit intégration, sécurité, environnements l'artefact E2E, SonarQube infrastructure puis la prod
Étape 1 : Build
Déclenchée à chaque modification, cette étape récupère le code, résout les dépendances, compile si nécessaire, et produit un artefact, typiquement aujourd'hui une image conteneur (Docker). C'est l'objet immuable qui sera testé puis déployé : l'étape qui matérialise le principe « build once ». Si le build échoue, la pipeline s'arrête immédiatement.
Étape 2 : Tests fonctionnels
On vérifie ici que le logiciel fait ce qu'il doit faire. Cette étape contient plusieurs niveaux, représentés par la pyramide des tests :
╱╲ Tests E2E (end-to-end)
╱ ╲ lents, coûteux, peu nombreux
╱────╲
╱ ╲ Tests d'intégration
╱ ╲ moyens
╱───────────╲
╱ ╲ Tests unitaires
╱______________╲ rapides, peu coûteux, très nombreux
- Tests unitaires : valident une fonction, une classe, isolément. Très rapides, on en a des milliers, ils tournent à chaque commit.
- Tests d'intégration : valident que plusieurs composants fonctionnent ensemble (ex. code applicatif + base de données).
- Tests end-to-end (E2E) : simulent un vrai parcours utilisateur de bout en bout, dans un navigateur (Cypress, Playwright, Selenium). Réalistes mais lents et fragiles, on en a peu.
La logique de la pyramide : beaucoup de tests rapides à la base, peu de tests lents au sommet. Une pipeline qui inverserait la pyramide (« cornet de glace ») serait lente et instable. On ajoute aussi l'analyse statique : linters et outils comme SonarQube, qui mesurent la qualité, la couverture et détectent les code smells sans exécuter le code.
Étape 3 : Tests techniques
On vérifie ici non plus ce que fait le logiciel, mais comment il se comporte en conditions réelles :
- Tests de charge / performance : le système tient-il la montée en charge ? On simule des milliers d'utilisateurs (JMeter, k6, Gatling) et on mesure temps de réponse, débit, point de rupture.
- Tests de sécurité : le SAST analyse le code source à la recherche de failles ; le DAST attaque l'application en fonctionnement ; l'analyse des dépendances (SCA) repère les bibliothèques tierces vulnérables.
- Tests d'infrastructure : si l'infra est décrite sous forme de code (Infrastructure as Code, Terraform, Ansible), on la teste elle aussi.
Étape 4 : Déploiement
L'étape qui amène l'artefact validé dans un environnement, et finalement en production. La manière de déployer fait l'objet du module 4. C'est ici que se joue la frontière : en Continuous Delivery, le pipeline s'arrête au seuil de la production et attend une validation manuelle ; en Continuous Deployment, il franchit ce seuil automatiquement.
3.3 Le prérequis qu'on oublie : la stratégie de branches
On peut avoir la plus belle pipeline du monde : si l'équipe travaille mal avec Git, il n'y aura pas de vraie intégration continue. La stratégie de branches est le prérequis humain de la CI. Trois grands modèles coexistent.
- GitFlow, modèle historique (2010), très structuré : branches
main,develop,feature/*,release/*,hotfix/*. Puissant mais lourd : les branches de fonctionnalité vivent longtemps, ce qui recrée l'integration hell. Adapté aux logiciels versionnés livrés explicitement. - GitHub Flow, beaucoup plus simple : une seule branche durable,
main, toujours déployable. Pour chaque travail, une branche courte, une pull request relue et testée par la CI, puis fusionnée. Adapté aux applications web. - Trunk-Based Development, le modèle considéré aujourd'hui comme le plus aligné avec la CI/CD. Tous les développeurs intègrent leur travail dans une branche unique (le trunk) au moins une fois par jour. Les branches, quand elles existent, vivent quelques heures.
Comment intégrer du code pas encore fini sans casser le trunk ? Deux techniques : les feature flags (on intègre le code, mais éteint, voir module 4) et le branch by abstraction (on fait évoluer le code derrière une couche d'abstraction stable).
3.4 Le panorama des outils
- GitHub Actions : intégré à GitHub, configuration en YAML dans
.github/workflows/. Très populaire, large écosystème d'actions réutilisables. - GitLab CI/CD : intégré à GitLab, configuration dans
.gitlab-ci.yml. Solution très complète, du dépôt au déploiement. - Jenkins : l'outil historique, open-source, auto-hébergé, extrêmement extensible via plugins. Plus ancien, demande davantage de maintenance, mais encore très présent.
Le principe est partout le même : la pipeline est décrite dans un fichier versionné avec le code (pipeline as code). Elle est donc relue, historisée, et évolue avec le projet.
3.5 Exemple commenté : GitHub Actions
name: CI/CD # Déclencheur : à chaque push sur main et sur chaque pull request on: push: branches: [ main ] pull_request: jobs: build-and-test: runs-on: ubuntu-latest # le runner : machine Ubuntu fournie par GitHub steps: - uses: actions/checkout@v4 # récupère le code du dépôt - name: Installer les dépendances run: npm ci # installation propre et reproductible - name: Build run: npm run build # étape 1 - construction de l'artefact - name: Tests unitaires run: npm test # étape 2 - tests fonctionnels deploy: needs: build-and-test # ne s'exécute QUE si le job précédent réussit if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest environment: production # GitHub peut exiger une validation manuelle ici steps: - uses: actions/checkout@v4 - name: Déploiement run: ./deploy.sh # étape 4 - déploiement
Points clés : le needs matérialise la porte de qualité (pas de déploiement si les tests échouent) ; le environment: production permet d'exiger une approbation humaine, c'est précisément le « bouton » du Continuous Delivery.
3.6 Exemple commenté : GitLab CI/CD
# Les étapes (stages), exécutées dans l'ordre stages: - build - test - deploy build-job: stage: build script: - npm ci - npm run build artifacts: paths: - dist/ # l'artefact est transmis aux stages suivants test-job: stage: test script: - npm test # ne démarre que si le stage build a réussi deploy-job: stage: deploy script: - ./deploy.sh environment: production rules: - if: $CI_COMMIT_BRANCH == "main" # uniquement sur main when: manual # CONTINUOUS DELIVERY : clic requis
when: manual par when: on_success ferait basculer le projet en Continuous Deployment. Une seule ligne sépare les deux régimes, c'est une décision d'organisation, pas de technologie.4.1 Le problème : déployer sans casser
Une fois l'artefact validé, il faut le mettre en production. La question n'est pas anodine : à l'instant du déploiement, des utilisateurs sont en train d'utiliser l'ancienne version. Comment passer de l'ancienne à la nouvelle sans interruption de service, et en maîtrisant le risque qu'un défaut soit passé à travers tous les tests ?
C'est ce que résolvent les stratégies de déploiement. Le critère de comparaison principal : si la nouvelle version est défectueuse, combien d'utilisateurs sont impactés, et pendant combien de temps ?
4.2 Recreate (déploiement « brutal »)
La stratégie de base : on arrête l'ancienne version, puis on démarre la nouvelle.
v1 v1 v1 (arrêt) v2 v2 v2
┌──┐┌──┐┌──┐ ▶ ┌─────────┐ ▶ ┌──┐┌──┐┌──┐
└──┘└──┘└──┘ │ INDISPO │ └──┘└──┘└──┘
└─────────┘
Avantage : simple, aucun risque de cohabitation entre versions. Inconvénient majeur : il y a une interruption de service pendant la bascule. À réserver aux environnements hors-production ou aux applications qui tolèrent une fenêtre de maintenance. C'est la référence de base à partir de laquelle on comprend les autres.
4.3 Rolling deployment (déploiement progressif)
On remplace les instances de l'ancienne version par la nouvelle une par une, progressivement. À tout moment, une partie des instances sert la v1, une autre la v2, et le service n'est jamais totalement interrompu.
Étape 1 : v2 v1 v1 v1 Étape 2 : v2 v2 v1 v1 Étape 3 : v2 v2 v2 v1 Étape 4 : v2 v2 v2 v2
Avantages : pas d'interruption ; pas besoin de doubler l'infrastructure. Inconvénients : pendant le déploiement, les deux versions coexistent, elles doivent être compatibles (notamment avec la base de données) ; le retour arrière est plus lent. C'est la stratégie par défaut de Kubernetes, donc l'une des plus répandues aujourd'hui.
4.4 Blue/Green deployment
On maintient deux environnements de production complets et identiques, Blue et Green. À un instant donné, un seul reçoit le trafic réel.
┌─────────────┐
Trafic ─▶│ BLUE v1 │ ◀── actif
└─────────────┘
┌─────────────┐
│ GREEN v2 │ ◀── on déploie et teste ici, à blanc
└─────────────┘
puis on bascule le routeur :
┌─────────────┐
│ BLUE v1 │ ◀── passif (garde-fou pour le rollback)
└─────────────┘
┌─────────────┐
Trafic ─▶│ GREEN v2 │ ◀── actif
└─────────────┘
On déploie la v2 sur l'environnement inactif (Green), on l'y teste tranquillement, puis on bascule tout le trafic d'un coup en reconfigurant le routeur.
Avantages : bascule instantanée ; retour arrière instantané (il suffit de re-router vers Blue, resté intact). Inconvénients : il faut doubler l'infrastructure ; la bascule expose 100 % des utilisateurs d'un coup à la v2.
4.5 Canary deployment
Le nom vient des canaris qu'on descendait dans les mines : si l'oiseau tombait, c'est que l'air était toxique, il servait de détecteur précoce. Ici, on expose la v2 à une petite fraction des utilisateurs (1 %, 5 %, 10 %…), on observe les métriques, et si tout va bien on augmente progressivement jusqu'à 100 %. Au moindre signal négatif, on rebascule les utilisateurs « canari » vers la v1.
95 % des utilisateurs ──▶ v1 v1 v1 v1
5 % des utilisateurs ──▶ v2 ◀── le « canari » observé
métriques OK ? on monte à 25 %, puis 50 %, puis 100 %
métriques KO ? on revient à 0 % - seuls 5 % ont été impactés
Avantages : c'est la stratégie qui minimise le rayon d'impact d'un défaut, au pire, quelques pour-cent d'utilisateurs touchés, brièvement. Inconvénients : la plus complexe à mettre en œuvre ; nécessite un routage fin du trafic et surtout une observabilité solide.
4.6 Feature flags (interrupteurs de fonctionnalité)
La technique la plus moderne, et celle qui change le plus la façon de penser. Un feature flag est un interrupteur, piloté par configuration, qui permet d'activer ou désactiver une fonctionnalité sans redéployer.
if (featureFlags.isEnabled("nouveau-tunnel-paiement")) { afficherNouveauTunnel(); } else { afficherAncienTunnel(); }
L'idée-clé : les feature flags découplent le déploiement du release. Déployer, c'est mettre le code en production (acte technique). Releaser, c'est rendre une fonctionnalité visible aux utilisateurs (acte métier). On peut donc déployer du code éteint en production pendant des semaines (ce qui rend possible le trunk-based development), puis l'allumer quand on le décide, pour tous, ou pour un segment précis (test interne, beta, déploiement géographique progressif). En cas de problème, on éteint l'interrupteur : rollback instantané, sans aucun redéploiement (kill switch).
Inconvénients : génère de la dette technique si on ne supprime pas les vieux flags ; multiplie les chemins de code à tester ; demande un outillage de gestion des flags.
4.7 Tableau comparatif
| Stratégie | Interruption ? | Coût infra | Rayon d'impact | Rollback | Complexité |
|---|---|---|---|---|---|
| Recreate | Oui | Faible | 100 % | Lent | Très faible |
| Rolling | Non | Faible | Croissant | Lent | Faible |
| Blue/Green | Non | Élevé (×2) | 100 % (bref) | Instantané | Moyenne |
| Canary | Non | Moyen | Quelques % | Rapide | Élevée |
| Feature flags | Non | Faible | Pilotable | Instantané | Moyenne |
Il n'y a pas de « meilleure » stratégie dans l'absolu. Le choix dépend du budget d'infrastructure, de la criticité du service, de la maturité de l'observabilité et du type d'application. Et ces stratégies se combinent : on peut faire un déploiement canary de code tout en pilotant l'exposition des fonctionnalités par feature flags.
4.8 Une note sur le rollback
Quelle que soit la stratégie, une règle d'or : un déploiement n'est jamais terminé tant qu'on ne sait pas revenir en arrière. Le plan de retour arrière fait partie de la release, au même titre que le code. Attention au point le plus piégeux : les migrations de base de données. Le code peut revenir en arrière instantanément ; une migration de schéma, beaucoup moins. D'où la pratique des migrations rétrocompatibles (la v1 et la v2 du code doivent toutes deux fonctionner avec le schéma courant), qui rend les déploiements zéro-downtime réellement sûrs.
5.1 Disponibilité et reprise d'activité
Déployer souvent et proprement, c'est bien. Mais que se passe-t-il si c'est l'infrastructure elle-même qui tombe, une panne de serveur, de datacenter, de région cloud ? C'est l'objet de la résilience, et elle conditionne directement la manière dont on livre.
- Haute disponibilité (HA) : la capacité du système à rester opérationnel malgré la panne d'un composant. On l'obtient par la redondance : ne jamais avoir un seul exemplaire de quoi que ce soit.
- Reprise d'activité (DR, Disaster Recovery) : la capacité à redémarrer le service après un sinistre majeur (perte d'un datacenter entier).
On mesure le DR avec deux indicateurs que tout ingénieur doit connaître :
- RTO (Recovery Time Objective) : en combien de temps doit-on avoir rétabli le service ? (durée d'indisponibilité acceptable)
- RPO (Recovery Point Objective) : quelle quantité de données peut-on se permettre de perdre, exprimée en temps ? (un RPO de 5 min = on accepte de perdre au maximum les 5 dernières minutes de données)
5.2 Architecture actif/passif
On dispose de (au moins) deux sites, deux datacenters, deux régions cloud. À un instant donné, le site actif traite l'intégralité du trafic ; le site passif est une réplique en attente, qui ne traite aucun trafic mais reçoit en permanence une réplication des données depuis le site actif.
┌──────────────────┐
Utilisateurs ───▶ │ SITE ACTIF │
│ traite 100 % │
└────────┬─────────┘
│ réplication des données
▼
┌──────────────────┐
│ SITE PASSIF │ (en attente)
│ traite 0 % │
└──────────────────┘
En cas de panne du site actif, on opère une bascule (failover) : le site passif devient actif et prend le trafic. Cette bascule peut être manuelle ou automatique, et se fait généralement en reconfigurant le DNS ou le load balancer.
Avantages : conception relativement simple ; pas de problème de cohérence puisqu'un seul site écrit les données à la fois. Inconvénients : le site passif est une ressource payée mais inexploitée en temps normal ; la bascule prend un certain temps (le RTO n'est pas nul) ; il faut tester régulièrement la bascule, sous peine de découvrir le jour J que le site passif ne fonctionne pas.
5.3 Architecture actif/actif
Ici, tous les sites traitent du trafic simultanément, en parallèle. Un répartiteur de charge (load balancer) distribue les utilisateurs entre eux.
┌──────────────────┐
┌────▶ │ SITE A - actif │ traite ~50 %
Load │ └──────────────────┘
balancer ──┤ ↕ synchronisation bidirectionnelle
│ ┌──────────────────┐
└────▶ │ SITE B - actif │ traite ~50 %
└──────────────────┘
Si un site tombe, l'autre absorbe tout le trafic : il n'y a quasiment pas d'interruption, le RTO tend vers zéro.
Avantages : aucune ressource gaspillée ; bascule quasi instantanée ; permet de répartir géographiquement les utilisateurs (chacun servi par le site le plus proche) ; absorbe mieux les pics de charge. Inconvénients : nettement plus complexe. Le défi central est la cohérence des données : si les deux sites acceptent des écritures en même temps, comment garantir qu'ils restent synchronisés sans conflit ? C'est un problème difficile (au cœur du théorème CAP), qui demande des bases de données et des architectures spécifiquement conçues pour cela.
5.4 Le lien avec la livraison
Pourquoi ce sujet dans un cours de CI/CD ? Parce que les stratégies de déploiement du module 4 sont, au fond, des applications de ces architectures :
- Le blue/green est une architecture actif/passif : Blue actif, Green passif, et « déployer » = « basculer ». La même mécanique de bascule sert à la fois pour la résilience (panne) et pour la livraison (nouvelle version).
- Un déploiement rolling ou canary suppose que l'application tourne déjà sur un parc redondant d'instances, donc une forme d'actif/actif à l'échelle des instances.
6.1 Rappel express : les méthodes de développement
La CI/CD ne tombe pas du ciel : elle prolonge une évolution des méthodes de développement.
- Le modèle historique en cascade (waterfall) enchaîne des phases longues et figées (spécification → conception → développement → test → livraison). Rigide, et l'erreur de cadrage ne se découvre qu'à la fin.
- Les méthodes agiles (manifeste Agile, 2001) y répondent par des cycles courts et itératifs, l'adaptation au changement et la livraison fréquente de valeur. Les deux cadres les plus utilisés : Scrum (le travail organisé en sprints de 1 à 4 semaines, avec des rôles, Product Owner, Scrum Master, équipe, et des rituels) et Kanban (un flux continu de tâches visualisées sur un tableau, avec une limite du travail en cours).
Le lien avec la CI/CD est direct : livrer en fin de chaque sprint n'a de sens que si livrer est devenu rapide et fiable. L'agilité crée la demande de livraisons fréquentes ; la CI/CD en fournit le moyen technique.
6.2 La culture DevOps
Pendant longtemps, deux équipes se sont fait face : les Dev (qui veulent livrer du changement vite) et les Ops (qui veulent garantir la stabilité). Leurs objectifs semblaient opposés, c'est le fameux « mur de la confusion » : le Dev « jette » son code par-dessus le mur, et l'Ops se débrouille en production.
DevOps est le mouvement culturel qui abat ce mur. Ce n'est pas un outil, ni un poste, ni une équipe : c'est un ensemble de principes.
- Responsabilité partagée : « You build it, you run it. » L'équipe qui développe est aussi responsable du bon fonctionnement en production.
- Automatisation : tout ce qui est répétitif et manuel (build, tests, déploiement, provisionnement d'infra) doit être automatisé, c'est précisément la pipeline.
- Mesure : on pilote avec des données, pas avec des impressions (voir 6.3).
- Amélioration continue : les incidents donnent lieu à des post-mortems sans blâme, on cherche la cause systémique, pas le coupable.
On entend aussi parler de SRE (Site Reliability Engineering), l'approche formalisée par Google. Elle introduit la notion d'error budget : on ne vise pas 100 % de disponibilité (impossible et ruineux) ; on définit un objectif réaliste (par exemple 99,9 %), et la différence, les 0,1 %, est un « budget » que l'équipe peut dépenser. Tant qu'il reste du budget, on déploie vite. S'il est épuisé, on gèle les nouveautés pour se concentrer sur la fiabilité. Le budget d'erreur réconcilie ainsi, chiffres à l'appui, la vitesse des Dev et la stabilité des Ops.
6.3 Mesurer : les métriques DORA
Comment savoir si une démarche CI/CD est bonne ? Le programme de recherche DORA (DevOps Research and Assessment, racheté par Google) a identifié quatre métriques clés qui prédisent la performance d'une équipe logicielle. Elles se répartissent en deux familles.
| Famille | Métrique | Question posée |
|---|---|---|
| Vitesse | Fréquence de déploiement | À quelle fréquence l'organisation déploie-t-elle en production ? |
| Lead Time for Changes | Combien de temps s'écoule entre un commit et sa mise en production ? | |
| Stabilité | Change Failure Rate | Quel % des déploiements provoque une dégradation nécessitant une correction ? |
| Recovery Time (MTTR) | En cas d'incident causé par un changement, en combien de temps rétablit-on le service ? |
Ces métriques sont précieuses car elles donnent un objectif mesurable : améliorer une pipeline, ce n'est pas une question de goût, cela se constate sur ces quatre chiffres.
7.1 Les idées à retenir
- « Si quelque chose fait mal, faites-le plus souvent. » Intégrer et déployer en continu, par petits incréments, pour transformer un événement risqué en non-événement.
- CI ⊂ Continuous Delivery ⊂ Continuous Deployment. La frontière entre Delivery et Deployment est un simple bouton humain avant la production.
- Une release traverse une chaîne d'environnements et de portes de qualité ; recette interne (« a-t-on bien construit ? ») et recette externe (« a-t-on construit le bon produit ? ») ne posent pas la même question.
- La pipeline automatise ces portes : build → tests fonctionnels → tests techniques → déploiement. Son vrai prérequis est humain : une stratégie de branches à branches courtes (trunk-based development).
- Les stratégies de déploiement se choisissent selon le rayon d'impact acceptable : recreate, rolling, blue/green, canary, feature flags. Les feature flags découplent déployer de releaser.
- Les architectures actif/passif et actif/actif servent la résilience et la livraison sans interruption, ce sont les mêmes briques.
- DevOps est une culture (responsabilité partagée, automatisation, mesure) ; les 4 métriques DORA prouvent que vitesse et stabilité progressent ensemble.
7.2 Pour aller plus loin
- Continuous Delivery, Jez Humble & David Farley, l'ouvrage de référence.
- Accelerate, Forsgren, Humble & Kim, le livre qui présente la recherche DORA.
- The Phoenix Project, Gene Kim, un roman pédagogique sur la culture DevOps.
- Le rapport annuel State of DevOps (DORA / Google Cloud).
- La documentation officielle de GitHub Actions et de GitLab CI/CD, pour pratiquer.
7.3 Lien avec le TP
Le travail pratique associé à ce cours a un objectif simple et direct : construire vous-mêmes une pipeline de CI/CD sur un projet applicatif, et faire un peu de développement. L'enjeu n'est pas la taille de l'application, mais de vivre concrètement ce que ce cours a décrit : un déclencheur sur un push, un build qui produit un artefact, des tests qui font office de porte de qualité, et un déploiement automatisé. C'est en voyant sa propre pipeline passer au vert, ou au rouge, qu'on saisit vraiment l'essence de la CI/CD.
8.1 Le bon modèle mental
Git n'est pas un « dossier synchronisé dans le cloud ». C'est un système de gestion de versions distribué : chaque développeur possède sur sa machine une copie complète de l'historique du projet. Pour bien l'utiliser, il faut visualiser trois zones en local, plus le dépôt distant.
Répertoire de Zone de Dépôt local Dépôt distant
travail préparation (historique) (GitHub / GitLab)
(working dir) (staging / index)
│ │ │ │
│── git add ───────▶│ │ │
│ │── git commit ───▶│ │
│ │ │── git push ──────▶│
│◀──────────── git pull / git clone ──────────────────────│
- Répertoire de travail : vos fichiers, tels que vous les modifiez.
- Zone de préparation (staging / index) : un sas où vous sélectionnez ce qui ira dans le prochain commit. C'est ce qui permet de ne committer qu'une partie de vos modifications.
- Dépôt local : l'historique de tous les commits, sur votre machine. On peut y travailler sans connexion.
- Dépôt distant (remote, appelé
originpar défaut) : la copie partagée, avec laquelle on synchronise.
Un commit est un instantané (snapshot) de l'état du projet à un instant donné, identifié par une empreinte unique (un hash). Une branche n'est rien d'autre qu'un pointeur mobile vers un commit. Comprendre ces quelques objets, c'est comprendre l'essentiel de Git.
8.2 Le workflow d'une journée de développement
1. git pull # récupérer les derniers changements 2. git switch -c feature/ma-fonction # créer une branche de travail 3. ... coder ... 4. git status # voir ce qui a changé 5. git add fichier1 fichier2 # préparer les fichiers 6. git commit -m "feat: ajoute X" # enregistrer un commit ↑ répéter 3→6 par petits incréments 7. git push -u origin feature/ma-fonction # publier la branche 8. ... ouvrir une Pull / Merge Request ... 9. ... relecture + CI verte → fusion dans main ...
8.3 Les branches en pratique
Une branche permet de travailler sur une fonctionnalité sans perturber le code stable (main).
git branch # lister les branches existantes git switch -c feature/login # créer une branche ET basculer dessus git switch main # revenir sur main git merge feature/login # fusionner dans la branche courante git branch -d feature/login # supprimer une branche devenue inutile
git switch et git restore (Git 2.23+) remplacent l'ancien git checkout, qui faisait trop de choses à la fois. Vous croiserez encore beaucoup git checkout dans les tutoriels : sachez que git checkout -b ≡ git switch -c.Le choix de la stratégie de branches (GitFlow, GitHub Flow, trunk-based) est traité au module 3.3. Pour un TP, le plus simple et le plus sain est le GitHub Flow : main toujours stable, une branche courte par fonctionnalité, une Pull Request pour fusionner.
8.4 Collaborer : Pull Requests et conflits
La Pull Request (GitHub) ou Merge Request (GitLab) est la demande de fusionner votre branche dans main. Elle a trois rôles : déclencher la relecture par les pairs (code review), déclencher la pipeline CI automatiquement, et tracer la discussion. On ne fusionne que si la review est validée et la CI est verte, c'est une porte de qualité (module 2).
Un conflit de fusion survient quand deux branches ont modifié les mêmes lignes d'un fichier. Git ne peut pas décider à votre place et marque la zone ainsi :
<<<<<<< HEAD le code de la branche courante ======= le code de la branche que l'on fusionne >>>>>>> feature/login
Pour le résoudre : ouvrez le fichier, choisissez la bonne version (en supprimant les marqueurs <<<, ===, >>>), puis git add fichier-resolu suivi de git commit. Un conflit n'est pas une erreur ni un drame : c'est juste Git qui vous demande de trancher. Les conflits sont d'autant plus rares et petits que l'on intègre souvent (revoilà la CI).
8.5 Les commandes de sauvetage (« au secours »)
Ce sont les commandes qui rassurent : presque tout est rattrapable avec Git.
git restore fichier # annuler les modifs NON commitées d'un fichier git restore --staged fichier # retirer un fichier du staging git stash # mettre de côté tout le travail en cours... git stash pop # ...et le récupérer plus tard git revert <hash> # créer un commit qui ANNULE un commit (sûr) git reset --soft HEAD~1 # annuler le dernier commit, GARDER les modifs git reset --hard HEAD # /!\ DANGER : tout réinitialiser, modifs PERDUES git reflog # historique de TOUS les déplacements de HEAD
- git revert vs git reset :
revertajoute un nouveau commit qui défait un ancien, sans réécrire l'histoire, donc sûr sur une branche partagée.resetréécrit l'histoire, à réserver à des commits locaux non encore poussés. - git reflog est le filet de sécurité ultime. Même après un
reset --hardmalheureux, Git garde la trace de l'ancien commit pendant des semaines :reflogpermet de retrouver son empreinte et d'y revenir. Tant qu'un travail a été commité au moins une fois, il est presque toujours récupérable.
8.6 Bonnes pratiques & messages de commit
- Committez tôt, committez souvent. Un commit = une idée.
- Soignez le message de commit. Une convention répandue, Conventional Commits, préfixe le message par un type :
feat:(fonctionnalité),fix:(correction),docs:,test:,refactor:,chore:. Ces préfixes se relient au Semantic Versioning du module 2 (feat:→ version mineure,fix:→ correctif). - Ne committez jamais de secrets (mots de passe, clés d'API, tokens) ni de fichiers générés (
node_modules/,dist/,.env). Listez-les dans un fichier.gitignoreà la racine du dépôt. - Faites git pull avant de commencer à travailler et avant de pousser, pour limiter les conflits.
- Une branche = une fonctionnalité, et une branche courte (quelques heures à quelques jours, pas quelques semaines).
8.7 Cheat sheet Git
Démarrer & configurer
| Commande | Effet |
|---|---|
| git config --global user.name "Nom" | Définir son nom (une fois) |
| git config --global user.email "mail" | Définir son email (une fois) |
| git clone <url> | Cloner un dépôt distant existant |
| git init | Initialiser un dépôt dans le dossier courant |
Au quotidien
| Commande | Effet |
|---|---|
| git status | Voir l'état des fichiers (le réflexe à avoir) |
| git add <fichier> | Préparer un fichier pour le commit |
| git add . | Préparer toutes les modifications |
| git commit -m "message" | Enregistrer un commit |
| git commit -am "message" | add + commit des fichiers déjà suivis |
| git push | Envoyer ses commits au dépôt distant |
| git pull | Récupérer et fusionner les commits distants |
| git fetch | Récupérer les commits distants sans fusionner |
Branches
| Commande | Effet |
|---|---|
| git branch | Lister les branches |
| git switch <branche> | Changer de branche |
| git switch -c <branche> | Créer une branche et basculer dessus |
| git merge <branche> | Fusionner une branche dans la branche courante |
| git branch -d <branche> | Supprimer une branche |
| git push -u origin <branche> | Publier une branche pour la première fois |
Inspecter
| Commande | Effet |
|---|---|
| git log --oneline --graph | Historique compact et visuel |
| git diff | Modifications non encore préparées |
| git diff --staged | Modifications préparées (en staging) |
| git show <hash> | Détail d'un commit précis |
| git blame <fichier> | Voir qui a modifié chaque ligne |
Réparer & sauver
| Commande | Effet |
|---|---|
| git restore <fichier> | Annuler les modifs non commitées d'un fichier |
| git restore --staged <fichier> | Retirer un fichier du staging |
| git stash / git stash pop | Mettre de côté / récupérer le travail en cours |
| git revert <hash> | Annuler un commit via un nouveau commit (sûr) |
| git reset --soft HEAD~1 | Annuler le dernier commit, garder les modifs |
| git reset --hard HEAD | /!\ Tout réinitialiser, modifs perdues |
| git reflog | Retrouver un commit « perdu » (filet de sécurité) |
| git cherry-pick <hash> | Appliquer un commit précis sur la branche courante |