
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 »Le schéma suivant montre ce que le job enfant récupère du parent, et ce qu'il peut redéfinir pour son propre compte.
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@sha256:c7220863385ee39fb6d822da81f4469d0cd33ff893d92ce94105e5c3f4b95fe2 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@sha256:c6ae79e38498325db67193d391e6ec1d224d96c693a8a4d943498556716d3783 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@sha256:c6ae79e38498325db67193d391e6ec1d224d96c693a8a4d943498556716d3783 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.
Syntaxe : trois symboles à connaître
Section intitulée « Syntaxe : trois symboles à connaître »| Symbole | Ce qu'il fait |
|---|---|
&name | Définit une ancre (comme "copier") |
*name | Référence l'ancre (comme "coller") |
<<: | Fusionne le contenu dans un dictionnaire |
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@sha256:dcb8a8a6ee981f949da505cb9f4f15cde696e7bcb088955bc1f92f23a4cd7a72 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@sha256:dcb8a8a6ee981f949da505cb9f4f15cde696e7bcb088955bc1f92f23a4cd7a72 services: - postgres:14 script: ruby test1.rb
test2: image: ruby:3.0@sha256:dcb8a8a6ee981f949da505cb9f4f15cde696e7bcb088955bc1f92f23a4cd7a72 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 »Un anchor ne se limite pas aux blocs de job : il fonctionne sur n'importe quelle valeur scalaire, ce qui permet de déclarer une chaîne une seule fois et de la réutiliser partout où elle est attendue.
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 »Plusieurs anchors peuvent être fusionnés dans un même job. L'ordre compte : en cas de clé présente dans deux sources, la dernière déclarée l'emporte.
.base_config: &base image: node:18@sha256:c6ae79e38498325db67193d391e6ec1d224d96c693a8a4d943498556716d3783
.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 »Le bloc variables se fusionne comme n'importe quel mapping. Un job peut donc
hériter d'un jeu commun tout en ajoutant les siennes, sans avoir à recopier les
valeurs héritées.
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 »Ces deux configurations sont directement transposables. Elles montrent le cas le plus courant, un socle commun décliné en plusieurs variantes de la même tâche.
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@sha256:de0eb0b3f2a47ba1eb89389859a9bd88b28e82f5826b6969ad604979713c2d4f 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 »Les trois erreurs ci-dessous se ressemblent : le pipeline part sans message clair, ou un job attendu n'apparaît pas. Le symptôme visible ne désigne jamais directement la cause.
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
On passe à la pratique
Section intitulée « On passe à la pratique »Mettez ces techniques en pratique dans le Lab 13, DRY : extends et anchors.
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