Aller au contenu
CI/CD & Automatisation medium

Artefacts et cache GitLab CI/CD

17 min de lecture

logo gitlab

Vos jobs s'exécutent sur des runners, mais votre npm install prend 3 minutes à chaque fois ? Le problème : les dépendances sont retéléchargées à chaque job. La solution : le cache pour réutiliser les dépendances, et les artefacts pour passer des fichiers entre jobs. Ce guide vous montre comment optimiser vos pipelines.

À la fin de ce module, vous saurez :

  • Différencier artefacts et cache : deux mécanismes complémentaires
  • Configurer les artefacts : passer des fichiers entre jobs (dist/, coverage/)
  • Configurer le cache : réutiliser node_modules/, .venv/ entre pipelines
  • Choisir la bonne clé de cache : invalider automatiquement quand les dépendances changent
  • Optimiser les performances : réduire le temps de pipeline de 50-90%
  • Dépanner : diagnostiquer les problèmes de cache et d'artefacts

Avant de continuer, assurez-vous de maîtriser :

Les deux mécanismes transportent des fichiers d'un job à l'autre, mais ils ne donnent pas les mêmes garanties. Un artefact est stocké sur GitLab et sera là, c'est un contrat. Un cache est une optimisation opportuniste : GitLab peut le purger, le runner peut ne pas le retrouver, et votre pipeline doit fonctionner sans. Cette différence de fiabilité décide de ce que vous mettez dans l'un et dans l'autre.

AspectArtefactsCache
ButPasser des fichiers entre jobsRéutiliser entre pipelines
PortéeJobs du même pipelineTous les pipelines (si cache partagé)
Durée de vieConfigurable (défaut variable selon instance)Jusqu'à invalidation de la clé
FiabilitéGarantie (stocké sur GitLab)Best-effort (peut être purgé)
TéléchargeableOui, dans l'interfaceNon
Exempledist/, coverage/.npm/, .cache/pip

Artefacts vs Cache : les artefacts passent entre jobs d'un même pipeline, le cache persiste entre pipelines

Les artefacts permettent de conserver des fichiers d'un job et de les passer aux jobs suivants. À la fin du job, GitLab compresse les chemins déclarés et les téléverse ; au démarrage de chaque job d'un stage ultérieur, il les redescend automatiquement, sans rien à déclarer côté consommateur. C'est ce transfert implicite qui surprend le plus : le job test ci-dessous ne mentionne nulle part dist/, il le reçoit quand même.

Le job build déclare dist/ en sortie, le job test le trouve dans son répertoire de travail. Le expire_in fixe la durée de conservation côté GitLab, il n'a aucun effet sur la disponibilité pendant le pipeline en cours.

build:
stage: build
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 week
test:
stage: test
script:
- npm test dist/ # dist/ est automatiquement disponible

Voici les cinq options réellement utiles au quotidien. Retenez surtout when: always : par défaut, un job qui échoue ne téléverse rien, y compris les rapports de test et les logs qui expliqueraient l'échec.

artifacts:
paths:
- dist/
- coverage/
exclude:
- "**/*.map" # Exclure les source maps
expire_in: 1 week # Durée de conservation
when: always # Même si le job échoue
name: "build-$CI_COMMIT_SHA" # Nom du fichier zip

Valeurs de when :

ValeurComportement
on_successUniquement si le job réussit (défaut)
on_failureUniquement si le job échoue
alwaysDans tous les cas

Les artefacts sont téléchargeables depuis l'interface GitLab :

  1. CI/CD > Jobs → cliquez sur un job
  2. Bouton Download artifacts (à droite)
  3. Ou dans CI/CD > Artifacts pour voir tous les artefacts

GitLab comprend certains formats de rapport pour les afficher dans l'interface :

test:
script:
- npm test -- --coverage --reporters=jest-junit
artifacts:
reports:
junit: junit.xml # Résultats de tests
coverage_report:
coverage_format: cobertura
path: coverage/cobertura.xml

Cela affiche les tests échoués directement dans la merge request !

Le cache conserve des fichiers entre les pipelines pour éviter de retélécharger les dépendances. Le runner l'extrait avant le script et le réarchive après, ce qui a un coût : sur un node_modules/ de plusieurs dizaines de milliers de fichiers, l'archivage peut annuler le gain. Deux réglages font toute la différence, la clé qui décide de la réutilisation et la politique qui décide de la réécriture.

Sans clé explicite, GitLab utilise la clé default, partagée par tous les jobs et toutes les branches du projet. C'est le point de départ le plus simple, et aussi celui qui produit le plus de collisions dès que deux branches ont des dépendances différentes.

build:
cache:
paths:
- node_modules/
script:
- npm ci
- npm run build

La clé de cache détermine quand le cache est réutilisé ou recréé :

cache:
key: $CI_COMMIT_REF_SLUG # Une clé par branche
paths:
- node_modules/

Clés courantes :

CléComportement
defaultCache global, partagé par tout
$CI_COMMIT_REF_SLUGUn cache par branche
$CI_JOB_NAMEUn cache par job
Fichier hash (voir ci-dessous)Invalidé quand le fichier change

Pour invalider le cache quand les dépendances changent :

cache:
key:
files:
- package-lock.json # Nouvelle clé si le lock change
paths:
- node_modules/

Si package-lock.json change, le cache est recréé automatiquement.

La politique contrôle si le job lit, écrit, ou fait les deux. C'est le réglage le plus rentable du guide : dans un pipeline classique, un seul job installe les dépendances, tous les autres se contentent de les lire. Leur laisser la politique par défaut pull-push les fait réarchiver et téléverser un cache identique à chaque exécution, pour rien.

