đŠ GitLab CI : comprendre le pipeline .gitlab-ci.yml, pour de bon

đ Introduction
La force de GitLab CI tient en une idĂ©e : tout le pipeline se dĂ©crit dans un seul fichier, .gitlab-ci.yml, versionnĂ© Ă la racine du dĂ©pĂŽt. Pas de configuration Ă©parpillĂ©e dans une interface web, pas dâoutil externe Ă brancher : GitLab dĂ©tecte ce fichier Ă chaque push et exĂ©cute ce quâil contient. La CI/CD vit avec le code, dans le mĂȘme commit.
Si vous avez dĂ©jĂ touchĂ© Ă une plateforme dâintĂ©gration continue, GitHub Actions par exemple, les concepts vous parleront, mĂȘme si le vocabulaire diffĂšre. Cet article pose les fondamentaux de GitLab CI : le modĂšle stages/jobs/runners, un premier pipeline complet, la distinction cache/artifacts qui pose souvent problĂšme, et le contrĂŽle du dĂ©clenchement avec rules. Les exemples sont volontairement agnostiques : ce qui compte, câest la mĂ©canique.
đ§± Le modĂšle : stages, jobs, runners
Trois notions structurent tout GitLab CI :
- Un job est lâunitĂ© de travail : un nom, une liste de commandes (
script), et lâenvironnement dans lequel elles tournent. - Un stage regroupe des jobs. Les stages sâexĂ©cutent en sĂ©quence (lâun aprĂšs lâautre), mais tous les jobs dâun mĂȘme stage tournent en parallĂšle. Câest le levier principal de rapiditĂ© : on parallĂ©lise ce qui peut lâĂȘtre.
- Un runner est lâagent qui exĂ©cute rĂ©ellement les jobs. GitLab.com fournit des runners partagĂ©s prĂȘts Ă lâemploi ; on peut aussi hĂ©berger les siens. Chaque runner utilise un executor : le plus courant est Docker, qui lance chaque job dans un conteneur frais Ă partir de lâimage dĂ©clarĂ©e.
Lâordre mental est donc : le pipeline enchaĂźne des stages, chaque stage lance ses jobs en parallĂšle, et chaque job sâexĂ©cute dans un conteneur sur un runner. Si aucun stage nâest dĂ©clarĂ©, GitLab en propose trois par dĂ©faut : build, test, deploy. Et un job sans stage explicite atterrit automatiquement dans test.
Au-delĂ des stages que vous dĂ©clarez, GitLab fournit deux stages implicites toujours disponibles, sans avoir Ă les lister : .pre et .post. .pre sâexĂ©cute avant tous les autres stages, .post aprĂšs tous les autres, et ce quelle que soit leur position dans le fichier. .pre est le stage de setup idĂ©al : prĂ©paration dâenvironnement, vĂ©rification de prĂ©requis, gĂ©nĂ©ration de variables Ă propager au reste du pipeline. .post sert plutĂŽt au nettoyage ou Ă des notifications de fin :
verifier-prerequis:
stage: .pre
script:
- ./scripts/check-env.sh
notifier:
stage: .post
when: always
script:
- ./scripts/notify.shđ Un premier .gitlab-ci.yml
Voici un pipeline complet et lisible. Il construit une application, la teste, puis la déploie, chaque job dans un conteneur Node :
stages:
- build
- test
- deploy
default:
image: node:22-alpine
build:
stage: build
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
test:
stage: test
script:
- npm test
deploy:
stage: deploy
script:
- ./scripts/deploy.sh
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'Tout y est : le bloc default fixe lâimage de tous les jobs (image: peut aussi ĂȘtre dĂ©fini par job), chaque job dĂ©clare son stage et son script, le job build publie son rĂ©sultat en artifacts, et deploy ne se dĂ©clenche que sur la branche par dĂ©faut grĂące Ă rules. La variable $CI_DEFAULT_BRANCH fait partie des nombreuses variables prĂ©dĂ©finies fournies par GitLab (comme $CI_COMMIT_SHA ou $CI_REGISTRY_IMAGE).
đ§° Structurer un job : before_script, after_script, tags
Au-delĂ de script, deux mots-clĂ©s aident Ă factoriser les commandes rĂ©pĂ©tĂ©es. before_script sâexĂ©cute avant le script du job (prĂ©paration : login, dĂ©pendances systĂšmeâŠ), after_script aprĂšs, et mĂȘme si le job Ă©choue (nettoyage, remontĂ©e de logs). PlacĂ©s dans le bloc default, ils sâappliquent Ă tous les jobs :
default:
image: node:22-alpine
before_script:
- node --version
- npm ciLe mot-clĂ© tags, lui, choisit quel runner exĂ©cute le job. Chaque runner dĂ©clare des Ă©tiquettes, et un job ne part que sur un runner qui possĂšde toutes celles quâil rĂ©clame. Indispensable pour cibler un runner self-hosted, une architecture prĂ©cise ou un environnement isolĂ© :
build-arm:
tags:
- arm64
- docker
script:
- ./build.shđ Cache ou artifacts : quelle diffĂ©rence ?
Câest la confusion la plus frĂ©quente, et les deux ne servent pas du tout Ă la mĂȘme chose.
Le cache sert Ă accĂ©lĂ©rer : il conserve des fichiers coĂ»teux Ă reconstituer, typiquement les dĂ©pendances tĂ©lĂ©chargĂ©es, dâun pipeline Ă lâautre. Câest un mĂ©canisme best-effort : le cache peut ĂȘtre absent (nouveau runner, expiration), et le job doit rester correct sans lui.
test:
stage: test
cache:
key:
files:
- package-lock.json
paths:
- .npm/
script:
- npm ci --cache .npm --prefer-offline
- npm testLes artifacts, eux, servent Ă transmettre : un job produit des fichiers (rĂ©sultat de build, rapports de test) que GitLab stocke, rend tĂ©lĂ©chargeables, et fournit aux jobs suivants qui en dĂ©pendent. Contrairement au cache, câest fiable et prĂ©vu pour circuler entre jobs et entre stages.
La rĂšgle mnĂ©motechnique : cache pour les dĂ©pendances, artifacts pour les rĂ©sultats. Un node_modules reconstructible va au cache ; un dist/ quâon veut dĂ©ployer va aux artifacts.
đŻ ContrĂŽler quand un job sâexĂ©cute : rules
Rares sont les jobs qui doivent tourner Ă chaque fois, sur toutes les branches. rules est lâoutil moderne pour dĂ©cider : il remplace lâancienne syntaxe only/except, encore fonctionnelle mais Ă Ă©viter pour un nouveau pipeline.
rules Ă©value une liste de conditions, dans lâordre, et sâarrĂȘte Ă la premiĂšre qui correspond :
deploy:
stage: deploy
script:
- ./scripts/deploy.sh
rules:
# déploie automatiquement sur la branche par défaut
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
# sur les autres branches, propose un déclenchement manuel
- if: '$CI_COMMIT_BRANCH'
when: manualOn combine des conditions if (sur les variables prĂ©dĂ©finies), des filtres changes (le job ne tourne que si certains fichiers ont changĂ©), des vĂ©rifications exists, et des clauses when (on_success, manual, neverâŠ). Câest expressif et centralisĂ©, lĂ oĂč only/except devenait vite illisible.
đ§© Aller plus loin : needs, variables, include
Trois mots-clĂ©s font passer un pipeline du niveau « ça marche » à « câest propre » :
needscasse la barriĂšre des stages pour crĂ©er un graphe de dĂ©pendances (DAG). Un job avecneeds: ['build']dĂ©marre dĂšs quebuildest fini, sans attendre la fin de tout le stage. Les pipelines deviennent nettement plus rapides.variablesdĂ©finit des valeurs rĂ©utilisables, globalement ou par job, pour ne pas rĂ©pĂ©ter une version, un chemin ou un nom dâimage.includeimporte de la configuration depuis lâextĂ©rieur, pour factoriser des pipelines entre projets. Il en existe plusieurs formes :include:local(un autre fichier du mĂȘme dĂ©pĂŽt),include:project(un fichier dâun autre projet GitLab),include:remote(une URL),include:template(un modĂšle fourni par GitLab) etinclude:component(un CI/CD component du catalogue).
include:
- local: '/ci/tests.yml'
- project: 'mon-groupe/ci-templates'
ref: main
file: '/deploy.yml'
- component: '$CI_SERVER_FQDN/mon-groupe/build@1.0'Les CI/CD components sont la brique moderne : des morceaux de pipeline rĂ©utilisables, versionnĂ©s et paramĂ©trables, publiĂ©s dans un catalogue et importĂ©s via include:component. Câest la direction que pousse GitLab pour mutualiser la CI proprement.
Ces trois leviers évitent la duplication, le péché mignon des fichiers CI qui grossissent.
â ïž Quelques prĂ©cautions
- Validez avant de pousser. GitLab fournit un outil CI Lint (dans le menu CI/CD du projet) qui vérifie la syntaxe du
.gitlab-ci.ymlsans lancer de pipeline. Un aller-retour de moins pour débusquer une indentation fautive. - Ne stockez jamais de secret en clair dans
.gitlab-ci.yml. Utilisez les variables CI/CD masquĂ©es et protĂ©gĂ©es dĂ©finies dans les rĂ©glages du projet, jamais une valeur codĂ©e en dur dans un fichier versionnĂ©. - Un cache nâest pas garanti. Ăcrivez vos jobs pour quâils fonctionnent mĂȘme cache vide. Si un fichier est indispensable au job suivant, câest un artifact, pas un cache.
- Ăpinglez vos images.
node:22-alpinereste prévisible ;node:latestchange sous vos pieds et rend les pipelines non reproductibles. - Surveillez la durée des artifacts. Ils consomment du stockage. Fixez une
expire_inraisonnable pour ceux qui nâont pas vocation Ă durer.
đ Conclusion
GitLab CI tient sur une poignĂ©e de concepts : des jobs regroupĂ©s en stages sĂ©quentiels, exĂ©cutĂ©s en parallĂšle par des runners dans des conteneurs. Autour de ce cĆur, quatre outils suffisent Ă couvrir lâessentiel : artifacts pour transmettre les rĂ©sultats, cache pour accĂ©lĂ©rer, rules pour dĂ©cider quand un job tourne, et needs/include pour garder le tout rapide et sans duplication.
Lâatout majeur reste la simplicitĂ© du modĂšle : un fichier, versionnĂ© avec le code, qui dĂ©crit tout le pipeline. Une fois le mental model en place, Ă©crire un .gitlab-ci.yml devient une formalitĂ©. Et comme chaque job tourne dans une image Docker, une bonne maĂźtrise des fondamentaux de Docker rend lâexercice encore plus naturel.
đ Liens utiles
/faq
Questions fréquentes
OĂč se configure un pipeline GitLab CI ?
+
Dans un fichier nommé « .gitlab-ci.yml » placé à la racine du dépÎt. GitLab le détecte automatiquement à chaque push et exécute le pipeline qu'il décrit. Tout (stages, jobs, cache, conditions de déclenchement) tient dans ce fichier versionné avec le code.
Quelle est la différence entre cache et artifacts dans GitLab CI ?
+
Le cache sert à réutiliser des dépendances (paquets téléchargés) entre pipelines pour accélérer les jobs, sans garantie de disponibilité. Les artifacts servent à transmettre des sorties d'un job à un autre (résultat de build, rapports) : ils sont stockés dans GitLab, téléchargeables et garantis pour les jobs qui en dépendent.
Qu'est-ce qu'un runner GitLab ?
+
Un runner est l'agent qui exécute concrÚtement les jobs. GitLab.com fournit des runners partagés clé en main ; on peut aussi héberger ses propres runners. Chaque runner utilise un « executor » (le plus courant est Docker, qui lance chaque job dans un conteneur à partir de l'image déclarée).
Faut-il utiliser rules ou only/except ?
+
rules est l'approche moderne et recommandée pour contrÎler quand un job s'exécute : elle combine conditions if, filtres de changements et clauses when dans une seule liste. only/except est l'ancienne syntaxe, encore fonctionnelle mais à éviter pour les nouveaux pipelines.