Introduction à l'optimisation de vos pipelines GitLab CI

Accélérez vos builds GitLab CI/CD en utilisant le système de cache, les artefacts de compilation et le graphe DAG.

Introduction à l'optimisation de vos pipelines GitLab CI

Dans les chapitres précédents, nous avons vu comment créer des automatisations simples. Cependant, dans un environnement DevOps professionnel, un pipeline ne doit pas simplement exécuter des commandes de manière linéaire. Il doit devenir intelligent.

L'enjeu n'est plus seulement de "faire fonctionner" le code, mais de l'optimiser pour qu'il soit plus rapide, moins coûteux en ressources et capable de s'adapter aux modifications complexes de votre projet. Nous allons maintenant explorer comment transformer votre fichier YAML en un véritable chef d'orchestre grâce aux Règles, au DAG, à la Matrice et à la gestion avancée des Artefacts et du Cache.

Maîtriser les Artefacts : Conserver et Transmettre vos fichiers

Qu'est-ce qu'un Artefact dans GitLab CI ?

Un artefact est une liste de fichiers ou de répertoires générés par un job à la fin de son exécution. Par défaut, GitLab nettoie l'environnement du Runner après chaque tâche, ce qui signifie que tout fichier créé (comme un binaire compilé ou un rapport de test) est supprimé. Les artefacts permettent de "sauvegarder" ces fichiers sur le serveur GitLab.

Imaginez qu'un job de construction est un artisan qui fabrique un meuble. Une fois le travail terminé, l'atelier est balayé. Si l'artisan ne met pas le meuble dans un carton d'expédition (l'artefact), le meuble disparaît. Les artefacts servent donc à deux choses : permettre aux jobs suivants de récupérer ces fichiers ou permettre à l'utilisateur de les télécharger manuellement.

Configuration dans le fichier .gitlab-ci.yml

Vous définissez les artefacts directement dans le job qui produit les fichiers.

job_compilation:
  stage: build
  script:
    - npm run build # Génère un dossier 'dist/'
  artifacts:
    name: "version_du_$CI_COMMIT_REF_NAME" # Nom personnalisable de l'archive
    paths:
      - dist/ # Le contenu à sauvegarder
    expire_in: 1 week # Temps avant suppression automatique sur GitLab
    when: on_success # N'upload que si le job réussit

Les options clés :

  • name : Donne un nom unique à l'archive téléchargée (très utile pour s'y retrouver).
  • expire_in : Définit la durée de vie de l'artefact avant sa suppression pour économiser l'espace disque du serveur.
  • when : Vous pouvez choisir d'envoyer des fichiers même en cas d'échec avec on_failure.

Où retrouver vos artefacts ?

