Matrix GitHub Actions : tests parallèles multi-versions en pratique

La semaine dernière, le projet venait tout juste de passer en production. Avant même la fin de l’après-midi, un utilisateur nous a signalé que la page affichait un écran blanc sous Node 16. J’ai eu un choc.
Deux heures de débogage. J’ai parcouru les logs, comparé le code en trois passes, et j’ai fini par comprendre : une API traitait JSON.stringify() différemment sous Node 16 et Node 20 — l’ancienne version levait une erreur sur les références circulaires, la nouvelle les gérait silencieusement. Notre pipeline CI ne testait que Node 20, donc ce problème de compatibilité n’avait jamais été intercepté.
Lors du post-mortem, je me suis dit : avec des tests parallèles multi-versions, on aurait détecté ça avant la mise en ligne. C’est à partir de ce moment que j’ai creusé le Matrix de GitHub Actions — le terme impressionne, mais en réalité il s’agit de découper automatiquement une tâche en plusieurs instances qui tournent en parallèle sur différentes versions et plateformes.
Dans cet article, je couvre le Matrix de A à Z : syntaxe de base, combinaisons de filtres exclude/include, choix de la stratégie fail-fast, contrôle des ressources avec max-parallel. À la fin, un modèle complet de tests Node.js multi-versions prêt à copier. Environ 10 minutes de lecture, et vous pourrez basculer votre CI en exécution parallèle multi-versions.
Bases du Matrix — prise en main en 5 minutes
Le Matrix, en une phrase : vous écrivez un job, GitHub Actions le déploie automatiquement en plusieurs tâches parallèles.
Exemple concret. Vous définissez trois versions Node.js [18, 20, 22], et le Matrix crée trois tâches de test indépendantes, chacune sous Node 18, Node 20 ou Node 22. Ces trois tâches démarrent en même temps, s’exécutent en parallèle, sans se gêner.
La configuration minimale ressemble à ceci :
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci && npm test
Regardez surtout strategy.matrix. node-version est le nom de variable que vous choisissez ; le tableau [18, 20, 22] en liste les valeurs possibles. GitHub Actions parcourt ce tableau, assigne chaque valeur à matrix.node-version, puis crée une instance de job correspondante.
La syntaxe ${{ matrix.node-version }} référence la valeur courante. Au premier passage c’est 18, puis 20, puis 22.
Ma première question en l’utilisant : ces trois tâches sont-elles séquentielles ou parallèles ? Réponse : par défaut, parallèles. À chaque push, GitHub lance trois Runners en même temps. En pratique, tester trois versions en série prenait 15 minutes ; avec le Matrix, 5 minutes — les tâches tournent en parallèle, le temps total se réduit à celle qui est la plus lente.
Attention toutefois : le parallélisme consomme plus de minutes Runner. Trois tâches, c’est trois fois le temps facturé. Avec le quota gratuit (2 000 minutes par mois), un gros matrix peut vite l’épuiser. On reviendra sur max-parallel plus loin.
Filtres exclude/include — affiner la matrice de tests
Quand vous combinez plusieurs dimensions, le nombre de combinaisons du Matrix explose.
Trois versions Node [16, 18, 20], trois OS [ubuntu, windows, macos], ça fait 3 × 3 = 9 tâches. Ajoutez des suites de tests [unit, integration, e2e], et vous atteignez 27. Beaucoup pour une petite équipe, où les minutes Runner ont un coût.
Certaines combinaisons n’ont aucun sens. Node 16 est EOL (End of Life) : le tester sous Windows et macOS, c’est du temps perdu. C’est là qu’intervient exclude.
strategy:
matrix:
node-version: [16, 18, 20]
os: [ubuntu-latest, windows-latest, macos-latest]
exclude:
- node-version: 16
os: windows-latest
- node-version: 16
os: macos-latest
Avec exclude, vous listez les combinaisons à retirer. La config ci-dessus supprime Node 16 + Windows et Node 16 + macOS. De 9 tâches, on passe à 7 — 22 % de minutes Runner en moins.
include fait l’inverse : ajouter des combinaisons ou des variables supplémentaires. Par exemple, tester Node 23 en version expérimentale, uniquement sur Ubuntu :
strategy:
matrix:
node-version: [16, 18, 20]
os: [ubuntu-latest, windows-latest]
include:
- node-version: 23
os: ubuntu-latest
experimental: true
Détail important : include n’ajoute pas seulement des combinaisons, il peut aussi ajouter des variables. Ici, experimental: true n’existe que pour la tâche Node 23. Vous pouvez l’exploiter dans les étapes suivantes, par exemple pour ne pas bloquer tout le workflow si la version expérimentale échoue :
- name: Run tests
run: npm test
continue-on-error: ${{ matrix.experimental == true }}
Piège que j’ai rencontré : la priorité entre exclude et include. GitHub Actions exécute d’abord include pour ajouter des combinaisons, puis exclude pour en supprimer. Si vous incluez une combinaison puis l’excluez, elle n’apparaîtra pas. Inverser l’ordre dans votre tête peut donner un résultat inattendu.
En résumé :
exclude: supprimer les combinaisons inutiles, économiser temps et budgetinclude: ajouter des cas particuliers, avec des variables pour un traitement différencié
fail-fast et max-parallel — optimiser la stratégie parallèle
Le Matrix a un comportement par défaut facile à oublier : fail-fast: true.
Concrètement : dès qu’une tâche du matrix échoue, GitHub Actions annule les autres encore en cours. Dix tâches en parallèle, la 3ᵉ tombe après une minute — les sept restantes sont arrêtées immédiatement.
Est-ce une bonne chose ? Ça dépend du contexte.
Pour une vérification de PR, fail-fast est pertinent. Quelqu’un pousse du code, le test Node 18 casse — inutile d’attendre les autres versions. Retour rapide à l’auteur, gain de temps et de ressources.
En revanche, pour des tests Nightly ou une régression périodique, fail-fast peut gêner. Vous voulez un rapport complet : quelles versions posent problème, lesquelles passent. Si Node 18 échoue et stoppe tout, vous ignorez si Node 20 a le même bug. Là, configurez fail-fast: false.
strategy:
fail-fast: false
matrix:
node-version: [16, 18, 20]
max-parallel limite le nombre de tâches lancées simultanément. Par défaut, pas de limite : GitHub démarre autant de tâches que possible. Sur un gros matrix — disons 30 combinaisons — vous ne voulez peut-être pas tout consommer d’un coup.
strategy:
fail-fast: true
max-parallel: 6
matrix:
node-version: [16, 18, 20, 22]
test-suite: [unit, integration, e2e]
Ici, au maximum 6 tâches en parallèle. Les 30 combinaisons s’exécutent par lots de 6. Avantage : ressources Runner maîtrisées, quota préservé. Inconvénient : durée totale plus longue.
Tableau de décision simple selon le scénario :
| Scénario | fail-fast | max-parallel | Raison |
|---|---|---|---|
| Vérification PR | true | illimité | Retour rapide, arrêt dès le premier échec |
| Tests Nightly | false | 4-6 | Rapport complet, repérer tous les bugs |
| Gros matrix (>20 combinaisons) | true | 4 | Limiter la consommation, éviter d’épuiser le quota |
| Versions expérimentales | false | illimité | L’échec expérimental n’influence pas le jugement global |
En pratique, fail-fast: true par défaut suffit la plupart du temps. Passez à false quand vous avez besoin d’un diagnostic complet. max-parallel impacte peu les petits matrix (moins de 10 combinaisons) ; c’est sur les grands qu’il faut y réfléchir.
Rappel : max-parallel limite les tâches que GitHub Actions lance en même temps, pas le nombre de Runners physiques. Avec un self-hosted runner, une valeur trop basse crée des files d’attente et ralentit l’ensemble. Sur les Runners publics, ce réglage a du sens.
Modèle complet — pipeline de tests Node.js multi-versions
Jusqu’ici, des notions isolées. Cette section propose une configuration complète, prête à copier.
Ce modèle inclut :
- Trois versions Node (16, 18, 20)
- Deux suites de tests (unit et integration)
- Deux systèmes d’exploitation (Ubuntu et Windows)
- Mise en cache automatique pour accélérer l’installation des dépendances
- Exclusion des tests Windows sur Node 16 (version EOL)
name: Multi-Version Test Matrix
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
max-parallel: 6
matrix:
node-version: [16, 18, 20]
test-suite: [unit, integration]
os: [ubuntu-latest, windows-latest]
exclude:
- node-version: 16
os: windows-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run ${{ matrix.test-suite }} tests
run: npm run test:${{ matrix.test-suite }}
Quelques points clés :
runs-on: ${{ matrix.os }} : l’OS est dynamique ; chaque tâche choisit le Runner correspondant à sa combinaison matrix.
cache: 'npm' : fonction de cache intégrée à setup-node. Elle met en cache les dépendances npm selon le hash de package-lock.json ; au second passage, réutilisation directe sans retéléchargement. En pratique, plus de 50 % de temps gagné sur l’installation des dépendances.
fail-fast: false : volontairement à false ici, car l’objectif des tests multi-versions est de révéler tous les problèmes. Une version en échec ne doit pas arrêter les autres.
npm run test:${{ matrix.test-suite }} : en supposant que package.json définit test:unit et test:integration, le Matrix appelle chacune selon la combinaison.
Combien de tâches au total ?
3 versions × 2 tests × 2 OS = 12 tâches, moins Node 16 + Windows (2 suites de tests), soit 10 tâches restantes.
Mesures : sur plusieurs projets avec ce modèle et le cache, le CI est passé d’environ 25 minutes en série à 8 minutes. Le gain vient surtout du parallélisme et du cache des dépendances.
Pour des projets plus larges :
- Augmenter
max-parallel(8 ou 10) - Isoler les tests e2e dans un job dédié pour ne pas ralentir le reste
- Utiliser
continue-on-errorpour les versions expérimentales
Copiez ce modèle dans .github/workflows/test.yml, ajustez versions et noms de suites, et vous devriez être opérationnel.
Conclusion
En synthèse :
Le Matrix déploie automatiquement un job en plusieurs tâches parallèles. Configuration simple, effet direct — un push, trois versions en parallèle, le temps CI se réduit à la tâche la plus lente.
exclude/include permettent un contrôle fin. Quand les combinaisons explosent, exclude supprime l’inutile et économise plus de 20 % de minutes Runner. include complète avec des cas spéciaux et des variables pour un traitement différencié.
fail-fast vaut true par défaut : un échec stoppe les autres. Pour les PR, gardez la valeur par défaut ; pour les tests Nightly, passez à false pour un rapport complet. max-parallel plafonne la concurrence — utile surtout sur les grands matrix.
Le cache est incontournable. Une ligne cache: 'npm' dans setup-node peut diviser par deux le temps d’installation des dépendances.
Prochaine étape : copiez le modèle complet dans .github/workflows/ de votre projet, lancez d’abord les tests sur trois versions Node.js. Une fois validé, étendez progressivement aux multi-plateformes et multi-suites. Pour approfondir le cache, consultez l’article de la série « Stratégies de cache GitHub Actions : accélérer votre pipeline CI/CD par 5 ».
Configurez les tests multi-versions tôt. N’attendez pas un bug en production — cet écran blanc, j’y repense encore avec la migraine.
Configurer les tests multi-versions avec GitHub Actions Matrix
Construire de zéro un pipeline de tests parallèles multi-versions, couvrant Node.js 16/18/20 et les plateformes Ubuntu/Windows
⏱️ Estimated time: 15 min
- 1
Step 1: Créer le fichier workflow
Créez `.github/workflows/test.yml` à la racine du projet :
• Vérifiez la structure : `.github/workflows/`
• Nom de fichier libre ; `test.yml` ou `ci.yml` sont courants - 2
Step 2: Configurer les déclencheurs
Définissez quand lancer les tests :
```yaml
on:
push:
branches: [main]
pull_request:
```
• Push sur main déclenche les tests
• Création ou mise à jour d'une PR également - 3
Step 3: Définir la matrice Matrix
Configurez versions, plateformes et suites de tests :
```yaml
strategy:
fail-fast: false
max-parallel: 6
matrix:
node-version: [16, 18, 20]
test-suite: [unit, integration]
os: [ubuntu-latest, windows-latest]
exclude:
- node-version: 16
os: windows-latest
```
• fail-fast: false pour un rapport complet
• max-parallel: 6 pour plafonner la concurrence
• exclude pour écarter les combinaisons invalides - 4
Step 4: Configurer les étapes de test
Définissez l'exécution concrète :
```yaml
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm run test:${{ matrix.test-suite }}
```
• cache: 'npm' active le cache des dépendances
• Les variables matrix configurent dynamiquement la version - 5
Step 5: Pousser et vérifier
Déclenchez les tests par un push :
• Commit sur main ou ouverture d'une PR
• Consultez l'exécution parallèle dans l'onglet GitHub Actions
• Vérifiez que chaque version affiche un résultat normal
FAQ
Le Matrix consomme-t-il plus de minutes Runner ?
fail-fast : true ou false ?
• Vérification PR : true recommandé (échec rapide, retour immédiat)
• Tests Nightly : false recommandé (rapport complet)
• Versions expérimentales : false (ne pas fausser le jugement global)
La valeur par défaut est true ; suffisant pour la plupart des PR.
exclude et include : lequel s'exécute en premier ?
Quelle valeur pour max-parallel ?
• Petit matrix (<10 combinaisons) : pas besoin de le définir
• Matrix moyen (10-20 combinaisons) : 6-8
• Gros matrix (>20 combinaisons) : 4-6
Trop bas allonge l'attente totale ; trop haut peut épuiser d'un coup les ressources Runner.
Comment accélérer avec le cache dans un Matrix ?
Quels types de variables le Matrix accepte-t-il ?
• Tableaux : `[18, 20, 22]`
• Tableaux d'objets : `[{name: 'a', value: 1}, {name: 'b', value: 2}]`
• Chaînes : à ajouter via include
Privilégiez tableaux et tableaux d'objets pour la lisibilité.
8 min de lecture · Publié le: 8 avr. 2026 · Mis à jour le: 27 juil. 2026
Guide complet GitHub Actions
Si vous arrivez depuis la recherche, le plus rapide est de passer à l’article précédent ou suivant de cette série.
Précédent
Stratégie de cache GitHub Actions : accélérer le pipeline CI/CD par 5
Guide pratique de la stratégie de cache GitHub Actions : exemples complets de npm à Docker, bonnes pratiques de conception des clés de cache, comparaison des gains de performance. Maîtrisez le mécanisme de cache pour accélérer votre pipeline CI/CD par 5 et réduire les coûts de build.
Partie 3 sur 10
Suivant
Matrix GitHub Actions : guide pratique des tests parallèles multi-plateformes et multi-versions
Guide pratique du Matrix GitHub Actions : de la syntaxe de base à exclude/include, fail-fast et max-parallel, avec 5 modèles de workflow prêts à l'emploi pour générer des tests parallèles multi-plateformes et réduire de 60 %+ le code de configuration.
Partie 5 sur 10



Commentaires
Connectez-vous avec GitHub pour laisser un commentaire