QCM d'ouverture
La séance commence par 20 minutes de QCM sur papier. Les questions portent sur les notions du cours-02 : Docker, GitHub Flow, Git Flow, Pull Requests, release branches, hotfixes et logique globale des workflows étudiés.
Posez le stylo quand le temps est écoulé.
Release-Based Workflow
GitHub Flow fonctionne très bien tant qu'une seule ligne courante suffit. Mais certains produits doivent fournir des livrables distincts, figer une version pour un audit, ou maintenir plusieurs versions majeures en parallèle. Dans ce cas, la release devient une branche explicite de stabilisation, pas seulement un tag posé à la fin.
Une release est un sanctuaire de stabilité
Dans le dépôt du TP, main représente la ligne
d'intégration de la prochaine version. La branche
release/v1.0 représente une version déjà livrée,
taguée v1.0.0, et release/v1.1 sera
créée depuis main lorsque la prochaine version
devra être stabilisée.
Une nouvelle fonctionnalité n'est jamais développée directement
sur une branche release/*. Ces branches restent des
sanctuaires destinés à la recette, à la stabilisation et aux
correctifs de bugs. Une feature part de main ;
une release ne reçoit que ce qui doit rendre un livrable sûr.
Même métier, mais plusieurs lignes à garder cohérentes
Une nouvelle fonctionnalité comme
GET /tasks/stats part de main, puis
la branche release/v1.1 est créée depuis
main au moment du gel de version. Un correctif
urgent, par exemple la validation du champ title,
part de release/v1.0, puis doit être reporté sur
main et sur release/v1.1 si le bug y
existe aussi.
Le coût caché : aligner les versions parallèles
Le Release-Based Workflow protège les versions livrées, mais il
crée une obligation de synchronisation. Un correctif appliqué
sur release/v1.0 ne corrige pas automatiquement
main ni release/v1.1. Le
cherry-pick devient donc un geste important pour
reporter un commit précis sans fusionner toute l'histoire d'une
branche dans une autre.
Pourquoi ce flow est-il particulièrement adapté aux livrables audités ou maintenus en parallèle ?
Parce qu'une branche release/* matérialise un état
de code précis, stabilisé et contrôlable. Elle peut être testée,
certifiée, livrée à un client, puis corrigée sans absorber toutes
les nouveautés de main.
En échange, l'équipe doit suivre explicitement où chaque bug
existe. Si le même défaut touche release/v1.0,
main et release/v1.1, le correctif doit
être reporté sur chaque ligne concernée.
Ce gitGraph illustre le cycle à retenir : une
release v1.0.0 déjà taguée, une fonctionnalité
préparée sur main, une release/v1.1
créée pour stabiliser la suite, et un hotfix reporté par
cherry-pick.
Chargement du gitGraph…
TP 3 : Release-Based Workflow (20 min)
Objectif : pratiquer un flow dans lequel une version déjà livrée
peut recevoir un correctif, pendant que la prochaine version est
préparée sur main puis stabilisée dans
release/v1.1.
Dépôt support (à forker sur GitHub avant de cloner) : github.com/GVI2026/tp-release-based-workflow
À observer :
main et release/v1.0 n'ont pas le même
rôle. La branche release/v1.0 contient déjà le commit
chore(release): bump project to version 1.0.0, tagué
v1.0.0. Une feature prépare la suite sur
main ; un hotfix corrige une version déjà livrée.
À réussir : appliquer un correctif critique sur la bonne release, puis le reporter sur les autres lignes où le bug existe encore.
Quel geste Git permet de reporter précisément un correctif de
release/v1.0 vers main et
release/v1.1 sans
fusionner toute la branche ?
Le geste attendu est le cherry-pick. Il applique un
commit précis sur une autre branche, ce qui permet de garder
plusieurs versions parallèles alignées sur un correctif critique
sans mélanger leurs cycles de release.
GitLab Flow
GitLab Flow répond à un autre besoin : organiser le passage du code
entre des environnements. Il reste proche d'un flow à branche
principale, mais ajoute des branches ou règles de déploiement qui
représentent les étapes de validation avant la production. Le
gitGraph ci-dessous montre une promotion de main vers
staging, puis de staging vers
production.
Principe :
main reçoit les features intégrées, puis une Pull
Request de promotion amène ce code vers staging.
Les versions candidates y sont taguées en rc (release-candidate) avant
la promotion finale vers production.
Usage typique : un service Cloud ou Web critique, par exemple la plateforme d'accès aux comptes d'une banque, où l'enjeu principal est de tester dans un environnement de pré-production proche du réel.
Point d'attention : GitLab Flow structure surtout la promotion entre environnements ; ce n'est pas le meilleur outil si le problème central est de maintenir plusieurs livrables clients figés en parallèle.
Chargement du gitGraph…
Trunk-Based Development
Le Trunk-Based Development est abordé ici comme une direction
possible, accessible aux équipes qui intègrent très fréquemment et
qui disposent déjà d'une pipeline CI/CD fiable et mature. Par
rapport à GitHub Flow, la différence n'est pas l'existence de
main, mais la durée très courte, voire l'absence, des
branches de travail.
Principe :
une branche principale unique, souvent main ou
trunk, sur laquelle les intégrations sont très
fréquentes.
Feature flags : ils permettent de masquer une fonctionnalité incomplète sans la garder éternellement sur une branche longue.
Release à chaque commit :
dans un modèle respecté à 100 %, chaque commit accepté sur
main peut déclencher une release. En pratique, une
équipe peut nuancer ce principe : par exemple, déployer le code
automatiquement mais garder une fonctionnalité désactivée derrière
un feature flag jusqu'à validation métier.
Pas toujours de PR :
dans un trunk-based strict, du code peut être ajouté directement
sur main si la CI/CD, les tests et les garde-fous
automatisés sont assez solides. Beaucoup d'équipes gardent quand
même des Pull Requests très courtes pour conserver une revue
légère sans recréer des branches longues.
Merge queues : elles sérialisent les intégrations pour réduire le risque de casser la branche principale au moment du merge.
Prérequis : une pipeline CI/CD fiable, rapide et lisible est indispensable pour que ce mode de travail soit viable.
Que se passe-t-il lorsqu'une feature buggée est ajoutée à la main sans revue de code ?
La CI/CD devient la première protection. Si la feature casse un test, le build, une règle de qualité ou une vérification de sécurité, la pipeline échoue, bloque le déploiement et remonte une alerte à l'équipe. Le commit est alors corrigé rapidement, annulé, ou la fonctionnalité est désactivée derrière un feature flag avant d'être visible par les utilisateurs.
Si le défaut passe malgré toutes les vérifications, le risque est plus élevé qu'avec une revue humaine classique. C'est pour cela que le Trunk-Based Development demande des tests rapides, fiables, une surveillance claire et une capacité de rollback ou de désactivation immédiate.
Chargement du gitGraph…
Tableau comparatif final des flows
Aucun flow n'est universel. Un projet peut très bien évoluer d'un mode très simple vers un flow plus structuré à mesure que la taille de l'équipe, le nombre de versions supportées et l'exigence qualité augmentent.
Sans flow réel : acceptable au tout début d'un prototype individuel, mais fragile.
GitHub Flow :
bon point d'entrée dès qu'une intégration fréquente sur une ligne
courante claire est visée ; l'équipe peut rester sur ce modèle en
choisissant elle-même quand générer une release, par exemple avec
release-please.
Git Flow : utile pour les projets à livraison manuelle ou communautaire, où des barrières humaines et un processus de validation rigide protègent la production.
GitLab Flow : pertinent pour un service Cloud ou Web critique qui doit passer par une pré-production avant de toucher les serveurs de production.
Release-Based Workflow : adapté aux livrables distincts, aux audits sur code figé et à la maintenance de plusieurs versions en parallèle.
Trunk-Based Development : logique quand la maturité CI/CD permet des intégrations très fréquentes sur un tronc unique.
Cette trajectoire synthétise la progression réaliste d'un projet.
Chargement du schéma…
Quel flow choisir pour un projet open source livré manuellement avec une forte revue humaine avant chaque version ?
Git Flow. Le besoin principal est de protéger une livraison manuelle avec des étapes explicites de préparation, validation, hotfix et tag.
Quel flow choisir pour un service bancaire en ligne qui doit passer par un environnement staging avant production ?
GitLab Flow. Le critère dominant est la promotion contrôlée du code entre environnements, avec une barrière de pré-production avant les serveurs réellement utilisés par les clients.
Quel flow choisir pour maintenir deux versions majeures certifiées chez des clients différents ?
Release-Based Workflow. Le point clé est de garder plusieurs livrables figés et maintenus en parallèle, tout en reportant les correctifs critiques sur chaque version concernée.
DevOps et CI/CD
Les flows présentés posent tous la même question en filigrane : comment garder confiance dans les changements quand plusieurs branches, plusieurs versions et plusieurs personnes sont actives en même temps ? DevOps et la CI/CD sont précisément la réponse industrielle à cette question.
DevOps : briser les silos
Pendant longtemps, développement et exploitation fonctionnaient en silos séparés avec des objectifs mesurés différemment. Les développeurs étaient évalués sur la quantité de fonctionnalités livrées ; les équipes d'exploitation sur la stabilité du système. Résultat : chaque mise en production devenait un moment de friction, de ralentissement et de méfiance mutuelle.
DevOps est d'abord une réponse culturelle et organisationnelle : aligner les équipes sur un objectif commun — livrer de la valeur rapidement et de façon fiable. L'outillage (CI/CD, monitoring, infrastructure as code) vient ensuite rendre cette collaboration concrète et répétable.
Le cycle DevOps est continu : il passe par la planification, le code, la vérification, le packaging, le déploiement, la configuration, la surveillance… puis revient à la planification à partir de ce qui est observé en production.
Chargement du cycle DevOps…
Que se passe-t-il quand un bug critique est découvert en production si Dev et Ops ont des objectifs mesurés séparément ?
L'équipe Dev peut considérer que le bug est "en prod donc c'est un problème Ops". L'équipe Ops peut refuser de déployer un correctif précipité qui risquerait de déstabiliser le système. Personne n'est incité à résoudre rapidement, car la responsabilité partagée n'est pas mesurée.
DevOps supprime cette friction en rendant les deux équipes co-responsables du même résultat : un service stable et évolutif.
CI, Continuous Delivery et Continuous Deployment (CD)
Ces trois pratiques forment un spectre progressif : chaque niveau automatise davantage, et chaque niveau suppose que le précédent fonctionne de façon fiable.
Intégration Continue (CI) : chaque commit déclenche automatiquement une vérification — formatage, lint, tests, build. L'objectif est de détecter immédiatement si le changement casse quelque chose dans le projet. Sans CI solide, les deux pratiques suivantes n'ont pas de fondation.
Continuous Delivery : la CI est complétée par une automatisation du packaging et de la préparation à la mise en production. L'artefact est toujours prêt à être déployé. Le déploiement lui-même reste déclenché manuellement — souvent pour des raisons métier ou réglementaires.
Continuous Deployment : le déploiement en production est lui aussi automatisé. Dès qu'un commit passe toutes les vérifications, il part en production sans intervention humaine. Cela suppose une confiance très élevée dans la pipeline et dans les tests.
Chargement du spectre CI/CD…
Dépôt CI pédagogique — temps 1 : prise en main guidée (20 min)
Dépôt support : GVI2026/tp-ci-api
Comme pour les autres TP du cours, ce dépôt doit d'abord être forké sur un compte GitHub avant d'être manipulé.
La théorie CI/CD étant posée, le dépôt pédagogique permet de lire un vrai workflow pour la première fois. L'objectif n'est pas encore de corriger quoi que ce soit, mais de repérer la structure avant d'en étudier l'anatomie en détail.
-
Repérer et lire le fichier
.github/workflows/ci.yml.
Workflow :
orchestration complète décrite dans un fichier YAML sous
.github/workflows/.
Event / Trigger :
événement qui déclenche la pipeline, par exemple
push, pull_request ou
schedule.
Job : unité d'exécution logique du workflow, exécutée sur son propre runner.
Step : action unitaire à l'intérieur d'un job, sous forme de script shell ou d'action réutilisable.
Runner : machine fraîche qui exécute un job.
Action :
brique réutilisable appelée avec uses:, par
exemple actions/checkout@v4.
Combien de jobs sont définis dans
.github/workflows/ci.yml, et quel est le rôle du
job qui s'exécute en premier ?
Le workflow contient cinq jobs : install,
format-lint, tests,
build et security. Le premier à
s'exécuter est install, dont le rôle est
d'installer les dépendances npm et de les stocker en cache
pour tous les jobs suivants. Si le cache est déjà présent,
l'étape npm ci est ignorée.
Ce mécanisme est documenté en détail dans
docs/fonctionnement-cache.md du dépôt.
Pour terminer cette prise en main, lancer la pipeline complète pour la première fois. Le premier lancement est plus long car les images Docker doivent être téléchargées :
act
Ce premier run peut prendre plusieurs minutes. La structure de la pipeline sera analysée en détail dans la section suivante.
Anatomie d'une pipeline GitHub Actions
Lorsqu'un commit est poussé, voici ce qui se passe concrètement côté GitHub Actions.
Un événement
(push, pull_request, ou encore un
planning schedule) déclenche l'exécution d'un
workflow —
un fichier YAML dans .github/workflows/. Ce
workflow décrit un ensemble de
jobs.
Chaque job s'exécute sur sa propre machine virtuelle fraîche,
appelée runner.
À l'intérieur d'un job, les
steps
s'enchaînent séquentiellement. Un step est soit un script
shell (run: npm test), soit une
action
réutilisable (uses: actions/checkout@v4).
Les jobs peuvent avoir des dépendances entre eux via
needs:. L'ensemble des jobs et de leurs dépendances
forme un DAG
(Directed Acyclic Graph) — un graphe orienté sans cycle. Ce
graphe rend visibles à la fois les dépendances obligatoires et
les opportunités de parallélisation.
Chargement de l'anatomie pipeline…
Le principe fail-fast
Placer les vérifications les plus rapides et les moins coûteuses en premier dans la chaîne n'est pas arbitraire : c'est le principe fail-fast. Un job qui échoue arrête immédiatement tous les jobs qui en dépendent. Inutile de compiler si le formatage du code est déjà incorrect. Inutile de scanner les dépendances si les tests unitaires échouent.
Voici la pipeline du dépôt pédagogique. Elle se lit de gauche à droite : chaque flèche en pointillés indique qu'un échec ici stoppera tous les jobs à droite. L'ordre sert à obtenir le diagnostic utile le plus tôt possible.
Le feedback loop : la valeur d'une pipeline ne se mesure pas seulement à ce qu'elle détecte, mais à la vitesse à laquelle elle renvoie l'information au développeur. Un retour en 2 minutes permet de corriger immédiatement. Un retour en 45 minutes implique un changement de contexte mental qui multiplie le temps de correction réel.
Chargement du graphe CI…
Descriptions des jobs
format-lint : vérifie le formatage et lance l'analyse statique. C'est le premier filtre de qualité : il détecte les erreurs mécaniques et les incohérences faciles à corriger.
tests : exécute les tests automatisés pour vérifier que le comportement attendu de l'application est toujours respecté.
build : compile l'application et confirme que le projet peut produire un artefact exploitable.
security : analyse les dépendances pour repérer les vulnérabilités connues avant qu'elles n'arrivent dans une chaîne de livraison.
Shift-left : détecter tôt, corriger moins cher
Dans un modèle traditionnel, les vérifications arrivent tard : les tests manuels et les audits de sécurité interviennent juste avant la mise en production. À ce stade, corriger un bug est entre 10 et 100 fois plus coûteux qu'en phase de développement, parce que l'auteur du code a changé de contexte, que d'autres fonctionnalités ont été empilées dessus, et que l'impact d'un correctif est plus difficile à isoler.
Le shift-left consiste à avancer toutes les vérifications possibles vers la gauche du cycle de vie du code. Concrètement, la CI exécute automatiquement formatage, lint, tests, build et contrôles de sécurité dès qu'un changement est proposé, au lieu d'attendre une phase de validation tardive.
Le shift-left explique donc quand les vérifications doivent arriver : pendant le développement et l'intégration. Le fail-fast explique ensuite dans quel ordre les organiser dans la pipeline pour renvoyer le diagnostic le plus utile le plus tôt possible.
À quelle étape de la pipeline est-il le moins coûteux de détecter une erreur ?
Le plus tôt possible — idéalement dans le job
format-lint. Une erreur attrapée là prend
quelques secondes à corriger : le fichier est édité et la
vérification relancée. Aucun contexte n'est perdu.
À l'inverse, une erreur qui n'est détectée qu'en production oblige à analyser des logs en direct, à réverter un déploiement, parfois à réveiller des personnes. Le coût humain et technique est sans commune mesure.
Dépôt CI pédagogique — temps 2 : exercices et correction (60 min)
Le but est maintenant de diagnostiquer puis corriger une CI cassée. Le dépôt a été conçu pour que les pannes soient réalistes, lisibles et rapides à interpréter.
Depuis un fork de tp-ci-api, GitHub Actions peut être
activé pour observer les mêmes exécutions directement sur GitHub, en
complément de act en local.
Pipeline de référence à garder en tête
install → format-lint → tests → build → security
L'ordre n'est pas arbitraire. Il sert à détecter vite les erreurs les moins coûteuses à diagnostiquer avant de mobiliser des étapes plus longues.
Commandes utiles pendant le TP
npm run format:check
npm run lint
npm run test:ci
npm run build
act
act -j format-lint
act -j tests
Exercice 1 — corriger une étape qualité simple
Niveau : Débutant
Branche : exercise/01-format-lint. L'objectif est de
lire le bon log, puis de corriger un problème de formatage ou de
lint sans modifier inutilement le reste du projet.
Exercice 2 — réparer un test unitaire
Niveau : Débutant
Branche : exercise/02-test-failure. L'échec est
volontairement simple à comprendre : le test doit être repéré,
son intention relue, puis le test ou le code testé doit être corrigé.
Exercice 3 — remettre la pipeline dans un ordre fail-fast
Niveau : Intermédiaire
Branche : exercise/03-pipeline-order. Le travail
consiste à réorganiser les dépendances de jobs dans
.github/workflows/ci.yml pour retrouver une chaîne
logique et lisible.
Exercice 4 — lire les logs et trouver la bonne cause
Niveau : Intermédiaire
Branche : exercise/04-log-reading. Ici, l'enjeu n'est
pas seulement de corriger : il faut surtout savoir lire le bon job,
la bonne step et le bon message d'erreur.
Exercice 5 — stabiliser la chaîne complète
Niveau : Avancé
Branche : exercise/05-stabilize. Cette branche sert à
vérifier qu'un ordre de diagnostic cohérent peut être appliqué
jusqu'au retour complet au vert.
Bonus — paralléliser une partie simple du DAG
Niveau : Avancé
Branche : bonus/parallelization. Ce bonus est
proposé à ceux qui ont terminé les exercices précédents. Le but
est de séparer proprement des vérifications indépendantes sans
rendre la lecture du graphe inutilement compliquée.
Conclusion et ouverture
En trois séances, le module est passé d'un usage local de Git à des workflows d'équipe structurés, puis à la question que tous ces flows soulèvent : comment garder confiance dans les changements quand les branches, les versions et les intégrations se multiplient ?
La CI répond à la première partie de cette question : détecter vite, corriger tôt, intégrer en confiance. L'autre partie — livrer en production de façon fiable et automatisée — sera l'objet du prochain cours, consacré au Continuous Delivery et au Continuous Deployment.