Stage 5 · Platform
Building Pipelines
Matrix Builds
Testing operating systems, language versions, architectures, and feature variants with fail-fast controls.
What Are Matrix Builds?
Matrix builds run the same job across multiple configurations — different operating systems, language versions, or feature flags. Instead of defining separate jobs for each combination, you define a matrix and the CI system generates jobs for every combination automatically.
This is essential for libraries and frameworks that support multiple platforms. A TypeScript library might need to test on Node 18, 20, and 22 across Ubuntu, Windows, and macOS — that is 9 combinations defined with a single matrix.
GitHub Actions Matrix
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [18, 20, 22]
exclude:
- os: windows-latest
node-version: 18
include:
- os: ubuntu-latest
node-version: 22
experimental: true
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: npm
- run: npm ci
- run: npm testThis creates 8 jobs (9 minus 1 excluded combination). The exclude removes Node 18 on Windows. The include adds an experimental flag to the Ubuntu/Node 22 combination. fail-fast: false ensures all jobs run even if one fails.
GitLab CI Parallel Jobs
test:
stage: test
parallel:
matrix:
- OS: ubuntu-22.04
NODE: ["18", "20", "22"]
- OS: macos-13
NODE: ["20", "22"]
- OS: windows-2022
NODE: ["20"]
image: node:${NODE}
script:
- npm ci
- npm test
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == "main"GitLab CI uses parallel: matrix to define combinations. Variables OS and NODE are available in the job. This creates 6 jobs total across the three OS/Node combinations.
Matrix Includes and Excludes
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
arch: [x64, arm64]
include:
- os: ubuntu-latest
arch: arm64
runner: ubuntu-latest-arm64
- os: macos-latest
arch: arm64
runner: macos-latest-xlarge
exclude:
- os: ubuntu-latest
arch: x64
runs-on: ${{ matrix.runner || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v4
- run: echo "Building for ${{ matrix.os }} ${{ matrix.arch }}"The matrix includes specific runner overrides for arm64 builds. The exclude removes the standard Ubuntu x64 combination. The runs-on expression uses the matrix runner if defined, otherwise falls back to ubuntu-latest.
Fail-Fast Behavior
By default, GitHub Actions cancels all matrix jobs when any job fails. This is called fail-fast. It saves resources but hides the full picture — you do not know which other configurations might also fail.
Set fail-fast: false to run all matrix jobs even if some fail. This gives you the complete picture of which configurations pass and which fail. It costs more in runner minutes but provides better signal.
Optimizing Matrix Builds
- Test minimum and maximum versions — if your library supports Node 18-22, test 18 and 22, not every version in between.
- Use conditional matrix entries — exclude combinations that are not supported or not relevant.
- Cache per matrix entry — use matrix-specific cache keys to avoid cache collisions between configurations.
- Parallelize within jobs — use matrix builds for cross-platform testing and parallel execution within each job.
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: [18, 20, 22]
test-suite: [unit, integration]
coverage: [false]
include:
- node-version: 20
test-suite: unit
coverage: true
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: npm
- run: npm ci
- run: npm test -- --suite=${{ matrix.test-suite }}
- name: Upload coverage
if: ${{ matrix.coverage }}
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/Only the Node 20 unit test job generates coverage reports. The matrix coverage variable controls which job uploads coverage. This avoids generating redundant coverage data across all matrix entries.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.