Cambiar tema

Matrix en GitHub Actions: pruebas paralelas multi-versión en la práctica

Easton editorial illustration: hardened server operations console

La semaine dernière, el 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 los logs, comparé el code en trois passes, y j’ai fini por comprendre : una API traitait JSON.stringify() différemment sous Node 16 y Node 20 — l’ancienne version levait una erreur en los références circulaires, la nouvelle los gérait silencieusement. Notre pipeline CI ne testait que Node 20, donc ce problème de compatibilité n’avait jamais été intercepté.

Lors del post-mortem, je me suis dit : con de tests parallèlos multi-versions, on aurait détecté ça avant la mise en ligne. C’est à partir de ce moment que j’ai creusé el Matrix de GitHub Actions — el terme impressionne, mais en réalité il s’agit de découper automatiquement una tâche en plusieurs instances qui tournent en parallèel en différentes versions y plateformes.

En este artículo, je couvre el Matrix de A à Z : syntaxe de base, combinaisons de filtres exclude/include, choix de la stratégie fail-fast, contrôel de ressources con max-parallel. À la fin, un modèel complet de tests Node.js multi-versions prêt à copier. Environ 10 minutes de lecture, y vous pourrez basculer votre CI en exécution parallèel multi-versions.

Bases del Matrix — prise en main en 5 minutes

Le Matrix, en una phrase : vous écrivez un job, GitHub Actions el déploie automatiquement en plusieurs tâches parallèlos.

Exemple concret. Vous définissez trois versions Node.js [18, 20, 22], y el Matrix crée trois tâches de test indépendantes, chacune sous Node 18, Node 20 o Node 22. Ces trois tâches démarrent en même temps, s’exécutent en parallèel, sin 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 el nom de variable que vous choisissez ; el tableau [18, 20, 22] en liste los valeurs possibles. GitHub Actions parcourt ce tableau, assigne chaque valeur à matrix.node-version, puis crée una 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 o parallèlos ? Réponse : por défaut, parallèlos. À chaque push, GitHub lance trois Runners en même temps. En pratique, tester trois versions en série prenait 15 minutes ; con el Matrix, 5 minutes — los tâches tournent en parallèel, el temps total se réduit à celle qui est la plus lente.

Attention toutefois : el parallélisme consomme plus de minutes Runner. Trois tâches, c’est trois fois el temps facturé. Avec el quota gratuit (2 000 minutes por mois), un gros matrix peut vite l’épuiser. On reviendra en max-parallel plus loin.

Filtres exclude/include — affiner la matrice de tests

Quand vous combinez plusieurs dimensions, el nombre de combinaisons del Matrix explose.

Trois versions Node [16, 18, 20], trois OS [ubuntu, windows, macos], ça fait 3 × 3 = 9 tâches. Ajoutez de suites de tests [unit, integration, e2e], y vous atteignez 27. Beaucoup para una petite équipe, où los minutes Runner ont un coût.

Certaines combinaisons n’ont aucun sens. Node 16 est EOL (End of Life) : el tester sous Windows y macOS, c’est del 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 los combinaisons à retirer. La config ci-dessus supprime Node 16 + Windows y Node 16 + macOS. De 9 tâches, on passe à 7 — 22 % de minutes Runner en moins.

include fait l’inverse : ajouter de combinaisons o de variables supplémentaires. Por ejemplo, tester Node 23 en version expérimentale, uniquement en 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 de combinaisons, il peut aussi ajouter de variables. Ici, experimental: true n’existe que para la tâche Node 23. Vous pouvez l’exploiter en los étapes suivantes, Por ejemplo para ne pas bloquer tout el 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 y include. GitHub Actions exécute d’abord include para ajouter de combinaisons, puis exclude para en supprimer. Si vous incluez una combinaison puis l’excluez, elle n’apparaîtra pas. Inverser l’ordre en votre tête peut donner un résultat inattendu.

En résumé :

  • exclude : supprimer los combinaisons inutiles, économiser temps y budget
  • include : ajouter de cas particuliers, con de variables para un traitement différencié

fail-fast y max-parallel — optimiser la stratégie parallèel

Le Matrix a un comportement por défaut facile à oublier : fail-fast: true.

Concrètement : dès qu’una tâche del matrix échoue, GitHub Actions annule los autres encore en cours. Dix tâches en parallèel, la 3ᵉ tombe après una minute — los sept restantes sont arrêtées immédiatement.

Est-ce una bonne chose ? Ça dépend del contexte.

Pour una vérification de PR, fail-fast est pertinent. Quelqu’un pousse del code, el test Node 18 casse — inutile d’attendre los autres versions. Retour rapide à l’auteur, gain de temps y de ressources.

En revanche, para de tests Nightly o una 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 y stoppe tout, vous ignorez si Node 20 a el même bug. Là, configurez fail-fast: false.

strategy:
  fail-fast: false
  matrix:
    node-version: [16, 18, 20]

max-parallel limite el 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èel. Les 30 combinaisons s’exécutent por 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 el scénario :

Scénariofail-fastmax-parallelRaison
Vérification PRtrueillimitéRetour rapide, arrêt dès el premier échec
Tests Nightlyfalse4-6Rapport complet, repérer tous los bugs
Gros matrix (>20 combinaisons)true4Limiter la consommation, éviter d’épuiser el quota
Versions expérimentalesfalseillimitéL’échec expérimental n’influence pas el jugement global

