
Vous répétez les mêmes lignes dans plusieurs jobs ? extends et les anchors YAML permettent de factoriser votre configuration. Définissez une fois, réutilisez partout.
Ce guide est fait pour vous si…
Section intitulée « Ce guide est fait pour vous si… »Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »À la fin de ce module, vous saurez :
- Utiliser
extends: faire hériter un job d’un template caché - Créer des jobs cachés : la convention
.pour les templates - Surcharger les propriétés : personnaliser l’héritage sans tout réécrire
- Comprendre la fusion : dictionnaires fusionnent, listes remplacent
- Utiliser les anchors YAML :
&,*et<<:pour les cas avancés - Choisir le bon outil : extends vs anchors vs
!reference
Prérequis
Section intitulée « Prérequis »Avant de continuer, assurez-vous de maîtriser :
extends : héritage de job
Section intitulée « extends : héritage de job »L’analogie de l’héritage familial
Section intitulée « L’analogie de l’héritage familial »Imaginez une recette de famille transmise de génération en génération. La recette de base reste la même, mais chaque génération peut y apporter sa touche personnelle : ajouter une épice, changer un ingrédient.
extends fonctionne pareil : un job “enfant” hérite de toutes les propriétés d’un job “parent”, mais peut surcharger (remplacer) certaines d’entre elles.
Syntaxe de base
Section intitulée « Syntaxe de base »Un job peut hériter d’un autre job avec extends. Le job parent est généralement caché (préfixé par .) pour ne pas s’exécuter lui-même :
# Job caché (ne s'exécute pas).base_job: image: python:3.11 before_script: - pip install -r requirements.txt
# Job qui héritetest: extends: .base_job script: - pytestQue se passe-t-il concrètement ?
GitLab “fusionne” le job parent et le job enfant. C’est comme si vous aviez écrit :
test: image: python:3.11 # Hérité de .base_job before_script: # Hérité de .base_job - pip install -r requirements.txt script: # Défini par test - pytestLe job test hérite automatiquement de :
image: python:3.11before_script: [pip install -r requirements.txt]
Et définit son propre script.
Jobs cachés (convention .)
Section intitulée « Jobs cachés (convention .) »Les jobs dont le nom commence par . sont des templates — ils ne s’exécutent jamais. Leur seul rôle est de servir de modèle pour d’autres jobs.
.template: # ❌ Ne s'exécute pas (commence par .) image: alpine
my_job: # ✅ S'exécute (nom normal) extends: .template script: echo "Hello"Pourquoi utiliser des jobs cachés ?
- Éviter la pollution : Sans le
., GitLab essaierait d’exécuter le template comme un vrai job - Clarté : En voyant
.nodejs_base, on comprend immédiatement que c’est un template - Convention : Tout le monde utilise cette notation, votre code est lisible par d’autres
Héritage multiple
Section intitulée « Héritage multiple »Un job peut hériter de plusieurs templates à la fois. C’est utile pour composer des comportements :
.base: image: node:18 variables: ENV: production
.with_cache: cache: paths: - node_modules/
build: extends: - .base # Premier : fournit image + variables - .with_cache # Second : ajoute le cache script: npm run buildbuild hérite de .base ET .with_cache. Le résultat final :
build: image: node:18 # De .base variables: ENV: production # De .base cache: paths: - node_modules/ # De .with_cache script: npm run build # Défini localementSurcharger les propriétés
Section intitulée « Surcharger les propriétés »L’héritage serait limité si on ne pouvait pas personnaliser. Le job enfant peut surcharger (remplacer) n’importe quelle propriété héritée du parent :
.node_base: image: node:18 script: - npm test variables: NODE_ENV: development
# Surcharge plusieurs propriétésbuild_prod: extends: .node_base image: node:20 # 🔄 Remplace node:18 par node:20 script: - npm run build # 🔄 Remplace npm test par npm run build variables: NODE_ENV: production # 🔄 Remplace development par production
# Garde presque tout, change juste le scripttest: extends: .node_base script: - npm run lint # 🔄 Remplace le script - npm testCe qui est surchargé vs ce qui est hérité :
Propriété dans build_prod | Valeur | Source |
|---|---|---|
image | node:20 | Surchargée (était node:18) |
script | npm run build | Surchargée (était npm test) |
variables.NODE_ENV | production | Surchargée (était development) |
Fusion des tableaux : le piège classique
Section intitulée « Fusion des tableaux : le piège classique »Voici le piège le plus fréquent avec extends : les tableaux (listes) sont complètement remplacés, pas fusionnés.
.base: script: - echo "step 1" - echo "step 2"
job: extends: .base script: - echo "only this" # ⚠️ REMPLACE complètement, ne s'ajoute pas !Résultat : job exécute uniquement echo "only this". Les étapes “step 1” et “step 2” ont disparu.
Comment ajouter des étapes sans remplacer ?
Utilisez before_script et after_script qui s’ajoutent autour de script :
.base: before_script: - echo "setup" # Toujours exécuté en premier script: - echo "main" # Le script principal
job: extends: .base after_script: - echo "cleanup" # S'ajoute à la fin, ne remplace rienOrdre d’exécution : setup → main → cleanup
Fusion des dictionnaires
Section intitulée « Fusion des dictionnaires »Les dictionnaires fusionnent en profondeur :
.base: variables: VAR1: "value1" VAR2: "value2"
job: extends: .base variables: VAR2: "overridden" # Surcharge VAR2 VAR3: "value3" # Ajoute VAR3 # Résultat : VAR1=value1, VAR2=overridden, VAR3=value3Anchors YAML
Section intitulée « Anchors YAML »Les anchors sont une fonctionnalité native de YAML — elles fonctionnent dans n’importe quel fichier YAML, pas seulement GitLab CI.
L’analogie du copier-coller intelligent
Section intitulée « L’analogie du copier-coller intelligent »Imaginez que vous surlignez un bloc de texte et lui donnez un nom (“bloc A”). Ensuite, partout où vous voulez ce même texte, vous tapez juste “coller bloc A”. C’est exactement ce que font les anchors.
Syntaxe : trois symboles à connaître
Section intitulée « Syntaxe : trois symboles à connaître »| Symbole | Ce qu’il fait | Analogie |
|---|---|---|
&name | Définit une ancre (comme “copier”) | “Je nomme ce bloc ‘config‘“ |
*name | Référence l’ancre (comme “coller”) | “Colle le bloc ‘config’ ici” |
<<: | Fusionne le contenu dans un dictionnaire | ”Fusionne ce bloc dans mes propriétés” |
Exemple concret
Section intitulée « Exemple concret »Voici comment utiliser les anchors pour éviter la répétition :
# 1️⃣ Définir une ancre avec &.job_template: &job_config # &job_config = "je nomme ce bloc" image: ruby:3.0 services: - postgres:14
# 2️⃣ Utiliser l'ancre avec << et *test1: <<: *job_config # "Fusionne job_config ici" script: ruby test1.rb
test2: <<: *job_config # Même configuration, autre script script: ruby test2.rbÉquivalent sans anchors (ce que vous auriez dû écrire sinon) :
test1: image: ruby:3.0 services: - postgres:14 script: ruby test1.rb
test2: image: ruby:3.0 services: - postgres:14 script: ruby test2.rbLes anchors vous ont économisé 4 lignes de duplication.
Anchors sur des valeurs
Section intitulée « Anchors sur des valeurs »variables: DATABASE_URL: &db_url "postgres://localhost:5432/app"
job1: variables: DB: *db_url
job2: variables: DATABASE: *db_urlCombiner plusieurs anchors
Section intitulée « Combiner plusieurs anchors ».base_config: &base image: node:18
.cache_config: &cache cache: paths: - node_modules/
build: <<: [*base, *cache] # Fusionne les deux script: npm run buildÉtendre des variables
Section intitulée « Étendre des variables »variables: &global_vars VAR1: "value1" VAR2: "value2"
job: variables: <<: *global_vars VAR3: "value3" # Ajoute une variableextends vs anchors vs !reference
Section intitulée « extends vs anchors vs !reference »| Aspect | extends | Anchors | !reference |
|---|---|---|---|
| Lisibilité | ✅ Plus clair | ❌ Syntaxe cryptique | ✅ Explicite |
| Merge mappings | ✅ Oui | ⚠️ Shallow | ❌ Non (insertion) |
| Réutiliser des listes | ❌ Écrase | ❌ Écrase | ✅ Oui |
| Multi-fichiers | ✅ Avec include | ❌ Même fichier | ✅ Avec include |
| Spécifique GitLab | Oui | Non (YAML) | Oui |
| Recommandé pour | Jobs complets | Valeurs simples | Fragments (rules, script) |
!reference : réutiliser des fragments
Section intitulée « !reference : réutiliser des fragments »GitLab propose !reference pour réutiliser des fragments de configuration (listes, mappings) sans les limitations des anchors :
.security_rules: rules: - if: '$CI_COMMIT_BRANCH == "main"' - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
.test_script: script: - npm test - npm run coverage
build: script: - npm run build rules: - !reference [.security_rules, rules] # Réutilise les rules
test: script: - !reference [.test_script, script] # Réutilise le script - npm run e2e # Ajoute une commande rules: - !reference [.security_rules, rules]Exemples pratiques
Section intitulée « Exemples pratiques »Base Node.js avec variantes
Section intitulée « Base Node.js avec variantes »variables: NODE_VERSION: "18" # Valeur par défaut, surchargeable
.node_base: image: "node:${NODE_VERSION}" cache: key: files: - package-lock.json paths: - node_modules/ before_script: - npm ci
build: extends: .node_base script: npm run build artifacts: paths: - dist/
test: extends: .node_base script: npm test coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'
lint: extends: .node_base script: npm run lint allow_failure: trueJobs de déploiement
Section intitulée « Jobs de déploiement ».deploy_base: image: alpine:3.18 before_script: - apk add --no-cache curl script: - ./deploy.sh "$ENVIRONMENT"
deploy_staging: extends: .deploy_base variables: ENVIRONMENT: staging environment: name: staging rules: - if: '$CI_COMMIT_BRANCH == "main"' when: manual
deploy_production: extends: .deploy_base variables: ENVIRONMENT: production environment: name: production rules: - if: '$CI_COMMIT_BRANCH == "main"' when: manualErreurs fréquentes
Section intitulée « Erreurs fréquentes »1. Le job ne s’exécute pas
Section intitulée « 1. Le job ne s’exécute pas »Symptôme : Votre job n’apparaît pas dans le pipeline.
Cause : Son nom commence par . — c’est un job caché (template).
Solution : Retirez le . du nom, ou créez un job qui extends ce template.
# ❌ Ne s'exécutera jamais.build: script: npm run build
# ✅ S'exécuterabuild: script: npm run build2. Script remplacé au lieu d’étendu
Section intitulée « 2. Script remplacé au lieu d’étendu »Symptôme : Les commandes du parent ont disparu.
Cause : Les tableaux (listes) ne fusionnent pas, ils sont remplacés.
Solution : Utilisez before_script / after_script, ou redéfinissez tout le script.
3. extends: unknown job
Section intitulée « 3. extends: unknown job »Symptôme : GitLab refuse de créer le pipeline.
Cause : Le job parent n’existe pas (faute de frappe, fichier non inclus).
Solution : Vérifiez :
- Le nom exact du job parent (avec le
.si c’est un template) - Que le fichier contenant le parent est bien inclus (
include:)
4. Anchor non trouvée
Section intitulée « 4. Anchor non trouvée »Symptôme : Erreur YAML à la création du pipeline.
Cause : Vous référencez une ancre (*name) avant de l’avoir définie (&name).
Solution : Définissez toujours l’ancre avant de l’utiliser dans le fichier.
# ❌ Erreur : ancre utilisée avant d'être définiejob: <<: *config # Erreur ! config n'existe pas encore
.template: &config image: alpine
# ✅ Correct : ancre définie d'abord.template: &config image: alpine
job: <<: *config # OK, config existeÀ retenir
Section intitulée « À retenir »extendspermet l’héritage de jobs — préférez-le aux anchors- Jobs cachés (
.name) ne s’exécutent pas, servent de templates - Mappings fusionnent, scalaires et tableaux sont écrasés
- Héritage multiple : le dernier gagne en cas de conflit
- Anchors (
&,*,<<:) pour les cas avancés dans le même fichier !referencepour réutiliser des fragments (rules, script) entre jobs- Combinez avec
includepour partager entre projets
Testez vos connaissances
Section intitulée « Testez vos connaissances »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