QCM de reprise du cours-03
La séance commence par 20 minutes de QCM sur papier. Les questions portent sur la fin du module précédent : CI, fail-fast, shift-left, métriques DORA, anatomie d'une pipeline et place du Trunk-Based Development dans la progression du module.
Les réponses attendues sont ci-dessous, cachées par défaut. Elles servent à la correction et à votre réactivation de mémoire, pas à remplacer le raisonnement pendant le QCM.
Quelle différence devez-vous être capables d'expliquer entre CI, Continuous Delivery et Continuous Deployment ?
La CI vérifie automatiquement chaque changement : formatage, lint, tests, build. Elle dit si le code reste sain.
La Continuous Delivery ajoute le packaging et la préparation à la mise en production : l'artefact est prêt à partir, mais un humain choisit le moment.
Le Continuous Deployment automatise aussi la dernière étape : si tout passe, la mise en production part sans validation humaine supplémentaire.
Pourquoi la logique fail-fast impose-t-elle un ordre précis entre les jobs d'une pipeline ?
Parce qu'un job peu coûteux doit échouer avant un job plus long ou plus cher à diagnostiquer. On place donc le formatage et le lint avant les tests, puis les tests avant le build, puis le build avant les étapes de livraison.
L'objectif n'est pas seulement d'aller vite. C'est surtout de renvoyer le bon diagnostic le plus tôt possible, quand le développeur a encore le contexte en tête.
Pourquoi le shift-left réduit-il le coût de correction ?
Plus une erreur est détectée tôt, moins elle a contaminé le reste du système et moins il faut reconstruire du contexte pour la corriger. Une erreur vue au lint coûte quelques secondes ; en production, elle peut coûter un incident, un rollback et une coordination humaine importante.
Job, step, runner, artefact, secret : quelles définitions devez-vous maîtriser ?
Job : unité logique d'exécution dans un workflow.
Step : action unitaire à l'intérieur d'un job.
Runner : machine qui exécute le job.
Artefact : résultat produit par la pipeline et réutilisable ensuite, par exemple un build ou un package.
Secret : donnée sensible injectée sans être écrite en clair dans le YAML.
Quelle différence clé devez-vous retenir entre GitLab Flow et Trunk-Based Development ?
GitLab Flow accepte plusieurs lignes actives, par exemple une branche courante et une branche de maintenance. Le Trunk-Based Development cherche au contraire à intégrer très souvent sur une branche principale unique.
Cette différence implique une exigence plus forte côté CI/CD pour le Trunk-Based : sans pipeline très fiable et feature flags, il devient vite impraticable.
Quelles métriques DORA doivent encore vous parler et à quoi servent-elles ?
Les repères les plus utiles ici sont la fréquence de déploiement, le délai entre commit et production, le temps de retour à un état stable après incident et le taux d'échec des changements. Ils servent à juger la performance réelle d'une chaîne de livraison, pas seulement son apparence.
CI vers CD : le chaînon manquant
Le cours-03 répondait à la question « est-ce que ce changement est encore sain ? ». Le cours d'aujourd'hui répond à la question qui vient juste après : « maintenant que le code passe, qu'est-ce qu'on en fait ? ».
La CI valide, elle ne livre pas. Tant qu'aucun artefact n'est versionné, publié puis déployé, on sait seulement que le code tient encore dans un environnement de vérification.
Continuous Delivery : le code est toujours déployable. Un humain décide quand lancer la mise en production.
Continuous Deployment :
la mise en production part automatiquement dès qu'un changement sur
main a passé toutes les vérifications. Cette étape
suppose plus de maturité : couverture de tests solide,
observabilité, rollback, culture d'incident maîtrisée.
Build once, deploy many : on construit l'artefact une seule fois, puis on le promeut sans le reconstruire. Ce qui change entre DEV, STAGING et PROD, c'est la configuration, pas le binaire ni le package publié.
Pourquoi ne pas viser immédiatement le déploiement continu ? Parce qu'une Delivery rigoureuse n'est pas une version ratée du Deployment. C'est souvent l'étape de maturité qui permet ensuite de rendre le dernier clic optionnel, puis inutile.
La lecture minimale à retenir est celle-ci : la validation est un prérequis, la publication d'artefact est un passage, puis le choix humain ou non détermine si vous êtes en Delivery ou en Deployment.
Chargement du flowchart…
Quels risques prenez-vous si vous activez un déploiement continu trop tôt dans une organisation encore immature ?
Vous automatisez la vitesse sans automatiser la maîtrise : peu de tests, peu d'observabilité, pas de rollback fiable, et donc des incidents plus fréquents et plus chers.
Le problème n'est pas l'automatisation elle-même. Le problème est de supprimer le garde-fou humain avant d'avoir construit les garde-fous techniques qui doivent le remplacer.
Feature Flags : déployer sans livrer
Le Trunk-Based Development ne dit pas « tout le monde code en vrac
sur main ». Il dit plutôt « tout le monde intègre tôt,
souvent, sur une ligne centrale fiable ». Pour rendre cela viable en
production, il faut découpler le déploiement technique de la mise à
disposition utilisateur.
Feature flag :
un interrupteur dans le code ou dans la configuration. La
fonctionnalité est présente dans l'artefact déployé, mais elle
reste inactive tant que le flag est à false.
Dans le contexte d'une API NestJS, un simple
FEATURE_NEW_ENDPOINT=false suffit déjà à illustrer le
principe : la route n'est pas exposée tant que la configuration ne
l'autorise pas.
if (process.env.FEATURE_NEW_ENDPOINT === 'true') {
// enregistrer le contrôleur ou activer le comportement
}
Avantages : pas de rollback lourd pour couper une fonctionnalité, possibilité de déployer plus souvent, et vraie séparation entre déploiement technique et release visible par les utilisateurs.
Limites : dette technique si les flags s'accumulent, tests à maintenir pour les deux états, et complexité de configuration croissante.
Le gitGraph ci-dessous montre l'idée essentielle : une
branche courte est intégrée tôt, le code part en production avec un
flag OFF, puis l'activation se fait séparément.
Chargement du gitGraph…
Si une fonctionnalité est derrière un flag OFF en production, devez-vous quand même la tester ?
Oui. Sinon, vous déployez volontairement du code non testé en espérant qu'il restera éteint. Le jour où quelqu'un activera le flag, le risque reviendra immédiatement.
SemVer, Conventional Commits et outillage de release
Pour automatiser une chaîne CD, il faut un mécanisme fiable qui transforme l'historique Git en version livrable. C'est là que SemVer et les Conventional Commits prennent une valeur opérationnelle.
PATCH pour une correction rétrocompatible, MINOR pour une nouvelle fonctionnalité rétrocompatible, MAJOR pour une rupture de compatibilité.
Côté commits, fix: déclenche typiquement un patch,
feat: un minor, et un ! ou un
BREAKING CHANGE: dans le corps signale un major.
Release Please
Release Please ouvre une Pull Request de release. L'équipe relit, merge, puis la release est matérialisée. C'est très utile pour un contexte de Continuous Delivery avec validation humaine explicite.
Semantic Release
Semantic Release agit directement à partir de l'historique des
commits sur main : calcul de version, changelog,
tag Git, publication. C'est l'outillage qui colle le mieux à une
logique de Continuous Deployment
intégral.
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/git"
]
}
Cohérence cours / TP :
dans le cours, nous parlons explicitement de Release Please et de
Semantic Release parce qu'ils rendent visible la différence entre
Delivery et Deployment. Dans le TP réel, le dépôt utilise
commit-and-tag-version pour simplifier l'exercice en
environnement local avec act.
L'idée pédagogique reste la même : des Conventional Commits pilotent un versioning automatisé. Simplement, le TP évite de vous faire passer du temps sur la plomberie Git supplémentaire qu'impliquerait une intégration complète de Semantic Release dans des runners locaux éphémères.
Que doivent produire ces messages de commit : fix:, feat!, chore: ?
fix: déclenche un bump PATCH.
feat! déclenche un bump MAJOR car il signale une rupture de compatibilité.
chore: ne déclenche généralement aucun bump de version par défaut.
Pourquoi Release Please n'est-il pas, à lui seul, du Continuous Deployment complet ?
Parce qu'il garde une étape humaine structurante : le merge de la Pull Request de release. Tant que cette action manuelle existe, le passage de l'historique Git à la release finale n'est pas totalement automatique.
Tests E2E avec Supertest
Si la CI devient aussi une chaîne de livraison, la qualité attendue avant le déploiement augmente. Les tests unitaires restent indispensables, mais ils ne suffisent pas à eux seuls pour garantir qu'une API répond correctement de bout en bout.
Tests unitaires : ils isolent une fonction, un service ou une règle métier à l'aide de mocks et de dépendances simulées.
Tests E2E : ils envoient de vraies requêtes HTTP à l'application démarrée en mémoire pour vérifier le routing, la validation, la réponse et le comportement global d'une fonctionnalité.
Supertest permet justement cela dans un projet NestJS sans devoir lancer un serveur réseau complet sur un port public.
// Démarrer le module NestJS en mémoire
// Envoyer GET /tasks
// Vérifier status 200 et structure de la réponse
// Fermer proprement l'application de test
Dans le TP réel, la CI contient déjà cette étape :
tests-e2e s'exécute après les tests unitaires et avant
le build.
C'est cohérent avec le risque : si l'API ne répond plus correctement, construire puis publier un artefact n'a plus d'intérêt.
Si un test E2E valide déjà POST /tasks, pouvez-vous supprimer les tests unitaires du service ?
Non. Les E2E sont moins nombreux, plus lents et moins précis pour explorer des branches internes ou des cas limites métier. Ils complètent les tests unitaires ; ils ne les remplacent pas.
Verdaccio : registre d'artefacts npm
Un serveur de production ne devrait pas recompiler le projet au moment du déploiement. Il doit consommer un artefact déjà construit, versionné et stocké dans un registre stable. Dans notre TP, ce rôle est joué par Verdaccio.
Verdaccio est un registre npm privé léger. Il stocke des packages
publiés, ici accessibles sur http://localhost:4873
depuis le DevContainer et les runners act.
Une fois une version publiée, elle est considérée comme immuable. Revenir en arrière ne consiste donc pas à reconstruire le projet, mais à réinstaller une version précédente déjà connue du registre.
npm pack
npm publish --registry http://localhost:4873
npm install tp-cd-api@0.1.0 --registry http://localhost:4873
Le rôle du registre est très simple dans la chaîne : il sert d'étagère intermédiaire entre le job de build et le job de déploiement.
Chargement du flowchart…
Pourquoi le serveur cible ne doit-il pas refaire un npm install depuis le code source du dépôt ?
Parce que vous risquez de reconstruire quelque chose de légèrement différent de ce qui a été testé : dépendances résolues autrement, scripts exécutés différemment, environnement non identique. L'artefact à déployer doit être exactement celui que la chaîne a validé.
Déploiement via SSH
Le but du cours n'est pas de faire du Kubernetes miniature. SSH suffit largement pour comprendre le mécanisme de base : se connecter à un serveur, installer la bonne version de l'artefact, redémarrer le processus, puis vérifier que l'application répond.
La pipeline se connecte au serveur cible avec une clé privée. Dans
le TP, cette clé est générée automatiquement puis exposée à
act via le fichier .secrets.
Une fois connectée, elle installe le package depuis Verdaccio,
redémarre l'application avec pm2, puis lance un
smoke test.
Un smoke test n'est pas une batterie de régression complète. C'est un test minimal exécuté immédiatement après déploiement pour savoir si le service a démarré et répond encore.
Repère important dans le TP :
côté serveur SSH, l'application écoute sur localhost:3000.
Depuis le DevContainer ou le runner, vous testez au contraire
http://localhost:3001/health, qui passe par un relais.
La séquence opérationnelle tient en quelques messages : connexion, installation, redémarrage, vérification interne, puis vérification externe.
Chargement du diagramme de séquence…
Quelle différence devez-vous retenir entre un test E2E de la pipeline et un smoke test de déploiement ?
Les tests E2E tournent avant la publication et avant le déploiement, dans l'environnement CI. Le smoke test tourne après déploiement, sur le vrai serveur cible, pour vérifier que le service vit toujours dans son environnement réel.
Si le smoke test échoue juste après le déploiement, que doit faire la chaîne idéale ?
Revenir à une version précédente connue et stable. C'est le sens du bonus de rollback : ne jamais laisser le serveur dans un état incertain après une publication ratée.
Dépôt CD pédagogique — temps 1 : prise en main guidée
Dépôt support : GVI2026/tp-cd-api
Le dépôt reprend la base NestJS du TP CI, ajoute un endpoint
/health, des tests E2E déjà en place, Verdaccio, un
serveur SSH simulé et une CI déjà fonctionnelle. Votre travail ne
consiste pas à réparer la base, mais à brancher la partie livraison.
-
Ouvrir le dépôt dans VS Code puis accepter le DevContainer si la
proposition apparaît. Attendre la fin du
postCreateCommand. -
Vérifier que Verdaccio répond :
curl http://localhost:4873/-/ping -
Vérifier l'accès au serveur cible :
ssh -p 2222 deployer@localhost "echo ok" -
Vérifier que la CI de base est déjà verte :
act -j security -
Repérer trois fichiers de référence avant de coder :
.github/workflows/ci.yml,docker-compose.ymletEXERCICE.md. -
Si Verdaccio ou le SSH-target cessent de répondre après une veille
ou un redémarrage du conteneur, relancer les relais réseau :
bash bin/check-relays.sh
Avant de commencer à écrire les jobs CD, qu'est-ce que vous devez avoir validé ?
Que la CI existante passe déjà, que Verdaccio répond, que le serveur SSH est joignable et que vous savez quels fichiers font foi pendant le TP. Sinon, vous risquez de déboguer l'infrastructure au lieu de déboguer vos jobs.
Dépôt CD pédagogique — temps 2 : exercices séquentiels
La pipeline CI du dépôt est déjà prête :
install → format-lint → tests → tests-e2e → build → security.
Vous n'ajoutez que la fin de chaîne : release, publication de
l'artefact, puis déploiement.
Point de méthode :
pendant le TP, le dépôt emploie commit-and-tag-version
pour simplifier la simulation locale. Ne confondez pas cet outil
de TP avec la comparaison conceptuelle faite plus haut entre
Release Please et Semantic Release.
Exercice 1 — job release
Objectif : automatiser la montée de version à partir des Conventional Commits, sans rajouter de nouvelle dette dans la CI.
-
Vérifier que le script
releaseexiste déjà danspackage.json. -
Ajouter le job
releaseaprèssecuritydans.github/workflows/ci.yml. -
Mettre
fetch-depth: 0sur le checkout, configurer l'identité Git du runner, puis lancer :npx commit-and-tag-version -
Vérifier la condition de branche : le job ne doit s'exécuter
que sur
main. -
Tester le job avec :
act -j release
Attention : avec act, le commit et le tag créés par
ce job vivent dans le runner éphémère. Ils ne réapparaissent pas
magiquement dans le dépôt local du DevContainer.
Exercice 2 — job publish
Objectif : publier exactement l'artefact déjà construit par le
job build, sans recompiler dans ce job.
-
Ajouter un job
publishqui dépend dereleaseet ne s'exécute que surmain. -
Restaurer
node_moduleset télécharger l'artefactbuild-distproduit plus tôt dans la chaîne. -
Configurer l'authentification npm minimale pour Verdaccio :
npm set //localhost:4873/:_authToken "dummy-token" -
Publier le package :
npm publish --registry http://localhost:4873 -
Tester avec
act -j publish, puis vérifier soit dans l'interface Verdaccio, soit avec :npm view tp-cd-api --registry http://localhost:4873
Si vous republiez exactement la même version, Verdaccio refusera l'opération. C'est normal : un registre npm traite les versions comme immuables.
Exercice 3 — job deploy
Objectif : installer la bonne version sur le serveur cible, redémarrer l'application et prouver que le déploiement a réussi.
-
Ajouter un job
deployqui dépend depublishet reste limité àmain. -
Utiliser l'action
appleboy/ssh-action@v0.1.7avechost: localhost,port: 2222,username: deployeret${{ secrets.SSH_PRIVATE_KEY }}. -
Dans le script distant, créer
~/app, installer le package avecnpm install --prefix ~/app tp-cd-api --ignore-scripts, puis relancer le processus viapm2. -
Vérifier d'abord côté serveur :
curl -f http://localhost:3000/health -
Ajouter ensuite un smoke test externe côté runner :
curl -f http://localhost:3001/health -
Vérifier enfin l'état du serveur avec :
ssh -p 2222 deployer@localhost "pm2 list"
Adresse utile à retenir : depuis le runner ou le DevContainer, Verdaccio s'appelle localhost:4873. Depuis le serveur cible, il s'appelle verdaccio:4873 via le réseau Docker interne.
Commande réflexe si le réseau de test décroche : bash bin/check-relays.sh.
Bonus — rollback automatique pour les plus rapides
L'objectif est de redéployer automatiquement la version précédente si le smoke test échoue. Dans le dépôt réel, l'idée recommandée consiste à mémoriser la version actuellement servie avant d'écraser le déploiement, puis à réinstaller cette version si le test final échoue.
Le bonus vérifie surtout que vous savez écrire une logique de résilience simple avec des conditions GitHub Actions et un script SSH complémentaire.
Correction collective
En correction, on relit la chaîne finale comme un DAG et non comme une liste de recettes. Ce qui compte n'est pas seulement « ça marche », mais « pourquoi cet ordre est-il logique et pourquoi cette chaîne arrête-t-elle au bon endroit ? ».
install → format-lint → tests → tests-e2e → build → security
↓
release → publish → deploy
- Relire les dépendances
needs:entre les jobs. - Vérifier les conditions
if:qui limitent release, publish et deploy àmain. - Identifier ce qui se passe si
publishéchoue :deployne part pas. - Relier chaque étape à son rôle : versionner, stocker, installer, vérifier.
Si le job publish échoue à mi-parcours, pourquoi est-ce une bonne nouvelle que deploy ne s'exécute pas ?
Parce qu'un déploiement sans artefact publié ou publié de façon incomplète ferait perdre la traçabilité de la chaîne. Le rôle du DAG est précisément d'empêcher la suite de s'appuyer sur un état incohérent.
Synthèse finale
En quatre cours, le module a suivi un fil cohérent : partir du versioning local, structurer le travail d'équipe avec des flows, fiabiliser l'intégration avec une CI, puis terminer par la livraison automatisée d'un artefact vers un environnement déployé.
Le message principal à emporter est simple : une chaîne CI/CD n'est pas seulement un ensemble d'outils. C'est un mécanisme qui transforme un changement de code en version identifiable, testée, publiable et déployable.
Conventional Commit
→ CI (format-lint, tests, E2E, build, security)
→ release
→ Verdaccio
→ SSH
→ smoke test
Les feature flags sont le complément stratégique qui permet de rendre un mode Trunk-Based crédible sans exposer trop tôt une fonctionnalité incomplète.
Ce qu'il manque encore à une chaîne de production réelle : plus d'observabilité, des alertes, des stratégies de rollback encore plus robustes et des environnements multi-étapes mieux instrumentés.
La prochaine séance revient sur l'ensemble du module pour une révision transversale et le QCM final.