Aller au contenu

Artifacts vs Cache dans GitHub Actions

Mise à jour :

Votre workflow CI prend 8 minutes. À chaque run, il télécharge les mêmes dépendances, reconstruit les mêmes fichiers… Pourquoi recommencer à zéro alors que rien n’a changé ?

GitHub Actions propose deux mécanismes pour éviter ce gaspillage : le cache et les artifacts. Ils semblent similaires, mais ont des usages très différents. Choisir le bon mécanisme au bon moment peut diviser par deux le temps de vos workflows.

La différence en une phrase

Analogie : le restaurant

Imaginez un restaurant :

  • Le cache, c’est le garde-manger : vous y stockez des ingrédients (farine, épices, conserves) que vous réutilisez pour plusieurs services. Ils ne sont pas spécifiques à un plat.

  • Les artifacts, c’est le passe-plat : les plats préparés en cuisine passent par là pour arriver en salle. Ils sont spécifiques à une commande.

Dans GitHub Actions :

  • Le cache stocke les dépendances (node_modules, pip packages) réutilisées entre les runs
  • Les artifacts transportent les résultats (build, rapports) entre les jobs d’un même run

Tableau comparatif détaillé

AspectCacheArtifacts
ObjectifAccélérer les builds répétitifsPartager des résultats
Durée de vie7 jours sans accèsConfigurable (1-90 jours)
AccèsMême workflow uniquementTéléchargeable par tous
Visible dans l’UINon (interne)Oui (téléchargeable)
Entre runs✅ Oui❌ Non (propre à chaque run)
Entre jobs⚠️ Pas fiable✅ Oui
Taille max10 GB par repo (total)10 GB par artifact
Coût stockageInclus dans le planInclus dans le plan

Quand utiliser le cache ?

Le cache est fait pour les fichiers qui ne changent pas souvent et qu’on peut recréer si nécessaire :

Dépendances

node_modules, .m2/repository, .cache/pip, vendor/

Outils téléchargés

Binaires, CLIs, SDKs

Builds intermédiaires

Fichiers de compilation, caches de bundlers

Comment fonctionne le cache ?

  1. Clé de cache : vous définissez une clé unique (ex: npm-linux-abc123)
  2. Restauration : au début du job, GitHub cherche un cache avec cette clé
  3. Hit ou miss :
    • Hit : le cache existe → il est restauré (rapide !)
    • Miss : pas de cache → les fichiers sont recréés normalement
  4. Sauvegarde : à la fin du job, le cache est sauvegardé avec la clé

Exemple : cache des dépendances npm

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# Le cache est restauré AVANT npm ci
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: ~/.npm # Où npm stocke son cache
key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
npm-${{ runner.os }}-
# npm ci utilise le cache s'il existe
- run: npm ci

Explication de la clé :

  • npm- : préfixe pour identifier le type de cache
  • ${{ runner.os }} : OS du runner (linux, windows, macos)
  • ${{ hashFiles('package-lock.json') }} : hash du lockfile

Quand le lockfile change → la clé change → nouveau cache créé.

Les restore-keys : le filet de sécurité

Que se passe-t-il si la clé exacte n’existe pas ?

key: npm-linux-abc123 # Clé exacte recherchée
restore-keys: |
npm-linux- # Sinon, cherche un cache commençant par "npm-linux-"
npm- # Sinon, cherche un cache commençant par "npm-"

C’est comme dire : “Je veux le cache du lockfile actuel, mais s’il n’existe pas, donne-moi le dernier cache npm disponible — c’est mieux que rien.”

Syntaxe simplifiée avec setup-node

Les actions setup-* intègrent souvent le cache :

# ✅ Équivalent plus simple
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: '20'
cache: 'npm' # Active le cache automatiquement
- run: npm ci

Disponible aussi pour Python (actions/setup-python), Go, Java, etc.


Quand utiliser les artifacts ?

Les artifacts sont faits pour les fichiers produits par un job qu’on veut :

Partager entre jobs

Build utilisé par les jobs test et deploy

Télécharger manuellement

Rapports de tests, couverture, logs

Conserver pour audit

Binaires signés, attestations

Comment fonctionnent les artifacts ?

  1. Upload : un job crée des fichiers et les uploade
  2. Stockage : GitHub les conserve (1-90 jours selon configuration)
  3. Download : un autre job (ou un humain) les télécharge
  4. Nettoyage : supprimés automatiquement après la période de rétention

Exemple : partager un build entre jobs

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Build
run: npm run build
# Upload le résultat du build
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: dist # Nom de l'artifact
path: dist/ # Fichiers à uploader
retention-days: 1 # Garder 1 jour (minimum)
test:
needs: build # ⚠️ OBLIGATOIRE pour garantir l'ordre
runs-on: ubuntu-latest
steps:
# Télécharger l'artifact du job build
- uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
with:
name: dist
path: dist/
- run: npm test
deploy:
needs: [build, test] # Après build ET test
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
with:
name: dist
path: dist/
- run: ./deploy.sh

Voir et télécharger les artifacts

Les artifacts sont visibles dans l’interface GitHub :

  1. Allez sur un run de workflow
  2. Scrollez jusqu’à la section Artifacts
  3. Cliquez sur le nom pour télécharger le zip

Utile pour récupérer des rapports de tests, des logs de debug, ou des builds.


Le pattern complet : cache + artifacts

Dans un workflow réel, vous utilisez les deux :

name: CI/CD
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# CACHE : accélérer l'installation des dépendances
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run build
- run: npm test
# ARTIFACT : partager le build pour le déploiement
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: production-build
path: dist/
retention-days: 7
deploy-staging:
needs: build
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
with:
name: production-build
path: dist/
- run: ./deploy.sh staging
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
with:
name: production-build
path: dist/
- run: ./deploy.sh production

Ce qui se passe :

  1. Le cache accélère npm ci (les dépendances sont réutilisées entre runs)
  2. L’artifact transporte le build vers staging puis production
  3. On ne rebuild qu’une seule fois pour tout le pipeline

Optimiser les artifacts

Exclure les fichiers inutiles

- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: dist
path: |
dist/
!dist/**/*.map # Exclure les source maps
!dist/**/*.d.ts # Exclure les types TypeScript

Uploader seulement en cas d’échec

Pour les logs de debug, inutile de les garder si tout fonctionne :

- name: Run tests
run: npm test
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: failure() # Seulement si le step précédent a échoué
with:
name: debug-logs
path: |
logs/
coverage/
test-results/
retention-days: 3

Minimiser la rétention

# Pour un artifact temporaire (entre jobs)
retention-days: 1
# Pour un build à déployer
retention-days: 7
# Pour un audit de sécurité
retention-days: 90

Erreurs courantes à éviter

❌ Utiliser le cache pour partager entre jobs

# ❌ NE FONCTIONNE PAS de manière fiable
jobs:
build:
steps:
- run: npm run build
- uses: actions/cache/save@...
with:
path: dist/
key: build-${{ github.sha }}
deploy:
needs: build
steps:
- uses: actions/cache/restore@...
# Peut échouer ! Le cache n'est pas garanti d'être disponible

Pourquoi ? Le cache est conçu pour être réutilisé entre runs, pas entre jobs du même run. Il peut y avoir des délais de propagation.

Solution : Utilisez un artifact.

❌ Oublier needs:

# ❌ Les jobs démarrent en parallèle !
jobs:
build:
steps:
- uses: actions/upload-artifact@...
test:
# Manque: needs: build
steps:
- uses: actions/download-artifact@... # Peut échouer

❌ Uploader tout le projet

# ❌ Upload node_modules, .git, tout...
- uses: actions/upload-artifact@...
with:
path: .
# ✅ Uniquement ce qui est nécessaire
- uses: actions/upload-artifact@...
with:
path: dist/

❌ Cacher les résultats de build

# ❌ Les builds doivent être dans des artifacts, pas en cache
- uses: actions/cache@...
with:
path: dist/
key: build-${{ github.sha }}
# ✅ Utiliser un artifact
- uses: actions/upload-artifact@...
with:
name: dist
path: dist/

Guide de décision rapide

SituationUtilisez
Accélérer npm ci / pip installCache
Partager le build entre jobsArtifact
Garder les rapports de testsArtifact
Réutiliser les dépendances entre runsCache
Télécharger un binaire pour releaseArtifact
Accélérer un build incrémentalCache
Transmettre des données entre jobsArtifact
Stocker des fichiers volumineux temporairesArtifact (retention-days: 1)

À retenir

Cache = entre runs

Pour les fichiers réutilisables (dépendances, outils) qui accélèrent les builds répétitifs.

Artifacts = entre jobs

Pour les fichiers produits (builds, rapports) à partager ou télécharger.

Clé de cache = lockfile

Utilisez hashFiles() sur le lockfile pour invalider le cache quand les dépendances changent.

needs: = obligatoire

Sans needs:, les jobs sont parallèles. L’artifact n’existera peut-être pas encore.

Checklist :

  1. ✅ Dépendances → Cache (via setup-node, setup-python, ou actions/cache)
  2. ✅ Résultats de build → Artifact (avec retention-days minimal)
  3. ✅ Partage entre jobs → Artifact + needs:
  4. ✅ Logs de debug → Artifact avec if: failure()

Liens utiles