Матрицы: тестируем на нескольких версиях

Один job — десятки комбинаций версий и платформ без копипасты.

Matrix — механизм, который размножает один job по комбинациям заданных значений, запуская их параллельно.

Зачем нужна матрица

Библиотека должна работать на Node 18 и 20, приложение — на Linux и Windows. Писать четыре почти одинаковых job — боль. Матрица описывает варианты один раз, а GitHub сам создаёт по job на каждую комбинацию.

Базовый пример

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: [18, 20, 22]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - run: npm ci
      - run: npm test

Это создаст три параллельных job: для Node 18, 20 и 22. Значение текущей версии доступно как ${{ matrix.node }}.

Несколько измерений

Можно перемножать оси. Здесь 3 версии × 2 ОС = 6 job:

strategy:
  matrix:
    node: [18, 20, 22]
    os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}

fail-fast и max-parallel

По умолчанию fail-fast: true — если одна комбинация упала, остальные отменяются. Иногда хочется увидеть результат всех вариантов:

strategy:
  fail-fast: false
  max-parallel: 2
  matrix:
    node: [18, 20, 22]

max-parallel ограничивает число одновременных job (бережёт лимит минут).

include и exclude

exclude убирает ненужную комбинацию, include добавляет особую:

strategy:
  matrix:
    node: [18, 20]
    os: [ubuntu-latest, windows-latest]
    exclude:
      - node: 18
        os: windows-latest      # эту пару не запускаем
    include:
      - node: 22
        os: ubuntu-latest
        experimental: true       # добавили особый вариант с доп. полем

Итог

  • Матрица размножает job по комбинациям значений и гоняет их параллельно.
  • Текущее значение оси доступно как ${{ matrix.имя }}.
  • fail-fast, max-parallel, include/exclude точно настраивают набор и поведение.
Проверьте себя
1. Сколько job создаст матрица с node: [18, 20] и os: [ubuntu-latest, windows-latest] без exclude?
A2
B4
C1
D8
2. Что делает fail-fast: false в стратегии матрицы?
AУскоряет сборку вдвое
BНе отменяет остальные комбинации, если одна упала — увидите результат всех
CОтключает тесты
DЗапускает job последовательно
3. Как внутри шагов получить текущее значение оси матрицы node?
A$NODE_VERSION
B${{ matrix.node }}
Cmatrix.get('node')
D${{ env.node }}
Поддержать проект