
Vous connaissez maintenant les concepts fondamentaux : pipeline, stages, jobs, runners. Il est temps de passer à la pratique ! Le fichier .gitlab-ci.yml décrit ce que GitLab doit automatiser. Ce guide vous apprend à le structurer méthodiquement : comment découper votre workflow en stages, définir des jobs, et écrire les scripts qui seront exécutés.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »À la fin de ce module, vous saurez :
- Structurer un fichier
.gitlab-ci.yml: la hiérarchie stages → jobs → script - Définir des stages : organiser les grandes étapes de votre pipeline
- Créer des jobs : configurer les tâches avec les bonnes propriétés
- Écrire des scripts : les commandes exécutées par chaque job
- Spécifier une image Docker : choisir l'environnement d'exécution
- Utiliser les variables : configurer vos jobs dynamiquement
- Valider votre fichier : éviter les erreurs de syntaxe
Prérequis
Section intitulée « Prérequis »Avant de continuer, assurez-vous de maîtriser :
La logique de construction
Section intitulée « La logique de construction »Avant d'écrire du YAML, posez-vous ces questions :
- Quelles sont les grandes étapes de mon workflow ? → Ce seront vos stages
- Quelles tâches dois-je accomplir à chaque étape ? → Ce seront vos jobs
- Quelles commandes chaque tâche doit-elle exécuter ? → Ce sera le script
Exemple de raisonnement pour un projet web :
| Question | Réponse | Élément YAML |
|---|---|---|
| Grandes étapes ? | Compiler, tester, déployer | stages: [build, test, deploy] |
| Tâches du test ? | Tests unitaires, linting | 2 jobs dans le stage test |
| Commandes du lint ? | npm run lint | script: [npm run lint] |
Structure minimale du fichier
Section intitulée « Structure minimale du fichier »Un pipeline GitLab tient en très peu de lignes. Le seul élément réellement indispensable est un job doté d'un script : le bloc stages est facultatif, GitLab en fournit un par défaut. Déclarez-le quand même, car c'est lui qui rend l'ordre d'exécution lisible pour la personne qui reprendra le fichier après vous.
Un fichier .gitlab-ci.yml valide contient au minimum :
# 1. Déclarer les stages (optionnel mais recommandé)stages: - build - test
# 2. Définir au moins un job avec un scriptmon-job: stage: build script: - echo "Hello GitLab CI!"Le fichier doit être :
- Nommé exactement
.gitlab-ci.yml(avec le point) - Placé à la racine du repository
- Encodé en UTF-8
Niveau 1 : Définir les stages
Section intitulée « Niveau 1 : Définir les stages »Les stages représentent les grandes étapes de votre pipeline. Ils s'exécutent dans l'ordre déclaré.
stages: - build # Étape 1 : compiler le code - test # Étape 2 : exécuter les tests - deploy # Étape 3 : déployer l'applicationRègles des stages :
| Règle | Explication |
|---|---|
| Ordre séquentiel | build se termine avant que test commence |
| Échec bloquant | Si build échoue, test et deploy ne s'exécutent pas |
| Stages par défaut | Sans déclaration, GitLab utilise : .pre, build, test, deploy, .post |
Quand créer un nouveau stage ?
Section intitulée « Quand créer un nouveau stage ? »Créez un stage quand vous avez une dépendance logique :
- Oui :
testdépend debuild, donc 2 stages séparés - Oui :
deploy-stagingavantdeploy-prod, donc 2 stages séparés - Non : tests unitaires et tests d'intégration, même stage car aucune dépendance entre eux
Niveau 2 : Définir les jobs
Section intitulée « Niveau 2 : Définir les jobs »Un job est une tâche qui appartient à un stage. C'est ici que vous décrivez ce qui doit être fait.
# Syntaxe d'un jobnom-du-job: # Nom libre, visible dans l'interface stage: test # À quel stage appartient ce job script: # Commandes à exécuter (OBLIGATOIRE) - commande1 - commande2Les propriétés d'un job
Section intitulée « Les propriétés d'un job »Une seule ligne de ce tableau est obligatoire : script. Toutes les autres ont une valeur par défaut, et deux de ces valeurs par défaut surprennent régulièrement. Un job sans stage atterrit dans test, même si vous pensiez le placer en début de pipeline. Un job sans image hérite de l'image configurée sur le runner, pas d'une image liée à votre langage. Les trois dernières lignes (cache, rules, needs) relèvent d'un usage plus avancé ; laissez-les de côté pour un premier pipeline.
| Propriété | Obligatoire | Description |
|---|---|---|
script | Oui | Liste des commandes à exécuter |
stage | Non | Stage d'appartenance (défaut: test) |
image | Non | Image Docker pour l'environnement |
variables | Non | Variables d'environnement du job |
artifacts | Non | Fichiers à conserver après le job |
cache | Non | Fichiers à réutiliser entre pipelines |
rules | Non | Conditions d'exécution |
needs | Non | Dépendances explicites (ignore l'ordre des stages) |
Jobs en parallèle
Section intitulée « Jobs en parallèle »Les jobs d'un même stage s'exécutent en parallèle :
stages: - test
test-unitaires: stage: test script: - npm run test:unit
test-integration: stage: test script: - npm run test:integration
lint: stage: test script: - npm run lintCes 3 jobs démarrent simultanément car ils sont tous dans le stage test.
Niveau 3 : Écrire les scripts
Section intitulée « Niveau 3 : Écrire les scripts »Le script contient les commandes shell exécutées par le job, dans l'ordre de la liste. Chaque item est une commande distincte, exécutée à la racine du dépôt fraîchement cloné par le runner. Les lignes echo de l'exemple ne servent pas de décoration : elles apparaissent dans les logs du job et servent de repères quand vous cherchez à quelle étape une construction s'est arrêtée.
build: stage: build script: - echo "Début du build" - npm ci - npm run build - echo "Build terminé"Règles du script
Section intitulée « Règles du script »La ligne à retenir est la troisième : GitLab ne juge pas la sortie de vos commandes, il regarde uniquement leur code de retour. Une commande qui affiche « ERROR » mais sort avec 0 laisse le job en vert, et une commande qui sort avec 1 stoppe le job même si tout semblait fonctionner. La dernière ligne explique pourquoi tant de jobs échouent sur une image Alpine : le shell y est /bin/sh, pas Bash, donc la syntaxe [[ ... ]] et les tableaux Bash provoquent une erreur de syntaxe.
| Règle | Exemple |
|---|---|
| Chaque ligne = une commande | - npm install |
| Exécution séquentielle | Ligne 1, puis ligne 2, puis ligne 3... |
| Échec = arrêt | Si une commande retourne un code ≠ 0, le job échoue |
| Shell par défaut | /bin/sh (ou celui de l'image Docker) |
Commandes multi-lignes
Section intitulée « Commandes multi-lignes »Le bloc littéral YAML | permet d'écrire plusieurs commandes qui partagent le même shell. C'est ce qui rend possible une condition if ou une boucle : découpées en items séparés, chaque ligne s'exécuterait dans son propre appel et la structure serait cassée. Attention toutefois, ce bloc reste une seule entrée de script pour GitLab : l'interface affiche tout d'un bloc et un échec en milieu de bloc est plus difficile à localiser dans les logs.
Pour des commandes longues ou des structures de contrôle, utilisez le bloc littéral | :
script: - | echo "Première ligne" echo "Deuxième ligne" if [ -f "config.json" ]; then echo "Config trouvée" fibefore_script et after_script
Section intitulée « before_script et after_script »Ces deux sections évitent de répéter la même préparation dans chaque job. La différence qui compte est leur comportement en cas d'échec : before_script est concaténé au script, donc s'il échoue, le job échoue immédiatement et le script n'est jamais lancé. À l'inverse, after_script s'exécute dans un shell séparé, y compris quand le job a échoué ou a été annulé, ce qui en fait le bon endroit pour un nettoyage ou la récupération d'un log de diagnostic. Corollaire à connaître : les variables définies dans le script ne sont pas visibles depuis after_script.
Déclarez-les sous default pour les appliquer à tous les jobs :
# S'exécute AVANT le script de chaque jobdefault: before_script: - echo "Préparation..." - npm ci
test: script: - npm test after_script: - echo "Nettoyage..." # S'exécute même si le job échoueSpécifier l'environnement avec image
Section intitulée « Spécifier l'environnement avec image »Un job sans image n'échoue pas : il hérite de l'image configurée sur le runner. Sur les runners hébergés par GitLab.com, cette valeur par défaut est ruby:3.1 ; sur un runner que vous administrez, c'est la clé image de la section [runners.docker] du fichier config.toml. Autrement dit, le même pipeline peut fonctionner chez vous et échouer chez un collègue sur command not found. Déclarer explicitement l'image est donc ce qui rend un pipeline reproductible.
build: image: node:24-alpine # Node.js 24 LTS sur Alpine Linux script: - node --version - npm ci - npm run buildLe tableau ci-dessous donne des points de départ, pas des obligations. La colonne image légère repose sur Alpine ou sur une variante slim : elle télécharge beaucoup plus vite, ce qui compte sur un pipeline lancé cinquante fois par jour, mais elle utilise la bibliothèque C musl au lieu de glibc. Un module natif compilé pour glibc peut donc refuser de se charger. En cas de doute au premier essai, prenez la colonne de droite.
| Langage | Image légère | Image complète |
|---|---|---|
| Node.js | node:24-alpine | node:24 |
| Python | python:3.13-slim | python:3.13 |
| Go | golang:1.26-alpine | golang:1.26 |
| Java | eclipse-temurin:21-alpine | eclipse-temurin:21 |
| Générique | alpine:3.24 | ubuntu:24.04 |
Définir des variables
Section intitulée « Définir des variables »Les variables permettent de configurer vos jobs sans modifier le script.
Variables globales
Section intitulée « Variables globales »Un bloc variables: écrit à la racine du fichier s'applique à tous les jobs du pipeline. Ces valeurs sont exportées comme variables d'environnement dans le conteneur du job, et s'utilisent avec la syntaxe shell $NOM. Réservez cet emplacement à ce qui est vraiment commun, comme une version d'outil ou un nom d'application ; une valeur qui ne concerne qu'un job appartient au job. Et gardez en tête que ce fichier est versionné dans Git : aucun secret n'a sa place ici, les jetons et mots de passe se déclarent dans les variables CI/CD du projet, masquées et protégées.
variables: NODE_ENV: production DEPLOY_TARGET: staging
build: script: - echo "Environment: $NODE_ENV" - echo "Target: $DEPLOY_TARGET"Variables par job
Section intitulée « Variables par job »Un bloc variables: placé dans un job ne vaut que pour ce job, et il écrase la valeur globale portant le même nom. C'est le mécanisme qui permet à un même pipeline de compiler en mode développement puis de déployer en mode production sans dupliquer le script. Le piège à connaître : ce bloc remplace intégralement la valeur globale pour la clé concernée, il ne la complète pas. Dans l'exemple ci-dessous, le NODE_ENV: production global n'a plus aucun effet sur le job build.
build: variables: NODE_ENV: development script: - npm run build
deploy: variables: NODE_ENV: production script: - npm run deployVariables prédéfinies GitLab
Section intitulée « Variables prédéfinies GitLab »GitLab injecte automatiquement des variables utiles :
| Variable | Contenu |
|---|---|
$CI_COMMIT_BRANCH | Nom de la branche |
$CI_COMMIT_SHORT_SHA | Hash court du commit |
$CI_PROJECT_NAME | Nom du projet |
$CI_PIPELINE_SOURCE | Déclencheur (push, merge_request, etc.) |
$CI_JOB_NAME | Nom du job en cours |
build: script: - echo "Building $CI_PROJECT_NAME on branch $CI_COMMIT_BRANCH" - echo "Commit: $CI_COMMIT_SHORT_SHA"Exemple complet commenté
Section intitulée « Exemple complet commenté »Ce pipeline rassemble tout ce qui précède sur un projet Node.js. Trois détails méritent votre attention à la lecture. Le job build publie dist/ en artifact, ce qui est la seule façon de transmettre des fichiers d'un stage au suivant : le répertoire de travail, lui, repart de zéro à chaque job. Les jobs test-unit et test-lint refont chacun un npm ci, parce qu'ils démarrent dans des conteneurs distincts et ne partagent aucun node_modules. Enfin, le job deploy combine rules et when: manual : il n'apparaît que sur la branche main, et il attend un clic dans l'interface avant de démarrer.
Voici un pipeline réaliste pour un projet Node.js :
# Déclaration des stages dans l'ordre d'exécutionstages: - build - test - deploy
# Variables globales disponibles dans tous les jobsvariables: NODE_ENV: production
# --- STAGE BUILD ---build: stage: build image: node:24-alpine@sha256:a0b9bf06e4e6193cf7a0f58816cc935ff8c2a908f81e6f1a95432d679c54fbfd script: - echo "Installation des dependances..." - npm ci - echo "Compilation..." - npm run build artifacts: paths: - dist/ # Conserve le dossier dist/ pour les jobs suivants expire_in: 1 hour # Supprimé après 1 heure
# --- STAGE TEST ---# Ces 2 jobs s'exécutent EN PARALLÈLEtest-unit: stage: test image: node:24-alpine@sha256:a0b9bf06e4e6193cf7a0f58816cc935ff8c2a908f81e6f1a95432d679c54fbfd script: - npm ci - npm run test:unit
test-lint: stage: test image: node:24-alpine@sha256:a0b9bf06e4e6193cf7a0f58816cc935ff8c2a908f81e6f1a95432d679c54fbfd script: - npm ci - npm run lint
# --- STAGE DEPLOY ---deploy: stage: deploy image: alpine:3.24@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b script: - echo "Deploiement vers $DEPLOY_TARGET..." - echo "Fichiers a deployer:" && ls dist/ rules: - if: $CI_COMMIT_BRANCH == "main" # Seulement sur main when: manual # Clic requis pour démarrerValider avant de commiter
Section intitulée « Valider avant de commiter »Une erreur de syntaxe ne se voit qu'après le push, et elle coûte un commit de correction dans l'historique. Les deux méthodes ci-dessous vérifient le fichier avant qu'il ne parte. Elles font toutes les deux appel au validateur de GitLab lui-même, pas à un analyseur YAML générique : elles détectent donc aussi un stage inconnu ou une propriété mal orthographiée, ce qu'un simple yamllint laisserait passer.
- Dans GitLab : Build > Pipeline editor > onglet Validate
- En local avec
glab, la CLI officielle GitLab :Fenêtre de terminal glab ci lint .gitlab-ci.yml
La validation mérite un traitement à part entière, notamment pour l'automatiser en pre-commit : le guide Valider un fichier .gitlab-ci.yml détaille l'API CI Lint et ses limites.
À retenir
Section intitulée « À retenir »| Niveau | Élément | Rôle |
|---|---|---|
| 1 | stages | Définit l'ordre des grandes étapes |
| 2 | Jobs | Tâches à accomplir (nommées librement) |
| 3 | script | Commandes shell à exécuter |
Construction logique :
- Listez vos étapes →
stages - Pour chaque étape, listez les tâches → jobs
- Pour chaque tâche, listez les commandes →
script
On passe à la pratique
Section intitulée « On passe à la pratique »Vous avez la méthode pour structurer un .gitlab-ci.yml. Passez maintenant sur un vrai cas guidé pour l'appliquer étape par étape dans GitLab.
Passez au Lab 01, Mon premier pipeline pour construire votre premier pipeline complet.
Contrôle des connaissances
Section intitulée « Contrôle des connaissances »Testez vos connaissances sur la structure des fichiers .gitlab-ci.yml.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Valider un fichier .gitlab-ci.yml : Contrôler la syntaxe de votre fichier avant de le pousser, avec CI Lint et le Pipeline editor.
- Debug : lire les logs GitLab CI/CD : Retrouver la cause exacte d'un job rouge dans la sortie brute du runner.
- Runners GitLab CI/CD : Savoir où et dans quelle image vos jobs s'exécutent réellement.