
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.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »À 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
Prérequis
Section intitulée « Prérequis »Avant de continuer, assurez-vous de maîtriser :
Artefacts vs Cache : quelle différence ?
Section intitulée « Artefacts vs Cache : quelle différence ? »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.
| Aspect | Artefacts | Cache |
|---|---|---|
| But | Passer des fichiers entre jobs | Réutiliser entre pipelines |
| Portée | Jobs du même pipeline | Tous les pipelines (si cache partagé) |
| Durée de vie | Configurable (défaut variable selon instance) | Jusqu'à invalidation de la clé |
| Fiabilité | Garantie (stocké sur GitLab) | Best-effort (peut être purgé) |
| Téléchargeable | Oui, dans l'interface | Non |
| Exemple | dist/, coverage/ | .npm/, .cache/pip |
Artefacts : passer des fichiers entre jobs
Section intitulée « Artefacts : passer des fichiers entre jobs »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.
Configuration de base
Section intitulée « Configuration de base »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 disponibleOptions des artefacts
Section intitulée « Options des artefacts »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 zipValeurs de when :
| Valeur | Comportement |
|---|---|
on_success | Uniquement si le job réussit (défaut) |
on_failure | Uniquement si le job échoue |
always | Dans tous les cas |
Télécharger les artefacts
Section intitulée « Télécharger les artefacts »Les artefacts sont téléchargeables depuis l'interface GitLab :
- CI/CD > Jobs → cliquez sur un job
- Bouton Download artifacts (à droite)
- Ou dans CI/CD > Artifacts pour voir tous les artefacts
Rapports de test
Section intitulée « Rapports de test »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.xmlCela affiche les tests échoués directement dans la merge request !
Cache : réutiliser entre pipelines
Section intitulée « Cache : réutiliser entre pipelines »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.
Configuration de base
Section intitulée « Configuration de base »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 buildClé de cache
Section intitulée « Clé de cache »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 |
|---|---|
default | Cache global, partagé par tout |
$CI_COMMIT_REF_SLUG | Un cache par branche |
$CI_JOB_NAME | Un cache par job |
| Fichier hash (voir ci-dessous) | Invalidé quand le fichier change |
Clé basée sur un fichier
Section intitulée « Clé basée sur un fichier »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.
Politique de cache
Section intitulée « Politique de cache »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| Politique | Lecture | Écriture | Cas d'usage |
|---|---|---|---|
pull-push | ✅ | ✅ | Job qui installe (défaut) |
pull | ✅ | ❌ | Jobs qui utilisent seulement |
push | ❌ | ✅ | Régénérer le cache |
Exemples par langage
Section intitulée « Exemples par langage »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: pullCacher un venv complet peut casser (image différente, version Python, dépendances natives). Plus robuste : cache pip (téléchargements) + artefact venv (même pipeline) :
variables: PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
default: cache: key: files: - requirements.txt paths: - .cache/pip/ # Cache des téléchargements pip policy: pull-push
install: stage: install script: - python -m venv .venv - . .venv/bin/activate - pip install -r requirements.txt artifacts: paths: - .venv/ # Artefact pour les jobs suivants expire_in: 1 day
test: stage: test script: - . .venv/bin/activate - pytest # Pas besoin de cache:policy ici, le venv vient des artefactsMaven télécharge dans ~/.m2/repository par défaut, hors du répertoire de projet donc hors de portée du cache. Le MAVEN_OPTS le redirige, c'est la ligne indispensable :
default: cache: key: files: - pom.xml paths: - .m2/repository/
variables: MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
build: stage: build script: - mvn clean package -DskipTests artifacts: paths: - target/*.jar
test: stage: test script: - mvn testCachez à la fois le module cache (dépendances) et le build cache (compilation) pour un gain maximal :
variables: GOPATH: "$CI_PROJECT_DIR/.go" GOMODCACHE: "$CI_PROJECT_DIR/.go/pkg/mod" GOCACHE: "$CI_PROJECT_DIR/.cache/go-build"
default: cache: key: files: - go.sum paths: - .go/pkg/mod/ # Modules téléchargés - .cache/go-build/ # Résultats de compilation policy: pull-push
build: stage: build script: - go build -o app ./... artifacts: paths: - app
test: stage: test script: - go test ./... cache: policy: pullStratégies d'optimisation
Section intitulée « Stratégies d'optimisation »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.
1. Cache les téléchargements, pas le build
Section intitulée « 1. Cache les téléchargements, pas le build »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échargementscache: paths: - .npm/ # ou .cache/pip, .m2/repository
# ❌ Mauvais : dist/ doit être en artefact, pas en cachecache: 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-push3. Clé basée sur le fichier de lock
Section intitulée « 3. Clé basée sur le fichier de lock »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 changent4. Un job dédié à l'installation
Section intitulée « 4. Un job dédié à l'installation »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: pullDépannage
Section intitulée « Dépannage »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ème | Cause probable | Solution |
|---|---|---|
| Cache jamais utilisé | Clé différente à chaque run | Vérifier la clé de cache |
| Cache obsolète | Lock 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 autoscale | Pas de cache distribué | Configurer S3/GCS côté runner |
| Artefacts non trouvés | Job dans un stage différent échoué | Vérifier les dépendances entre stages |
| Artefacts expirés | expire_in trop court | Augmenter la durée |
| Artefacts jamais supprimés | Dernier pipeline réussi conservé | Désactiver dans Settings > CI/CD |
À retenir
Section intitulée « À retenir »- Artefacts = fichiers entre jobs (même pipeline), Cache = fichiers entre pipelines
- Cache pour les téléchargements (
.npm/,.cache/pip), artefacts pour les résultats (dist/,.venv/) - Clé basée sur le lock file pour invalider automatiquement quand les dépendances changent
policy: pullpour les jobs qui ne modifient pas le cache (plus rapide)- Cache distribué requis pour autoscaling/Kubernetes (S3, GCS, Azure Blob)
- Le cache est best-effort, votre pipeline doit fonctionner sans
On passe à la pratique
Section intitulée « On passe à la pratique »Appliquez ces notions dans le Lab 04, Artifacts et cache.
Contrôle des connaissances
Section intitulée « Contrôle des connaissances »Testez vos connaissances sur les artefacts et le cache GitLab CI/CD.
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
Pour aller plus loin
Section intitulée « Pour aller plus loin »- 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
needsplutôt que sur l'ordre des stages.