
Vous copiez-collez les mêmes jobs entre vos projets ? Les templates GitLab CI/CD permettent de centraliser et réutiliser vos configurations. Modifiez en un seul endroit, propagez 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 les 5 types d’include : local, project, remote, template, component
- Créer un projet de templates : structure et organisation recommandées
- Versionner vos templates : ref avec tags pour la stabilité
- Partager entre projets : une source de vérité pour 50+ repos
- Conditionner les includes : rules pour inclure selon le contexte
- Sécuriser vos templates : éviter les risques de supply chain
- Débugger avec le Pipeline Editor : visualiser la config merged
Prérequis
Section intitulée « Prérequis »Avant de continuer, assurez-vous de maîtriser :
Pourquoi factoriser ?
Section intitulée « Pourquoi factoriser ? »Le problème : la dette de copier-coller
Section intitulée « Le problème : la dette de copier-coller »Sans factorisation, voici ce qui se passe :
| Situation | Impact concret |
|---|---|
| Duplication | Même job Node.js copié dans 50 projets |
| Dérive | Chaque projet diverge : Node 16 ici, Node 18 là, Node 20 ailleurs |
| Maintenance | Vulnérabilité découverte ? 50 merge requests à créer… |
| Incohérence | Projet A teste avec coverage, projet B non |
Exemple concret : Vous découvrez que npm ci est plus rapide et fiable que npm install. Pour mettre à jour 50 projets, il faut :
- 50 branches
- 50 merge requests
- 50 reviews
- 50 merges
→ 1 journée de travail pour un changement de 2 mots.
La solution : un template centralisé
Section intitulée « La solution : un template centralisé »Avec les templates :
| Avantage | Résultat |
|---|---|
| Une source de vérité | Le template définit la “bonne façon” de builder Node.js |
| Cohérence garantie | Tous les projets utilisent la même version |
| Mise à jour simple | 1 merge request dans le projet de templates = 50 projets mis à jour |
| Standards enforcés | Tests, linting, sécurité inclus par défaut |
include : importer des fichiers
Section intitulée « include : importer des fichiers »Le mot-clé include permet d’importer du YAML depuis d’autres fichiers. C’est la base de la réutilisation.
Les 5 types d’include
Section intitulée « Les 5 types d’include »GitLab propose 5 façons d’inclure des fichiers, selon leur emplacement :
| Type | Syntaxe | Où est le fichier ? | Cas d’usage typique |
|---|---|---|---|
local | local: '/path/file.yml' | Même repository | Découper un gros .gitlab-ci.yml |
project | project: 'group/project' | Autre projet GitLab | Templates partagés (recommandé) |
remote | remote: 'https://...' | URL externe | Templates open source |
template | template: 'Jobs/Build.gitlab-ci.yml' | Templates officiels GitLab | SAST, DAST, License Scanning |
component | component: 'gitlab.com/org/comp@v1' | CI/CD Catalog | Briques versionnées réutilisables |
Include local : organiser un gros fichier
Section intitulée « Include local : organiser un gros fichier »Quand votre .gitlab-ci.yml dépasse 200-300 lignes, il devient difficile à lire. La solution : découper en fichiers par catégorie.
# .gitlab-ci.yml (fichier principal, court et lisible)include: - local: '/ci/build.yml' # Jobs de build - local: '/ci/test.yml' # Jobs de test - local: '/ci/deploy.yml' # Jobs de déploiement
stages: - build - test - deploy# ci/build.yml (dédié au build)build: stage: build script: - npm ci - npm run buildPourquoi c’est mieux ?
- Lisibilité : chaque fichier a une seule responsabilité
- Collaboration : l’équipe infra modifie
deploy.yml, les devs modifienttest.yml - Navigation : on trouve rapidement ce qu’on cherche
Include project : partager entre projets
Section intitulée « Include project : partager entre projets »C’est le type d’include le plus utile. Il permet d’importer des templates depuis un projet GitLab dédié.
include: - project: 'devops/ci-templates' # Projet contenant les templates file: '/templates/nodejs.yml' # Chemin du fichier dans ce projet ref: 'main' # Branche, tag ou commitDéconstruction de la syntaxe :
| Option | Ce qu’elle fait | Exemple |
|---|---|---|
project | Chemin complet du projet GitLab | 'devops/ci-templates' |
file | Chemin du fichier dans le projet | '/templates/nodejs.yml' |
ref | Version à utiliser (optionnel) | 'main', 'v1.0.0', 'a1b2c3d' |
Le chemin project expliqueé :
devops/ci-templates└──┬── └────┬───────── groupe nom du projetSi votre projet est dans un sous-groupe : 'company/devops/ci-templates'
Include remote
Section intitulée « Include remote »Fichier externe via URL :
include: - remote: 'https://example.com/templates/ci.yml'Limites et pièges de include
Section intitulée « Limites et pièges de include »Templates officiels GitLab
Section intitulée « Templates officiels GitLab »GitLab fournit des templates prêts à l’emploi :
include: - template: Jobs/Build.gitlab-ci.yml - template: Security/SAST.gitlab-ci.ymlDocumentation officielle : GitLab CI/CD Templates — cette page liste tous les templates maintenus par GitLab avec leur documentation d’utilisation.
Templates centralisés dans un projet dédié
Section intitulée « Templates centralisés dans un projet dédié »Structure recommandée
Section intitulée « Structure recommandée »Créez un projet devops/ci-templates avec cette structure :
ci-templates/├── templates/│ ├── nodejs.yml│ ├── python.yml│ ├── docker.yml│ └── deploy/│ ├── kubernetes.yml│ └── aws.yml├── jobs/│ ├── lint.yml│ ├── test.yml│ └── security.yml└── README.mdExemple de template Node.js
Section intitulée « Exemple de template Node.js »Deux approches sont possibles. Choisissez-en une seule pour éviter la confusion :
Principe : Chaque job fait npm ci, mais le cache accélère le téléchargement.
# templates/nodejs.yml — Pattern Cache (recommandé pour débuter)
variables: NODE_VERSION: "18"
# Configuration de base partagée.nodejs_base: image: "node:${NODE_VERSION}" cache: key: files: - package-lock.json # Invalide si deps changent paths: - .npm/ # Cache npm, PAS node_modules/ policy: pull-push before_script: - npm ci --cache .npm --prefer-offline
# Build : npm ci déjà fait dans before_script.nodejs_build: extends: .nodejs_base script: - npm run build artifacts: paths: - dist/ expire_in: 1 week
# Test : npm ci déjà fait dans before_script.nodejs_test: extends: .nodejs_base script: - npm test coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'Avantages : Simple, robuste, fonctionne sur tous les runners.
Principe : Un job install produit node_modules/ en artifact, les autres le récupèrent via needs.
# templates/nodejs.yml — Pattern Artifacts (optimisé)
variables: NODE_VERSION: "18"
.nodejs_base: image: "node:${NODE_VERSION}"
# Install : produit node_modules/ une seule fois.nodejs_install: extends: .nodejs_base script: - npm ci artifacts: paths: - node_modules/ expire_in: 1 hour
# Build : récupère node_modules/ via needs (PAS de npm ci).nodejs_build: extends: .nodejs_base script: - npm run build # node_modules/ déjà présent artifacts: paths: - dist/ expire_in: 1 week
# Test : récupère node_modules/ via needs (PAS de npm ci).nodejs_test: extends: .nodejs_base script: - npm test # node_modules/ déjà présent coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'Usage côté projet :
install: extends: .nodejs_install
build: extends: .nodejs_build needs: ["install"] # Récupère node_modules/
test: extends: .nodejs_test needs: ["install"] # Récupère node_modules/Avantages : Plus rapide si beaucoup de jobs (install une seule fois). Inconvénient : Plus complexe, artifacts volumineux.
Utilisation dans un projet
Section intitulée « Utilisation dans un projet »include: - project: 'devops/ci-templates' file: '/templates/nodejs.yml' ref: 'v1.0.0'
stages: - install - build - test
install: stage: install extends: .nodejs_install
build: stage: build extends: .nodejs_build needs: ["install"]
test: stage: test extends: .nodejs_test needs: ["install"]Versionner avec ref
Section intitulée « Versionner avec ref »Pourquoi c’est critique
Section intitulée « Pourquoi c’est critique »Sans ref, vous utilisez la branche par défaut du projet de templates. Si quelqu’un y pousse un changement non testé, tous vos pipelines peuvent casser.
# ⚠️ Dangereux : utilise toujours la dernière versioninclude: - project: 'devops/ci-templates' file: '/templates/nodejs.yml' # Pas de ref = branche par défaut = peut changer à tout momentContrôler quelle version utiliser
Section intitulée « Contrôler quelle version utiliser »include: # ✅ Version stable pour la prod (recommandé) - project: 'devops/ci-templates' file: '/templates/nodejs.yml' ref: 'v1.0.0' # Tag = version figée
# ✅ Commit spécifique (maximum de contrôle) - project: 'devops/ci-templates' file: '/templates/nodejs.yml' ref: 'a1b2c3d4e5f6' # SHA du commit
# ⚠️ Branche (peut changer) - project: 'devops/ci-templates' file: '/templates/nodejs.yml' ref: 'main'Stratégie de versioning recommandée
Section intitulée « Stratégie de versioning recommandée »| Environnement | Quel ref utiliser | Pourquoi |
|---|---|---|
| Production | Tag (v1.0.0) | Stable, testé, ne change jamais |
| Staging | Branche main | Teste les dernières évolutions |
| Développement | Branche feature/* | Teste une nouvelle fonctionnalité |
Includes conditionnels
Section intitulée « Includes conditionnels »GitLab supporte include:rules pour conditionner les fichiers inclus :
include: # Toujours inclus - local: '/ci/base.yml'
# Seulement si variable définie - local: '/ci/security.yml' rules: - if: '$ENABLE_SECURITY == "true"'
# Seulement sur main - local: '/ci/deploy-prod.yml' rules: - if: '$CI_COMMIT_BRANCH == "main"'Quand utiliser (et quand éviter)
Section intitulée « Quand utiliser (et quand éviter) »| ✅ Bon usage | ⚠️ Mauvais usage |
|---|---|
Activer la sécurité via $ENABLE_SECURITY | Multiplier les conditions jusqu’à l’illisibilité |
Inclure le déploiement prod uniquement sur main | Conditionner chaque template individuellement |
| Désactiver des jobs en mode “dry-run” | Créer des branches logiques complexes |
Surcharger les templates
Section intitulée « Surcharger les templates »Les jobs qui étendent un template peuvent surcharger n’importe quelle propriété :
include: - project: 'devops/ci-templates' file: '/templates/nodejs.yml'
build: extends: .nodejs_build variables: NODE_VERSION: "20" # Surcharge la version script: - npm run build:prod # Surcharge le script after_script: - echo "Build terminé" # Ajoute un after_scriptOutils recommandés
Section intitulée « Outils recommandés »To Be Continuous
Section intitulée « To Be Continuous »Plateforme de templates GitLab CI/CD maintenus par des experts :
- Templates prêts à l’emploi pour de nombreuses technologies
- Bien documentés et régulièrement mis à jour
- Supporte les workflows modernes (Gitflow, trunk-based)
Site : to-be-continuous.gitlab.io
R2DevOps
Section intitulée « R2DevOps »Catalogue de templates avec audit de conformité :
- Catalogue visuel de templates
- Détection de secrets et variables non protégées
- Audit de conformité automatique
Site : r2devops.io
Sécurité des templates
Section intitulée « Sécurité des templates »Pinner par tag ou commit
Section intitulée « Pinner par tag ou commit »Utilisez toujours ref pour éviter les surprises :
include: # ✅ Version pinnée (recommandé) - project: 'devops/ci-templates' file: '/templates/nodejs.yml' ref: 'v1.0.0' # Tag
# ✅ Commit spécifique (maximum de contrôle) - project: 'devops/ci-templates' file: '/templates/nodejs.yml' ref: 'a1b2c3d4e5f6' # SHA commit
# ⚠️ Branche (peut changer) - project: 'devops/ci-templates' file: '/templates/nodejs.yml' ref: 'main'Vérifier l’intégrité (GitLab 17.9+)
Section intitulée « Vérifier l’intégrité (GitLab 17.9+) »include:integrity permet de vérifier le hash SHA256 du fichier inclus :
include: - remote: 'https://example.com/templates/ci.yml' integrity: 'sha256:abc123def456...' # Hash du fichierPinner aussi les components
Section intitulée « Pinner aussi les components »Les CI/CD Components (include: component) présentent le même risque que les includes classiques si vous ne les pinnez pas :
# ❌ Dangereux : utilise toujours la dernière versioninclude: - component: 'gitlab.com/components/sast@main'
# ✅ Sûr : version figéeinclude: - component: 'gitlab.com/components/sast@1.2.0'
# ✅ Maximum de contrôle : SHA du commitinclude: - component: 'gitlab.com/components/sast@a1b2c3d4e5f6'Mini-lab : Pipeline Editor et config merged
Section intitulée « Mini-lab : Pipeline Editor et config merged »Quand vous utilisez include, l’outil indispensable c’est le Pipeline Editor de GitLab.
-
Ouvrir le Pipeline Editor
Dans votre projet : Build → Pipeline editor
-
Visualiser la configuration complète
Cliquez sur l’onglet “View merged YAML” (ou “Full configuration”).
Vous voyez la configuration après résolution de tous les includes — c’est ce que GitLab exécute réellement.
-
Identifier l’origine d’un job
Dans la vue merged, cherchez le job qui pose problème. Vous pouvez voir :
- Toutes les variables héritées
- Les
extendsrésolus - Les
rulesfinales
-
Valider avant de commit
Le bouton “Validate” vérifie la syntaxe YAML et les références (jobs, stages).
Bonnes pratiques
Section intitulée « Bonnes pratiques »1. Préfixez les jobs cachés par technologie
Section intitulée « 1. Préfixez les jobs cachés par technologie »Sans préfixe, vous risquez des conflits entre templates :
# ❌ Risque de conflit.build: # Et si un autre template a aussi .build ? script: ...
# ✅ Préfixe explicite.nodejs_build:.python_build:.docker_build:2. Documentez vos templates
Section intitulée « 2. Documentez vos templates »Chaque template devrait avoir un README avec :
- Ce que fait le template (objectif)
- Comment l’utiliser (exemple minimal)
- Variables configurables (liste avec défauts)
- Versions supportées (changelog des breaking changes)
3. Testez vos templates
Section intitulée « 3. Testez vos templates »Créez un projet ci-templates-tests qui :
- Inclut chaque template
- Lance un pipeline de validation
- Vérifie que les jobs s’exécutent sans erreur
4. Séparez par technologie
Section intitulée « 4. Séparez par technologie »Un fichier = une technologie :
templates/├── nodejs.yml # Tout ce qui concerne Node.js├── python.yml # Tout ce qui concerne Python├── docker.yml # Build/push d'images Docker└── security.yml # Scans de sécurité (SAST, DAST)5. Variables par défaut explicites
Section intitulée « 5. Variables par défaut explicites »Définissez toujours une valeur par défaut dans le template :
# Dans le templatevariables: NODE_VERSION: "18" # Valeur par défaut
.nodejs_build: image: "node:${NODE_VERSION}"# Dans le projet (surcharge optionnelle)variables: NODE_VERSION: "20" # Surcharge la valeur par défaut6. Pinez TOUJOURS vos refs
Section intitulée « 6. Pinez TOUJOURS vos refs »# ❌ Dangereuxinclude: - project: 'devops/ci-templates' file: '/templates/nodejs.yml' # Pas de ref = utilise main = peut casser à tout moment
# ✅ Sûrinclude: - project: 'devops/ci-templates' file: '/templates/nodejs.yml' ref: 'v1.2.0' # Version figée7. Adoptez des conventions de nommage cohérentes
Section intitulée « 7. Adoptez des conventions de nommage cohérentes »Quand plusieurs équipes partagent des templates, les conventions évitent les conflits et facilitent la lecture :
| Élément | Convention | Exemples |
|---|---|---|
| Jobs cachés | .{techno}_{action} | .nodejs_build, .python_test, .docker_push |
| Variables de version | {TECHNO}_VERSION | NODE_VERSION, PYTHON_VERSION, GO_VERSION |
| Stages | Noms prévisibles | build, test, security, deploy |
| Fichiers | {techno}.yml | nodejs.yml, python.yml, security.yml |
# Exemple de template bien nommévariables: NODE_VERSION: "18" # Convention : TECHNO_VERSION
.nodejs_base: # Convention : .techno_action image: "node:${NODE_VERSION}"
.nodejs_build: extends: .nodejs_base stage: build # Stage prévisibleErreurs fréquentes
Section intitulée « Erreurs fréquentes »1. file not found
Section intitulée « 1. file not found »Symptôme : Le pipeline refuse de se créer.
include config from '/templates/nodejs.yml' not foundCauses possibles :
- Chemin incorrect (vérifiez les
/au début) - Fichier renommé ou supprimé dans le projet source
refqui pointe vers une branche/tag inexistant
Solution : Vérifiez le chemin exact dans le projet source.
2. project not found ou 403 Forbidden
Section intitulée « 2. project not found ou 403 Forbidden »Symptôme : GitLab ne trouve pas le projet de templates.
Causes possibles :
- Chemin de projet incorrect (
group/projectvsgroup/subgroup/project) - Pas de permissions d’accès au projet
- Projet privé sans accès pour le runner
Solution :
- Vérifiez que vous pouvez accéder au projet dans l’interface GitLab
- Demandez l’accès “Guest” minimum au projet de templates
3. Job hérité non trouvé
Section intitulée « 3. Job hérité non trouvé »Symptôme : extends: .nodejs_build échoue.
Cause : Le template n’exporte pas ce job (nom différent, ou job supprimé).
Solution : Ouvrez le fichier template et vérifiez le nom exact des jobs cachés.
4. Conflit de noms entre templates
Section intitulée « 4. Conflit de noms entre templates »Symptôme : Comportement bizarre, variables écrasées.
Cause : Deux templates définissent un job avec le même nom.
Solution : Utilisez des préfixes uniques (.nodejs_, .python_).
5. Variables non surchargées
Section intitulée « 5. Variables non surchargées »Symptôme : Votre valeur personnalisée est ignorée.
# Template.job: variables: VERSION: "1.0"
# Votre projetjob: extends: .job VERSION: "2.0" # ❌ Syntaxe incorrecte !Solution : Les variables se définissent dans variables:.
job: extends: .job variables: VERSION: "2.0" # ✅ CorrectÀ retenir
Section intitulée « À retenir »include: localpour les fichiers du même repoinclude: projectpour les templates centralisésinclude: componentpour les briques versionnées du CI/CD Catalogrefpour versionner — pinez par tag ou commit (y compris les components !)extendspour hériter et surcharger- Préfixer les jobs cachés (
.nodejs_,.python_) - Éviter
include: remotenon maîtrisé (risque supply chain) - Choisir UN pattern pour Node.js : cache
.npm/OU artifactsnode_modules/ - Pipeline Editor → View merged YAML pour débugger les includes
- Max 150 includes et 2 niveaux d’imbrication pour rester maintenable