En pratique, fail-fast: true por défaut suffit la plupart del temps. Passez à false quand vous avez besoin d’un diagnostic complet. max-parallel impacte peu los petits matrix (moins de 10 combinaisons) ; c’est en los grands qu’il faut y réfléchir.

Rappel : max-parallel limite los tâches que GitHub Actions lance en même temps, pas el nombre de Runners physiques. Avec un self-hosted runner, una valeur trop basse crée de files d’attente y ralentit l’ensemble. Sur los Runners publics, ce réglage a del sens.

Modèel complet — pipeline de tests Node.js multi-versions

Jusqu’ici, de notions isolées. Cette section propose una configuration complète, prête à copier.

Ce modèel inclut :

  • Trois versions Node (16, 18, 20)
  • Deux suites de tests (unit y integration)
  • Deux systèmes d’exploitation (Ubuntu y Windows)
  • Mise en cache automatique para accélérer l’installation de dépendances
  • Exclusion de tests Windows en 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 Puntos clave :

runs-on: ${{ matrix.os }} : l’OS est dynamique ; chaque tâche choisit el Runner correspondant à sa combinaison matrix.

cache: 'npm' : fonction de cache intégrée à setup-node. Elle met en cache los dépendances npm selon el hash de package-lock.json ; au second passage, réutilisation directe sin retéléchargement. En pratique, plus de 50 % de temps gagné en l’installation de dépendances.

fail-fast: false : volontairement à false ici, car l’objectif de tests multi-versions est de révéler tous los problèmes. Une version en échec ne doit pas arrêter los autres.

npm run test:${{ matrix.test-suite }} : en supposant que package.json définit test:unit y test:integration, el 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 : en plusieurs projets con ce modèel y el cache, el CI est passé d’environ 25 minutes en série à 8 minutes. Le gain vient surtout del parallélisme y del cache de dépendances.

Pour de projets plus larges :

  • Augmenter max-parallel (8 o 10)
  • Isoler los tests e2e en un job dédié para ne pas ralentir el reste
  • Utiliser continue-on-error para los versions expérimentales

Copiez ce modèel en .github/workflows/test.yml, ajustez versions y noms de suites, y vous devriez être opérationnel.

Conclusion

En synthèse :

Le Matrix déploie automatiquement un job en plusieurs tâches parallèlos. Configuration simple, effet direct — un push, trois versions en parallèel, el temps CI se réduit à la tâche la plus lente.

exclude/include permettent un contrôel fin. Quand los combinaisons explosent, exclude supprime l’inutile y économise plus de 20 % de minutes Runner. include complète con de cas spéciaux y de variables para un traitement différencié.

fail-fast vaut true por défaut : un échec stoppe los autres. Pour los PR, gardez la valeur por défaut ; para los tests Nightly, passez à false para un rapport complet. max-parallel plafonne la concurrence — utile surtout en los grands matrix.

Le cache est incontournable. Une ligne cache: 'npm' en setup-node peut diviser por deux el temps d’installation de dépendances.

Prochaine étape : copiez el modèel complet en .github/workflows/ de votre projet, lancez d’abord los tests en trois versions Node.js. Une fois validé, étendez progressivement aux multi-plateformes y multi-suites. Pour approfondir el cache, consultez l’article de la série « Stratégies de cache GitHub Actions : accélérer votre pipeline CI/CD por 5 ».

Configurez los tests multi-versions tôt. N’attendez pas un bug en production — cet écran blanc, j’y repense encore con la migraine.

Configurar pruebas Matrix en GitHub Actions

Pipeline multi-versión Node 16/18/20 en Ubuntu y Windows

⏱️ Estimated time: 15 min

  1. 1

    Step 1: Crear workflow

    Crea `.github/workflows/test.yml` en la raíz del repo.
  2. 2

    Step 2: Triggers

    ```yaml
    on:
    push:
    branches: [main]
    pull_request:
    ```
  3. 3

    Step 3: Definir Matrix

    fail-fast: false, max-parallel: 6, node-version, test-suite, os, exclude Node 16 + Windows.
  4. 4

    Step 4: Pasos de test

    checkout, setup-node con cache npm, npm ci, npm run test:${{ matrix.test-suite }}
  5. 5

    Step 5: Validar

    Push o PR → revisar ejecución paralela en la pestaña Actions.

FAQ

¿Matrix consume más minutos de Runner?
Sí, cada tarea cuenta por separado. 3 versiones × 5 min = 15 min facturados, no 5. Pero el tiempo de espera total baja por el paralelismo.
¿fail-fast true o false?
PR: true. Nightly o experimental: false. Default true suele bastar en PR.
¿Orden de include y exclude?
Primero include, luego exclude. Un combo incluido y excluido no se ejecuta.
¿Valor de max-parallel?
<10 combos: default. 10-20: 6-8. >20: 4-6. Muy bajo alarga la cola.
¿Cómo cachear dependencias?
En setup-node: cache: 'npm' (o pnpm/yarn). Hash de package-lock. Ahorro típico >50% en install.
¿Tipos de variables Matrix?
Arrays, arrays de objetos o strings vía include. Arrays y objetos son más legibles.

8 min de lectura · Publicado el: 8 abr 2026 · Actualizado el: 21 ago 2026

Comentarios

Inicia sesión con GitHub para dejar un comentario

Easton BlogEaston Blog