Optimiser les pipelines CI/CD avec GitHub Actions : matrices, caches et stratégies de déclenchement
Apprenez à accélérer vos builds, réduire les coûts et garantir la reproductibilité grâce aux matrices, aux caches et aux déclencheurs conditionnels dans GitHub Actions.
Introduction
GitHub Actions est devenu le choix de prédilection pour automatiser les builds, les tests et les déploiements. Pourtant, un workflow mal conçu peut entraîner des temps d’exécution excessifs et une consommation inutile de ressources. Cet article montre, de façon concrète, comment structurer un pipeline CI/CD efficace : utilisation des matrices pour couvrir plusieurs environnements, mise en cache des dépendances et définition de stratégies de déclenchement précises.
Utiliser les matrices pour tester plusieurs environnements
Les matrices permettent d’exécuter le même job avec des paramètres différents (versions de langage, systèmes d’exploitation, etc.) sans dupliquer le code du workflow.
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: [14, 16, 18]
fail-fast: false
steps:
- uses: actions/checkout@v3
- name: Set up Node.js ${{ matrix.node }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}
- run: npm ci
- run: npm test
Dans cet exemple, chaque combinaison (OS × version Node) est exécutée en parallèle. La clé fail-fast: false garantit que l’échec d’une matrice n’interrompt pas les autres, ce qui est utile pour obtenir un panorama complet des incompatibilités.
Astuces pratiques
- Limitez le nombre de combinaisons à ce qui est réellement requis ; chaque matrice supplémentaire multiplie le coût d’exécution.
- Utilisez la variable
matrix.includepour ajouter des cas spécifiques (par ex. un test sur une version de Node non‑sémantique).
Mettre en cache les dépendances
Le téléchargement répété des dépendances (npm, Maven, pip, …) augmente fortement le temps de build. GitHub Actions propose un mécanisme de cache partagé entre les jobs.
- name: Cache npm dependencies
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
Le key se base sur le hash du fichier de verrouillage ; dès que le contenu change, le cache est invalidé et un nouveau est créé. Le champ restore-keys sert de secours si aucune correspondance exacte n’est trouvée.
Points d’attention
- Le cache ne doit pas dépasser 5 GB (limite imposée par GitHub). Surveillez sa taille en affichant le répertoire caché.
- Pour les projets multi‑modules, créez plusieurs caches afin d’éviter les collisions entre chemins de dépendances.
Configurer les stratégies de déclenchement et les workflows conditionnels
Un pipeline efficace ne doit pas s’exécuter à chaque push. GitHub Actions permet de filtrer les événements grâce aux expressions if et aux filtres paths/branches.
on:
push:
branches: [ main, release/* ]
paths:
- src/**
- package.json
- .github/workflows/ci.yml
Cette configuration limite les exécutions aux branches principales et aux modifications du code source. De plus, à l’intérieur d’un job, on peut conditionner l’étape de déploiement :
- name: Deploy to production
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: ./deploy.sh
Les expressions booléennes offrent une granularité fine, évitant les builds inutiles et réduisant les coûts.
Bonnes pratiques et pièges à éviter
- Décomposer les jobs : un job qui compile, teste et déploie en une seule étape est difficile à diagnostiquer. Séparez les responsabilités (build, test, lint, deploy).
- Limiter la durée maximale : définissez
timeout-minutespour chaque job afin d’empêcher les builds bloqués. - Utiliser les artefacts : partagez les résultats de compilation entre les jobs avec
actions/upload-artifactetactions/download-artifactplutôt que de re‑compiler. - Surveiller les quotas : chaque compte possède un quota mensuel de minutes d’exécution. Consultez la page
Settings > Billing & planspour anticiper les dépassements. - Documenter le workflow : ajoutez des commentaires dans le fichier YAML pour expliquer les raisons des choix (ex. pourquoi
fail-fastest désactivé).
En appliquant ces techniques, vous transformerez un pipeline basique en une chaîne d’intégration continue robuste, rapide et économique. Chaque optimisation se traduit immédiatement par des builds plus courts, moins de ressources consommées et une meilleure visibilité sur la qualité du code.
Envie d’aller plus loin avec CertifApp ?
Découvrir CertifApp