Mettre en place une architecture DRY sur GitLab CI

Industrialisez vos configurations GitLab CI/CD grâce aux mots-clés include, extends et au catalogue de composants.

Architecture DRY (Don't Repeat Yourself) sur GitLab

Le problème du pipeline monolithique

Au début d'un projet, un fichier .gitlab-ci.yml de 50 lignes fait très bien l'affaire. Mais lorsque l'entreprise grandit, que vous gérez le déploiement de 10 microservices, des tests de sécurité et des environnements multiples, votre fichier peut rapidement atteindre plusieurs milliers de lignes. Il devient alors un cauchemar à maintenir.

La philosophie DRY (Don't Repeat Yourself) s'applique aussi à l'infrastructure. GitLab propose plusieurs mécanismes pour découper, modulariser et réutiliser vos configurations CI/CD.

L'héritage de Jobs avec "extends"

Si plusieurs jobs utilisent la même image Docker, les mêmes variables ou les mêmes scripts de préparation, vous ne devez pas copier-coller ce code. Vous créez un template sous la forme d'un Job caché.

Astuce technique : Le point initial

Un job dont le nom commence par un point (ex: .mon_template) est ignoré par le moteur GitLab CI. Il ne sera jamais exécuté seul, il sert uniquement de modèle pour les autres.

Exemple d'industrialisation Docker :

# Définition du modèle commun
.docker_base:
  image: docker:24.0
  services:
    - docker:24.0-dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  tags:
    - docker-builder

# Utilisation concrète du modèle
build_api:
  extends: .docker_base
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE/api:$CI_COMMIT_SHA ./api
    - docker push $CI_REGISTRY_IMAGE/api:$CI_COMMIT_SHA

build_frontend:
  extends: .docker_base
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE/front:$CI_COMMIT_SHA ./frontend
    - docker push $CI_REGISTRY_IMAGE/front:$CI_COMMIT_SHA

Pourquoi c'est mieux ? Si vous décidez de changer la version de Docker ou de modifier la méthode de connexion au registre, vous ne modifiez qu'une seule ligne dans le template et tous vos jobs de build sont mis à jour instantanément.

La modularité avec "include"

Le mot-clé include permet de fragmenter votre configuration. C'est l'outil indispensable pour centraliser les standards au sein d'une entreprise.

  • local : Pour découper un fichier trop long en plusieurs petits fichiers thématiques dans le même projet.
  • project : Pour importer des règles depuis un dépôt GitLab externe (ex: un dépôt "Security-Team" qui impose des scans sur tous les projets).
  • template : Pour utiliser les modèles officiels fournis par GitLab (sécurité, qualité, etc.).

Regardons comment un expert DevOps découpe réellement son travail Gitlab CI. L'objectif est d'éviter le pipeline monolithique (un seul fichier géant de 2000 lignes) qui est impossible à maintenir.

Le spécialiste du build (ci/builders.yml)

Ce fichier est stocké dans un sous-dossier nommé ci/. Il ne contient que la logique de fabrication de l'application.

# Ce job est défini ici pour ne pas encombrer le fichier principal
job_construction_docker:
  stage: build
  image: docker:24.0
  services:
    - docker:24.0-dind
  script:
    - echo "Connexion au registre..."
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - echo "Fabrication de l'image..."
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

Le Chef d'Orchestre (.gitlab-ci.yml)

C'est le fichier à la racine du projet. Il est très court car il se contente d'importer le travail des autres et de définir les étapes globales.

# 1. On importe la logique de build depuis notre fichier local
include:
  - local: '/ci/builders.yml'

# 2. On définit l'ordre des étapes
stages:
  - build
  - test
  - deploy

# 3. On définit les jobs restants (plus simples)
job_test_rapide:
  stage: test
  script:
    - echo "Lancement des tests unitaires..."
    - exit 0 # Succès fictif

Le secret des experts : L'écrasement (Override)

Si vous incluez un fichier contenant un job nommé job_test, vous pouvez redéfinir ce même job dans votre fichier principal pour changer juste une commande. GitLab prendra votre version locale en priorité. C'est l'outil parfait pour utiliser des templates standards tout en les personnalisant légèrement.

Le Catalogue CI/CD : Votre bibliothèque de composants

À quoi sert le Catalogue CI/CD ?

Dans les chapitres précédents, nous avons vu comment utiliser include pour importer des fichiers. Le Catalogue CI/CD est l'évolution moderne de ce concept. C'est une place de marché interne (ou publique) où vous pouvez trouver des briques de pipeline prêtes à l'emploi, appelées composants.

Au lieu de copier-coller des scripts complexes pour scanner votre code ou déployer sur Kubernetes, vous allez simplement "piocher" un composant certifié dans le catalogue. C'est un gain de temps massif car vous utilisez du code maintenu par d'autres experts, garantissant ainsi que vos pipelines respectent toujours les dernières normes de sécurité.

Comment accéder au catalogue ?

Pour consulter les composants disponibles pour vous et votre équipe, vous avez deux méthodes :

  • Depuis la barre de recherche : Sélectionnez Search or go to, puis Explore, et enfin CI/CD Catalog.
  • Depuis l'éditeur de pipeline : Si vous êtes déjà en train de modifier votre fichier .gitlab-ci.yml, un bouton CI/CD Catalog est directement disponible dans l'interface.
Consultez le catalogue CI/CD

"Consultez le catalogue CI/CD"

Visibilité et Permissions

Tous les composants ne sont pas visibles par tout le monde. Leur accès dépend des réglages de visibilité du projet d'origine :

  • Projets Privés : Les composants ne sont visibles que par les membres du projet (rôles Guest à Owner). Notez que pour utiliser concrètement le composant dans un pipeline, vous devez posséder au moins le rôle Reporter.
  • Projets Internes : Visibles par tous les utilisateurs connectés à votre instance GitLab.
  • Projets Publics : Visibles par n'importe qui ayant accès à l'instance, même sans être connecté.

Exemple d'utilisation d'un composant du catalogue :

include:
  # Utilisation d'un composant de détection de secrets depuis le catalogue
  - component: gitlab.com/components/secret-detection/secret-detection@1.0.0
    inputs:
      stage: test

Pourquoi privilégier le catalogue au "include: file" ?

Contrairement à un simple fichier inclus, les composants du catalogue sont encapsulés. Ils utilisent des inputs (entrées) qui agissent comme des arguments de fonction, ce qui évite que les variables du composant ne viennent écraser vos propres variables de projet par accident.

Bonnes Pratiques de l'Architecte DevOps

Pourquoi centraliser vos configurations ?

Dans une entreprise gérant des dizaines ou des centaines de projets, laisser chaque équipe écrire son propre fichier .gitlab-ci.yml est une erreur stratégique. Cela mène à une fragmentation technologique : chaque projet utilise une version différente de Docker, des scripts de déploiement disparates et des niveaux de sécurité inégaux.

L'approche de l'Architecte DevOps consiste à créer une "source unique de vérité". En centralisant la logique complexe dans un dépôt dédié, vous transformez la maintenance corrective en une tâche simple et instantanée pour toute l'organisation.

Mise en œuvre : Le projet "ci-templates"

La méthode consiste à créer un projet GitLab spécifique, par exemple nommé direction-technique/ci-templates, dont le seul but est d'héberger des fichiers YAML réutilisables.

Ce que l'on centralise dans ce dépôt :

  • Les jobs de déploiement : Les commandes complexes pour Kubernetes, Terraform ou rsync vers vos serveurs.
  • Les règles de Qualité (Linting) : Les configurations pour vérifier que le code respecte les normes de l'entreprise.
  • La sécurité : L'inclusion des scanners SAST et de détection de secrets pré-configurés avec vos variables spécifiques.

Le fonctionnement technique : include:project

Pour utiliser ces standards, les développeurs n'ont plus qu'à importer le fichier distant dans leur propre projet.

# Dans le projet d'une équipe de développeurs
include:
  - project: 'direction-technique/ci-templates'
    ref: 'v2.4.0' # On pointe vers une version stable (un Git Tag)
    file: '/templates/production-deploy.yml'

stages:
  - build
  - deploy

job_local_build:
  stage: build
  script:
    - npm run build

# Le job de déploiement est "magiquement" importé et prêt à l'emploi

Les avantages d'un dépôt de standards

Avantage Description
Maintenance Unique Si vous changez de serveur de production, vous modifiez le script dans ci-templates une seule fois. Tous les projets héritent de la mise à jour au prochain lancement.
Sécurité Globale Vous garantissez que 100% des projets utilisent les mêmes scanners de vulnérabilités sans exception.
Montée en compétence Les nouveaux développeurs n'ont pas besoin d'apprendre Kubernetes, ils utilisent simplement le template "clé en main" fourni par les experts DevOps.

Conseil d'expert : Ne jamais pointer sur "main"

Lorsque vous utilisez include:project, utilisez toujours l'option ref pour cibler un tag (ex: v1.0.0). Si vous pointez sur la branche par défaut et que vous faites une modification cassante dans le dépôt de standards, vous risquez de bloquer simultanément tous les pipelines de l'entreprise.

Conclusion

La maîtrise de l'architecture DRY marque le passage d'une configuration artisanale à une véritable ingénierie de production. En utilisant l'héritage avec extends pour vos logiques internes et la modularité avec include pour vos standards externes, vous transformez un pipeline monolithique fragile en un système agile et scalable.

Grâce au Catalogue CI/CD et à la centralisation dans un dépôt de standards, vous garantissez désormais que chaque projet de votre organisation bénéficie des meilleures pratiques en matière de sécurité et de déploiement. Vous ne vous contentez plus de faire fonctionner du code, vous bâtissez une infrastructure robuste capable de soutenir la croissance de votre entreprise.

Cependant, une architecture propre n'est que la moitié du chemin. Pour que vos pipelines industrialisés puissent interagir avec le monde réel, ils doivent pouvoir communiquer de manière sécurisée avec vos serveurs. Dans le prochain chapitre, nous allons voir comment gérer les Environnements de déploiement et sécuriser vos accès distants grâce aux clés SSH.

Espace commentaire

Écrire un commentaire

Rejoignez la discussion

Vous devez être connecté pour poster un message.

22 commentaires

ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

D'autres questions sur la modularité avant que je passe au prochain sujet sur les accès SSH ?

24/05/2026 à 19:15
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Catalogue direct. L'encapsulation via les inputs rend le code beaucoup plus robuste qu'un simple include qui pollue ton namespace de variables.

24/05/2026 à 13:52
gchauveau
Membre
Avatar de gchauveau
gchauveau
Membre

Pour les gros projets, vous préférez include:file ou le catalogue ?

24/05/2026 à 06:02
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Effectivement, les scripts sont remplacés. Pour fusionner, utilise des ancêtres YAML :

.base:   before_script:     - echo "base"  job:   extends: .base   before_script:     - !reference [.base, before_script]     - echo "nouveau"
23/05/2026 à 23:11
rene-blanc
Membre
Avatar de rene-blanc
rene-blanc
Membre

Le extends ne fonctionne pas pour les before_script, il les écrase au lieu de les fusionner, c'est relou.

23/05/2026 à 16:17
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Oui, redéfinis simplement la variable dans ton fichier principal. Ta valeur locale prendra le dessus sur le template.

23/05/2026 à 12:04
picard-noel
Membre
Avatar de picard-noel
picard-noel
Membre

Est-ce que je peux surcharger une variable définie dans un template importé ?

23/05/2026 à 07:02
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Vérifie si ton fichier est bien dans le dépôt. Parfois, un mauvais .gitignore empêche le fichier d'être tracké par Git.

23/05/2026 à 02:21
peron-raymond
Membre Actif
Avatar de peron-raymond
peron-raymond
Membre Actif

J'ai une erreur 404 sur mon include. Le chemin est pourtant dans le dossier ci/.

22/05/2026 à 18:29
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Tu tagues tes releases dans le dépôt du composant. Ensuite, dans tes projets, tu appelles la version précise :

- component: gitlab.com/my-org/my-comp@1.2.3

Ne jamais utiliser @main en prod.

22/05/2026 à 13:09

Le catalogue CI/CD c'est bien, mais comment on versionne nos composants pour ne pas tout casser ?

22/05/2026 à 09:04
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

T'as bien mis le point au début ?

.mon_job_cache:   script:     - echo "test"

Si t'oublies le point, GitLab le traite comme un job normal.

22/05/2026 à 04:35

J'ai un souci avec mon job caché. Il n'est pas ignoré comme prévu.

22/05/2026 à 00:02
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Si ton projet est gros, arrête le local et passe sur un dépôt de templates centralisé. Trop d'imports locaux, c'est la porte ouverte au chaos.

21/05/2026 à 19:18
hugues13
Membre Actif
Avatar de hugues13
hugues13
Membre Actif

J'ai tenté de modulariser avec include:local mais mon fichier est devenu illisible avec trop d'imports.

21/05/2026 à 14:51
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Utilise l'outil CI Lint dans l'interface GitLab. Ça valide la syntaxe YAML et l'expansion des include avant de push.

21/05/2026 à 08:17
mnavarro
Membre
Avatar de mnavarro
mnavarro
Membre

Comment je peux débugger mon .gitlab-ci.yml sans lancer 50 pipelines qui échouent ?

21/05/2026 à 01:10
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Oui, c'est le comportement attendu. GitLab fusionne les configurations. Si tu veux éviter ça, utilise les composants du catalogue qui isolent les inputs.

20/05/2026 à 17:20
celine06
Membre Actif
Avatar de celine06
celine06
Membre Actif

J'essaie d'utiliser extends pour factoriser mes jobs mais mes variables locales écrasent tout, c'est normal ?

20/05/2026 à 11:58

C'était bien ça, le ref pointait sur une branche supprimée. Merci.

20/05/2026 à 05:15
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Vérifie les permissions du projet distant. Si c'est un projet privé, ton runner doit avoir accès au dépôt. T'as bien configuré le ref sur un tag stable ?

19/05/2026 à 23:44

Super article. Par contre j'ai une erreur avec include:project. Mon pipeline ne trouve pas le fichier distant alors que le chemin semble bon.

19/05/2026 à 18:18

Rejoindre la communauté

Recevoir les derniers articles gratuitement en créant un compte !

S'inscrire