Anatomie d'une pipeline CI/CD
Les étapes, les agents, les artefacts — et ce qui circule entre eux.
Une développeuse pousse son code sur Git. Quelques minutes plus tard, elle reçoit une notification : les tests passent, l'image Docker est construite, le déploiement en pré-production est terminé. Elle n'a rien fait manuellement — c'est la pipeline qui a tout orchestré. Mais qu'est-ce qui distingue cette pipeline d'un simple script shell, et pourquoi cette abstraction est-elle devenue incontournable ?
En bref
Une pipeline CI/CD est un système d'exécution gouverné qui transforme du code source en logiciel déployable, de façon reproductible, traçable et observable. Ce n'est pas un script : c'est une infrastructure.
Une pipeline n'est pas un script
Vous avez peut-être un script Bash qui compile et déploie votre application. Ce n'est pas une pipeline. La différence ne tient pas à ce que fait le code, mais à comment il s'exécute et à ce qu'on peut en observer.
| Script | Pipeline |
|---|---|
| Tourne sur votre machine ou un serveur fixe | S'exécute dans un environnement contrôlé et isolé |
| Lit les variables d'environnement locales | Déclare explicitement ses besoins (secrets, artefacts) |
| Renvoie « ça marche » ou « ça plante » | Expose chaque étape, son statut, sa durée |
| Aucune trace une fois terminé | Conserve logs, artefacts, historique complet |
Lancé manuellement ou par cron | Déclenché par des événements Git (push, PR, tag) |
Ce qui sépare un script d'une pipeline : l'environnement, la déclaration, la trace.
Un script peut être une étape d'une pipeline. Mais la pipeline apporte l'orchestration, la gouvernance et la visibilité que le script seul ne fournit pas.
La structure d'exécution
Pour comprendre une pipeline, il faut installer quelques concepts. Prenons-les un par un, du plus petit au plus grand.
Les jobs : l'unité atomique
Un job est la plus petite unité d'exécution. Voyez-le comme un conteneur jetable : il démarre, fait son travail, puis disparaît. Chaque job s'exécute dans un environnement isolé et produit un résultat binaire — succès ou échec. Son cycle de vie ne varie pas : préparation de l'environnement (image Docker, dépendances système), récupération du code source, exécution des commandes, dépôt des artefacts si le job a réussi, nettoyage.
Trois propriétés le définissent :
- Isolation — chaque job démarre dans un environnement vierge. Ce qui s'est passé dans un job précédent ne pollue pas celui-ci.
- Atomicité — un job réussit (code de retour 0) ou échoue (code de retour différent de 0). Pas d'état intermédiaire.
- Parallélisation — plusieurs jobs peuvent tourner en même temps s'ils ne dépendent pas les uns des autres.
| Job | Rôle | Dépend de |
|---|---|---|
lint | vérifie le style du code | rien |
unit-tests | exécute les tests unitaires | rien |
build-docker | construit une image Docker | lint, unit-tests |
deploy-staging | déploie sur l'environnement de test | build-docker |
Quatre jobs indépendants — mais pas sans relation entre eux.
Si les tests plantent, cela n'empêche pas le linter de tourner : les deux sont indépendants et peuvent s'exécuter en parallèle. En revanche, si les tests plantent, on ne construira pas l'image Docker : il y a là une relation de dépendance.
Les stages : organiser les jobs par phase
Un stage (ou phase) regroupe des jobs qui poursuivent le même objectif. Les stages s'exécutent dans l'ordre, mais les jobs d'un même stage peuvent tourner en parallèle.
Les stages s'enchaînent de gauche à droite à l'intérieur d'un stage, les jobs sont parallèles.
Découper en stages sert trois objectifs : échouer vite — si
lint échoue, inutile de lancer build la lisibilité —
le flux se visualise clairement dans l'interface et l'optimisation —
parallélisation maximale au sein d'un stage.
Le graphe d'exécution
Une pipeline complexe forme un graphe acyclique dirigé (DAG). Ce sont les dépendances déclarées entre jobs qui définissent l'ordre d'exécution, et pas seulement la succession des stages.
Graphe acyclique dirigé
Un graphe orienté dans lequel aucun chemin ne revient à son point de départ. Appliqué à une pipeline : un job ne peut pas dépendre, directement ou indirectement, de lui-même — sans quoi la pipeline ne démarrerait jamais.
Comprendre ce graphe, c'est pouvoir optimiser les temps d'exécution : deux jobs sans dépendance mutuelle peuvent toujours tourner en parallèle, même s'ils sont écrits l'un après l'autre.
Runners et agents
Qui exécute le code ?
Un runner (GitHub Actions, GitLab CI) ou agent (Jenkins, Azure DevOps) est la machine qui exécute vos jobs. Le flux est toujours le même : la plateforme CI/CD assigne un job à un runner disponible le runner récupère le job — code et configuration le job s'exécute le runner renvoie les logs et le statut à la plateforme.
Types de runners
| Type | Avantages | Inconvénients |
|---|---|---|
| Hébergé (GitHub, GitLab SaaS) | prêt à l'emploi, maintenance incluse | ressources limitées, pas d'accès au réseau interne |
| Auto-hébergé | contrôle total, accès aux ressources internes | maintenance et sécurité à votre charge |
| Éphémère | isolation maximale, pas de pollution entre jobs | temps de démarrage plus long |
Trois modèles de runner — le choix engage la sécurité, la performance et le coût.
Ce que le type de runner change concrètement : la sécurité — un runner partagé, a fortiori public, peut exposer vos secrets s'il est mal configuré la performance — accès à des ressources spécifiques, bases de données internes ou GPU le coût — les minutes gratuites des runners hébergés s'épuisent vite dès qu'on construit souvent.
Isolation et sécurité des runners
Un job a accès à tout ce que le runner peut voir : le système de fichiers du runner, les variables d'environnement, les secrets injectés et le réseau joignable depuis la machine.
Un runner partagé est une surface d'attaque
Si plusieurs projets partagent le même runner, un job malveillant peut accéder aux données d'un autre projet. C'est pourquoi les runners éphémères, détruits après chaque job, sont la règle dès que le contexte est sensible.
Cache et artefacts
La confusion entre cache et artefact est fréquente : les deux stockent des données, mais leur usage est fondamentalement différent.
Le cache : accélérer les builds
Le cache conserve des fichiers entre deux exécutions pour éviter de
les recalculer — dépendances npm, modules Python, dépôt local Maven. À la
première exécution, npm install télécharge 300 paquets en trois minutes,
puis sauvegarde le cache à la suivante, il le retrouve et rend la main en dix
secondes.
Un cache est identifié par une clé calculée sur un hachage (fichier de verrouillage, nom de branche). Il est optionnel : le job doit fonctionner même sans lui. Il est partagé entre jobs et entre pipelines, et il peut devenir obsolète — c'est normal.
Les artefacts : transmettre des résultats
Un artefact est le produit d'un job, transmis aux jobs suivants ou
téléchargé par un humain. C'est le livrable de l'étape. Pourquoi est-ce
important ? Parce que les jobs sont isolés : si le job build produit un
fichier, le job deploy ne le verra pas, sauf si ce fichier est
déclaré comme artefact.
Les jobs étant isolés, seul un artefact déclaré franchit la frontière — le cache, lui, reste une optimisation locale.
Un artefact est attaché à un job précis, doté d'une durée de rétention configurable — 30 à 90 jours par défaut selon les plateformes —, téléchargeable après la fin de la pipeline, et obligatoire pour les jobs qui en dépendent.
| Aspect | Cache | Artefact |
|---|---|---|
| But | accélérer | transmettre |
| Obligatoire | non | oui, s'il y a une dépendance |
| Persistance | entre exécutions | durée de rétention limitée |
| Exemple | node_modules/ | dist/, report.xml |
| S'il est absent | le job est plus lent | le job échoue |
Le cache est une optimisation, l'artefact est un contrat.
Environnements de déploiement
Un environnement représente une cible de déploiement : développement, pré-production, production. Les pipelines modernes permettent de définir des règles propres à chaque environnement.
Un même artefact, trois cibles — des règles et des secrets qui se durcissent à chaque étage.
Règles de protection
La production mérite des garde-fous : une approbation humaine avant le
déploiement un délai de quelques minutes entre pré-production et
production, pour pouvoir annuler des plages horaires — pas de
déploiement le vendredi après-midi des branches autorisées — seule
main peut déployer en production.
Secrets par environnement
Chaque environnement possède ses propres identifiants : la base de données de pré-production n'est pas celle de production, les clés d'API de test ne sont pas celles de production, et les jetons de développement portent des permissions réduites.
À retenir
La séparation des secrets réduit l'impact d'une fuite : un secret de pré-production compromis ne donne pas accès à la production.
Logs et observabilité
Ce que les logs doivent contenir
Un job correctement journalisé permet de comprendre ce qui s'est passé sans relancer la pipeline :
- les commandes exécutées — exactement ce qui a été lancé
- la sortie standard et la sortie d'erreur, complètes
- des horodatages — début et fin de chaque étape
- les variables d'environnement utiles au contexte d'exécution, secrets exclus
- les versions des outils, dépendances et images employés.
Masquage des secrets
Les plateformes CI/CD masquent automatiquement les secrets déclarés dans les logs. Restent les fuites indirectes, qu'aucun masquage ne rattrape.
{Deux façons de faire fuiter un jeton, et la parade.}
# À ÉVITER : le secret peut fuiter par un simple echo
echo "Token: MY_TOKEN"
# À ÉVITER : une erreur curl peut réafficher l'en-tête complet
curl -H "Authorization: TOKEN" https://api.example.com
# CORRECT : passer par un fichier temporaire, jamais par la ligne de commande
echo "TOKEN" > /tmp/token.txt
curl -H "Authorization: (cat /tmp/token.txt)" https://api.example.comLe masquage n'est pas une protection
Il n'agit que sur les valeurs que la plateforme connaît, et seulement dans les logs qu'elle collecte. Un secret transmis en argument de commande reste visible dans la table des processus du runner.
Métriques essentielles
Une pipeline en bonne santé expose ses métriques : la durée moyenne, temps écoulé entre le déclenchement et la fin le taux de succès, part de pipelines au vert sur sept jours les tests instables (flaky), ceux qui échouent de façon aléatoire le temps d'attente en file, délai avant qu'un runner se libère.
Trois alertes à mettre en place
Une pipeline qui dépasse un seuil de durée (régression de performance) un taux de succès qui chute sous un plancher défini (problème systémique) un job qui échoue plus de n fois (test instable à corriger).
Les invariants d'une pipeline
Au-delà des concepts techniques, une pipeline repose sur trois garanties. Si l'une manque, vous avez un script qui s'exécute à distance — pas une pipeline.
Reproductibilité : même entrée, même sortie
Règle d'or
Le même commit doit produire le même artefact, peu importe quand et où la pipeline s'exécute.
Si votre pipeline donne des résultats différents à chaque exécution, elle perd toute valeur : on ne peut plus faire confiance à ce qu'elle produit. Quatre causes reviennent sans cesse :
- dépendances non épinglées —
npm installsanspackage-lock.jsonpeut installer des versions différentes d'une fois sur l'autre - tests qui dépendent de l'heure — un test qui vérifie « il est entre 9 h et 18 h » échouera la nuit
- appels à des API externes sans bouchon — si l'API change ou devient indisponible, les tests plantent aléatoirement
- cache non déterministe — si le cache contient des fichiers d'une exécution précédente, le résultat peut varier.
La parade tient en trois gestes : épingler toutes les dépendances — un
package-lock.json, un Pipfile.lock ou un go.sum versionné
avec le code utiliser des images Docker à tag fixe, jamais latest
isoler les tests de l'heure locale comme des données externes.
Traçabilité : remonter de l'artefact au commit
Quand un bug apparaît en production, vous devez pouvoir répondre à quatre questions : quel commit a introduit ce changement ? Quelle pipeline a construit cet artefact ? Quels tests ont été exécutés ? Qui a déclenché le déploiement ?
Sans traçabilité, le débogage devient de l'archéologie : on fouille les logs et les messages de commit en espérant tomber sur le bon élément. Trois pratiques la garantissent : chaque artefact porte le SHA du commit qui l'a produit, chaque déploiement conserve un lien vers la pipeline d'origine, et chaque job expose ses logs complets — pas seulement un verdict.
Observabilité : savoir ce qui se passe
Une pipeline doit exposer son état de santé en temps réel : pas seulement « ça marche » ou « ça plante », mais des métriques actionnables. Pourquoi est-ce critique ? Parce qu'une pipeline qui ralentit progressivement finit par bloquer toute l'équipe. Si vous ne détectez pas qu'un job de test passe de 2 à 15 minutes, vous le découvrirez trop tard — quand plus personne ne voudra pousser de code.
Ce que la pipeline révèle
Une pipeline CI/CD n'est jamais neutre. Elle cristallise les décisions de l'équipe, parfois à son insu. Voici les questions auxquelles elle répond implicitement.
- Quels tests sont obligatoires ? Si un test peut être ignoré, il ne l'est pas. Si la pipeline bloque sans lui, il l'est.
- Qui peut déployer en production ? Si chacun peut fusionner sur
mainet que cela déclenche un déploiement automatique, alors tout le monde déploie. Si une approbation est requise, seuls certains rôles le peuvent. - Combien de temps peut-on attendre un retour ? Une pipeline de 45 minutes décourage les petits commits fréquents une pipeline de 5 minutes encourage l'itération rapide.
- Quelle confiance accorde-t-on aux dépendances externes ? Si la pipeline bloque dès qu'une dépendance ne répond pas, vous avez un point de défaillance unique. Si elle continue sur un cache ou une version épinglée, vous avez anticipé la panne.
Loi de Conway
Une équipe cloisonnée — dev d'un côté, ops de l'autre — produira une pipeline fragmentée : déploiement manuel après la construction. Une équipe sans ownership clair produira une pipeline sans maintenance : personne ne nettoie les jobs obsolètes.
À retenir de cette séance
Jobs, stages, runners, cache, artefacts, environnements : ce vocabulaire décrit une structure d'exécution, pas une suite de commandes. Les trois invariants — reproductibilité, traçabilité, observabilité — sont ce qui rend cette structure digne de confiance. Une pipeline qui les perd redevient un script, quelle que soit la plateforme qui l'héberge.
Réponse unique
Quelle est l'unité atomique d'exécution d'une pipeline ?
Indice · Qu'est-ce qui réussit ou échoue d'un seul tenant ?
[ METTRE EN PRATIQUE ]
Cartographier une pipeline existante
3 étapes · 30 min · 120 XP
[ CETTE LEÇON DANS LES PARCOURS ]
- Ingénieur DevOpsétape 15 / 23suivant — CI, Delivery, Deployment →