# Job qui lit ET écrit le cache (défaut)
install:
cache:
policy: pull-push
paths:
- node_modules/
script:
- npm ci
# Job qui lit seulement (plus rapide)
test:
cache:
policy: pull
paths:
- node_modules/
script:
- npm test
PolitiqueLectureÉcritureCas d'usage
pull-pushJob qui installe (défaut)
pullJobs qui utilisent seulement
pushRégénérer le cache

Chaque écosystème place son cache ailleurs, et le piège est toujours le même : cacher le répertoire d'installation au lieu du répertoire de téléchargement. Les quatre configurations ci-dessous sont complètes et transposables, elles redirigent d'abord le cache de l'outil dans $CI_PROJECT_DIR (seul emplacement que le runner sait archiver), puis y appliquent une clé basée sur le fichier de lock.

npm ci supprime et recrée node_modules/ à chaque exécution. Le gain vient du cache npm (tarballs téléchargés), pas de node_modules/ :

variables:
NPM_CONFIG_CACHE: "$CI_PROJECT_DIR/.npm"
default:
cache:
key:
files:
- package-lock.json
paths:
- .npm/ # Cache des tarballs, pas node_modules
policy: pull-push
install:
stage: install
script:
- npm ci --prefer-offline # Utilise le cache local si possible
cache:
policy: pull-push
build:
stage: build
script:
- npm ci --prefer-offline
- npm run build
cache:
policy: pull
artifacts:
paths:
- dist/
test:
stage: test
script:
- npm ci --prefer-offline
- npm test
cache:
policy: pull

Ces quatre réglages se posent indépendamment les uns des autres et se cumulent. Appliquez-les dans l'ordre indiqué : le premier corrige l'erreur de conception la plus répandue, les trois suivants réduisent le temps passé à transférer le cache. Mesurez avant et après sur un pipeline réel, la durée des étapes Checking cache et Creating cache figure dans les logs de chaque job.

Mettre dist/ en cache le fait remonter d'un pipeline à l'autre : vous risquez de tester un build périmé sans vous en apercevoir. Les résultats de build sont des artefacts, jamais du cache.

# ✅ Bon : cache des téléchargements
cache:
paths:
- .npm/ # ou .cache/pip, .m2/repository
# ❌ Mauvais : dist/ doit être en artefact, pas en cache
cache:
paths:
- .npm/
- dist/

2. Utilisez policy: pull pour les jobs qui ne modifient pas le cache

Section intitulée « 2. Utilisez policy: pull pour les jobs qui ne modifient pas le cache »

Un job de test n'ajoute aucune dépendance : lui faire réarchiver puis téléverser le cache à chaque exécution est du temps perdu sur chaque pipeline.

test:
cache:
policy: pull # 2x plus rapide que pull-push

Tant que le lock ne bouge pas, la clé reste identique et le cache est réutilisé. Dès qu'une dépendance change, la clé change et le cache se reconstruit, sans purge manuelle ni intervention de votre part.

cache:
key:
files:
- package-lock.json # Invalide auto si dépendances changent

Le stage .pre s'exécute avant tous les autres stages du pipeline. Y isoler l'installation donne un point unique d'écriture du cache, ce qui rend le policy: pull des autres jobs sûr.

install:
stage: .pre # Stage spécial, avant tous les autres
script:
- npm ci
cache:
policy: pull-push
paths:
- node_modules/
# Les autres jobs utilisent policy: pull

Deux lignes de ce tableau décrivent un fonctionnement normal, pas une panne : un cache invalidé après un changement de lock et un Cache not found au premier run sont exactement ce qu'on attend. Les vrais problèmes sont ailleurs, dans une clé instable ou dans l'absence de backend partagé côté runner.

ProblèmeCause probableSolution
Cache jamais utiliséClé différente à chaque runVérifier la clé de cache
Cache obsolèteLock file changéBonne chose ! Le cache se reconstruit
"Cache not found"Premier run ou cache purgéNormal, le cache se recréera
Cache OK en local, KO en autoscalePas de cache distribuéConfigurer S3/GCS côté runner
Artefacts non trouvésJob dans un stage différent échouéVérifier les dépendances entre stages
Artefacts expirésexpire_in trop courtAugmenter la durée
Artefacts jamais supprimésDernier pipeline réussi conservéDésactiver dans Settings > CI/CD
  1. Artefacts = fichiers entre jobs (même pipeline), Cache = fichiers entre pipelines
  2. Cache pour les téléchargements (.npm/, .cache/pip), artefacts pour les résultats (dist/, .venv/)
  3. Clé basée sur le lock file pour invalider automatiquement quand les dépendances changent
  4. policy: pull pour les jobs qui ne modifient pas le cache (plus rapide)
  5. Cache distribué requis pour autoscaling/Kubernetes (S3, GCS, Azure Blob)
  6. Le cache est best-effort, votre pipeline doit fonctionner sans

Appliquez ces notions dans le Lab 04, Artifacts et cache.

Testez vos connaissances sur les artefacts et le cache GitLab CI/CD.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

10 questions
5 min.
70% requis

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

  • Variables et secrets : Paramétrer les chemins d'artefacts et les clés de cache au lieu de les figer dans le YAML.
  • Conditions rules : Ne produire artefacts et cache que sur les branches où ils servent réellement.
  • DAG et parallélisme : Chaîner les jobs sur leurs vraies dépendances d'artefacts avec needs plutôt que sur l'ordre des stages.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn