Dépendances
node_modules, .m2/repository, .cache/pip, vendor/
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.
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 :
| Aspect | Cache | Artifacts |
|---|---|---|
| Objectif | Accélérer les builds répétitifs | Partager des résultats |
| Durée de vie | 7 jours sans accès | Configurable (1-90 jours) |
| Accès | Même workflow uniquement | Téléchargeable par tous |
| Visible dans l’UI | Non (interne) | Oui (téléchargeable) |
| Entre runs | ✅ Oui | ❌ Non (propre à chaque run) |
| Entre jobs | ⚠️ Pas fiable | ✅ Oui |
| Taille max | 10 GB par repo (total) | 10 GB par artifact |
| Coût stockage | Inclus dans le plan | Inclus dans le plan |
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
npm-linux-abc123)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 ciExplication 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 lockfileQuand le lockfile change → la clé change → nouveau cache créé.
Que se passe-t-il si la clé exacte n’existe pas ?
key: npm-linux-abc123 # Clé exacte recherchéerestore-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.”
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 ciDisponible aussi pour Python (actions/setup-python), Go, Java, etc.
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
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.shLes artifacts sont visibles dans l’interface GitHub :
Utile pour récupérer des rapports de tests, des logs de debug, ou des builds.
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 productionCe qui se passe :
npm ci (les dépendances sont réutilisées entre runs)- 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 TypeScriptPour 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# Pour un artifact temporaire (entre jobs)retention-days: 1
# Pour un build à déployerretention-days: 7
# Pour un audit de sécuritéretention-days: 90# ❌ NE FONCTIONNE PAS de manière fiablejobs: 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 disponiblePourquoi ? 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.
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# ❌ Upload node_modules, .git, tout...- uses: actions/upload-artifact@... with: path: .
# ✅ Uniquement ce qui est nécessaire- uses: actions/upload-artifact@... with: path: dist/# ❌ 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/| Situation | Utilisez |
|---|---|
Accélérer npm ci / pip install | Cache |
| Partager le build entre jobs | Artifact |
| Garder les rapports de tests | Artifact |
| Réutiliser les dépendances entre runs | Cache |
| Télécharger un binaire pour release | Artifact |
| Accélérer un build incrémental | Cache |
| Transmettre des données entre jobs | Artifact |
| Stocker des fichiers volumineux temporaires | Artifact (retention-days: 1) |
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 :
setup-node, setup-python, ou actions/cache)retention-days minimal)needs:if: failure()