GitLab offre plusieurs points d'accès pour récupérer vos fichiers générés :

  • Dans le pipeline : Allez dans Build > Pipelines. À droite de chaque pipeline, une icône de téléchargement permet de récupérer les artefacts de tous les jobs.
  • Dans un job spécifique : Cliquez sur un job terminé. Dans la colonne de droite, vous verrez une section Job artifacts avec les boutons Download et Browse.
  • Via l'API : Utile pour des scripts externes qui souhaitent récupérer la dernière version stable d'un programme (Plus d'informations ici)
Interface de téléchargement des artefacts

"L'interface de job permet de parcourir les fichiers directement dans le navigateur"

Optimisation de la performance : Le Cache GitLab CI

Pourquoi utiliser le Cache ?

Dans un pipeline CI/CD, beaucoup de temps est gaspillé à retélécharger les mêmes dépendances à chaque exécution (comme les dossiers node_modules ou .maven). Le Cache est un mécanisme de stockage temporaire qui permet de conserver ces fichiers entre deux exécutions du pipeline.

Contrairement aux Artifacts, qui servent à transmettre des fichiers entre les étapes (stages) d'un même pipeline, le Cache est conçu pour accélérer les pipelines futurs en réutilisant les données déjà téléchargées. Une stratégie de cache bien configurée peut réduire le temps de vos pipelines de plus de 50%.

Configuration du Cache dans le .gitlab-ci.yml

Pour activer le cache, vous devez définir deux éléments : une clé (key) pour identifier le cache et les chemins (paths) des dossiers à sauvegarder.

# Exemple d'optimisation pour un projet Node.js
variables:
  npm_config_cache: "$CI_PROJECT_DIR/.npm"

cache:
  key:
    files:
      - package-lock.json # Le cache change uniquement si ce fichier est modifié
  paths:
    - .npm/
    - node_modules/

job_test:
  stage: test
  image: node:22-alpine
  script:
    - npm ci --cache .npm --prefer-offline
    - npm test

Explication des paramètres :

  • files : GitLab génère une empreinte numérique (hash) basée sur le fichier package-lock.json. Si vous ajoutez une dépendance, la clé change et le cache est recréé.
  • paths : Liste les répertoires que le Runner doit compresser et envoyer au serveur GitLab à la fin du job.

Gestion des politiques de téléchargement (Policy)

Pour optimiser encore plus les performances, vous pouvez définir une politique d'utilisation du cache :

  • pull-push (par défaut) : Le job télécharge le cache au début et le met à jour à la fin.
  • pull : Le job télécharge le cache mais ne le renvoie pas à la fin. Idéal pour les jobs de test.
  • push : Le job ne télécharge rien mais crée/écrase le cache à la fin.

Exemple d'utilisation:

job_test_rapide:
  stage: test
  cache:
    key: "dependencies-$CI_COMMIT_REF_SLUG"
    paths:
      - node_modules/
    policy: pull # On gagne du temps en ne renvoyant pas le cache

Cache vs Artifacts : Le verdict

Utilisez le Cache pour les dépendances logicielles (fichiers que vous pouvez retélécharger). Utilisez les Artifacts pour les fichiers produits par votre build (ex: exécutables, rapports) que vous ne voulez surtout pas perdre.

Le contrôle du flux : Maîtriser le mot-clé "rules"

Le mot-clé rules est le remplaçant moderne et plus puissant des anciennes directives only/except. Il permet d'évaluer une liste de conditions pour décider si un job doit être ajouté au pipeline.

deploy_to_production:
  stage: deploy
  script:
    - echo "Déploiement en cours..."
  rules:
    # Condition 1 : Exécution automatique uniquement sur la branche par défaut (main)
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      changes:
        - src/**/* # Uniquement si le dossier source est modifié
      when: on_success

    # Condition 2 : Déclenchement manuel autorisé pour les autres branches
    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
      when: manual
      allow_failure: true

Explication technique du code :

  • if : Utilise les variables CI/CD pour tester le contexte (ici, la branche).
  • changes : GitLab analyse le commit pour voir si les fichiers spécifiés ont bougé.
  • when: manual : Transforme le job en bouton dans l'interface GitLab. Le déploiement n'aura lieu que si un humain clique dessus.

Briser les barrières : Le DAG (Directed Acyclic Graph)

Le mot-clé "needs"

Par défaut, GitLab exécute les jobs de manière strictement linéaire. L'utilisation du mot-clé needs permet de briser cette barrière en créant un Directed Acyclic Graph (DAG).

Pourquoi utiliser "needs" :

  • Vitesse (Asynchronisme) : Si un build finit plus vite qu'un autre, les tests associés démarrent immédiatement sans attendre le reste du stage.
  • Indépendance des flux : Vous créez des "couloirs" d'exécution séparés. Les erreurs du back-end ne ralentissent plus le front-end.
test_frontend:
  stage: test
  needs: ["build_frontend"] # Dépendance directe
  script: npm run test

L'exécution de masse : parallel:matrix

La Matrice est l'outil ultime pour les tests multi-environnements et la scalabilité.

Pourquoi utiliser la matrice ?

  • Maintenance simplifiée : Vous ne modifiez qu'un seul bloc de code pour mettre à jour des dizaines de jobs simultanément.
  • Couverture maximale : Idéal pour tester la compatibilité de votre application sur plusieurs versions d'un langage (ex: Node.js 18, 20, 22) ou différents systèmes.
  • Gain de temps : GitLab distribue ces jobs sur tous les Runners disponibles, permettant une exécution massivement parallèle.
tests_compatibilite:
  stage: test
  image: node:${VERSION_NODE}
  parallel:
    matrix:
      - VERSION_NODE: ["18", "20", "22"]
        ENV: ["dev", "prod"]
  script:
    - echo "Exécution du test sur Node $VERSION_NODE pour l'environnement $ENV"
    - npm test

Sortie - Jobs générés :

Le moteur GitLab va créer 6 instances de jobs indépendantes :
1. tests_compatibilite: [18, dev]
2. tests_compatibilite: [18, prod]
3. tests_compatibilite: [20, dev]
4. tests_compatibilite: [20, prod]
5. tests_compatibilite: [22, dev]
6. tests_compatibilite: [22, prod]

Hooks globaux : before_script et after_script

Pour éviter la redondance, GitLab propose des Hooks (crochets).

  • before_script : S'exécute avant le script principal de chaque job. Idéal pour préparer l'environnement.
  • after_script : S'exécute systématiquement à la fin, même si le job a échoué. Crucial pour le nettoyage ou les notifications.

Exemple d'utilisation:

default:
  before_script:
    - apk add --no-cache curl  # Installation d'un outil requis par tous les jobs
  after_script:
    - echo "Nettoyage du répertoire de travail sur le Runner..."

job_web_test:
  stage: test
  script:
    - curl https://mon-application.local/health
    - npm run test

Optimisation : Le Cache vs les Hooks

Si votre before_script contient une commande lourde comme npm install, combinez-le avec le Cache pour diviser par deux le temps total du pipeline.

Conclusion

En maîtrisant ces outils, vous n'êtes plus un simple utilisateur de la CI/CD, vous en êtes l'architecte. Vous savez désormais réduire le temps d'attente grâce au Cache, sécuriser vos productions via les Artefacts et piloter des exécutions massives avec la Matrice.

Cependant, une infrastructure performante doit pouvoir se mesurer. Dans le prochain chapitre, nous utiliserons le Cycle Analytics pour transformer vos gains techniques en données tangibles.

Espace commentaire

Écrire un commentaire

Rejoignez la discussion

Vous devez être connecté pour poster un message.

21 commentaires

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

Content que ça aide. Le secret c'est vraiment de découpler au maximum les jobs qui n'ont pas de dépendances directes entre eux.

23/05/2026 à 19:06

Merci pour le tuto sur le DAG, ça a divisé mon temps de build par 3.

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

Utilise la syntaxe **/* pour récursif. Si tu mets juste src/, il ne verra pas forcément les modifications profondes. Exemple :

rules:
  - changes:
      - "src/**/*"
23/05/2026 à 05:59
virginie59
Membre
Avatar de virginie59
virginie59
Membre

J'ai testé rules: changes mais ça ne semble pas détecter les fichiers dans les sous-répertoires, une idée ?

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

C'est pour ça que je recommande de coupler le before_script avec le cache. Voici comment optimiser l'installation d'outils :

default:
  before_script:
    - if [ ! -d ".bin" ]; then mkdir .bin; fi
    - export PATH=$PATH:.bin
22/05/2026 à 16:17
maryse97
Membre
Avatar de maryse97
maryse97
Membre

Oui, dès que le job démarre, le before_script tourne. Attention aux coûts si tu installes des trucs lourds à chaque fois.

22/05/2026 à 10:42

Le before_script global s'exécute même si le job est en manual ?

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

Non, pas nativement. Pour forcer un reset, le plus simple reste de changer la key dans ton fichier de config. Ça force le Runner à en créer un nouveau.

21/05/2026 à 22:34
aimee25
Membre
Avatar de aimee25
aimee25
Membre

Est-ce qu'on peut forcer le nettoyage du cache via l'interface sans vider tout le bucket S3 ?

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

Vérifie aussi que le job cité dans needs n'est pas ignoré par une règle rules. Si le job parent n'existe pas, le job enfant échouera.

21/05/2026 à 14:16
emile95
Membre
Avatar de emile95
emile95
Membre

Regarde bien ton indentation. Si ton job n'est pas dans le même pipeline ou si le nom est mal orthographié, le DAG ne peut pas créer le lien.

21/05/2026 à 10:01
ymallet
Membre
Avatar de ymallet
ymallet
Membre

J'ai une erreur job not found quand je mets un nom dans needs. Comment je debug ça ?

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

C'est par job. Si tu ne précises rien, GitLab garde les artefacts indéfiniment, ce qui finit par saturer ton disque. Mets toujours une expiration raisonnable comme 1 week.

20/05/2026 à 20:09
rvalentin
Membre
Avatar de rvalentin
rvalentin
Membre

Le expire_in des artefacts est global ou par job ?

20/05/2026 à 14:14
thibaut65
Membre
Avatar de thibaut65
thibaut65
Membre

Oui, tu peux utiliser une variable dans ton image:. Par exemple : image: node:${VERSION_NODE}. Ça marche très bien chez moi.

20/05/2026 à 07:24
olemonnier
Membre Rédacteur
Avatar de olemonnier
olemonnier
Membre Rédacteur

Quelqu'un a réussi à faire marcher parallel:matrix avec une image Docker dynamique ?

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

Oui, c'est le comportement attendu. Avec needs, tu brises la structure linéaire des stages. Tu dois explicitement définir artifacts: true dans ton needs si tu veux récupérer les fichiers du job parent.

19/05/2026 à 20:29
ydurand
Membre
Avatar de ydurand
ydurand
Membre

J'ai un souci avec le DAG. Quand j'utilise needs, mes artefacts ne sont pas transmis aux jobs aval. C'est normal ?

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

Exact. Vérifie aussi la valeur de ta key. Si elle change à chaque commit, tu recrées un nouveau cache à chaque fois au lieu de réutiliser l'existant. Utilise files comme indiqué dans mon exemple pour stabiliser la clé.

19/05/2026 à 08:15
colette04
Membre Actif
Avatar de colette04
colette04
Membre Actif

Vérifie tes chemins dans .gitlab-ci.yml. Si tu es en pull policy sans avoir fait de push avant, c'est normal que ton cache soit vide.

19/05/2026 à 02:30
faivre-eric
Membre
Avatar de faivre-eric
faivre-eric
Membre

Super article. Par contre, mon cache node_modules ne se télécharge jamais. J'ai l'impression que le Runner ignore ma config.

18/05/2026 à 19:19

Rejoindre la communauté

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

S'inscrire