Skip to main content
HomeTools

GitHub Actions Matrix Preview

Free

Paste a GitHub Actions workflow, a strategy: block or a matrix: block. The preview builds the cartesian product of the matrix variables, removes exclude partial matches, then applies include the way GitHub documents it: an entry extends every original combination it can join without overwriting an original value, and otherwise becomes a job of its own. It shows the job names, fail-fast and max-parallel, the count against the 256-job limit, and explains what each include and exclude entry did. Expressions such as fromJSON(...) are flagged, never guessed. Everything runs in your browser.

#ci-cd#github-actions#yaml#matrix#config

Matrix Preview

Client-Side Only

Expanded in this browser tab. The workflow is parsed and expanded by fixed rules taken from GitHub's matrix documentation. Nothing is uploaded, and expressions are reported rather than evaluated.

jobs.e2e

Jobs
15 / 256
Product
18
Excluded
4
Added by include
1
fail-fast
false
max-parallel
6

Findings (4)

  • Warning jobs.e2e.strategy.matrix.include[2]

    {os: windows-latest, browser: webkit} became a job of its own. The 2 combinations it would have joined were removed by exclude, which runs first. It has no shard, so matrix.shard is an empty string in this job.

  • Note jobs.e2e.strategy.matrix.include[0]

    {os: ubuntu-latest, browser: chromium, coverage: true} is merged into 2 combinations, because it does not name shard. To change one job, give a value for every matrix variable.

  • Note jobs.e2e.strategy.matrix.include[1]

    {os: ubuntu-latest, browser: chromium, node: 24} is merged into 2 combinations, because it does not name shard. To change one job, give a value for every matrix variable.

  • Note jobs.e2e.strategy.matrix.include[2]

    This combination matches an exclude entry, but include is processed after exclude, so it runs anyway.

What exclude and include did, in order

  1. exclude[0]
    {"os":"windows-latest","browser":"webkit"}removed 2 combinations
  2. exclude[1]
    {"os":"macos-latest","browser":"firefox"}removed 2 combinations
  3. include[0]
    {"os":"ubuntu-latest","browser":"chromium","coverage":true}merged into 2 jobs
  4. include[1]
    {"os":"ubuntu-latest","browser":"chromium","node":24}merged into 2 jobs
  5. include[2]
    {"os":"windows-latest","browser":"webkit"}added as a new job

Jobs in the order GitHub creates them

Expanded matrix for jobs.e2e: one row per job
#Job nameosbrowsershardcoveragenodeFrom
1e2e (ubuntu-latest, chromium, 1/2)ubuntu-latestchromium1/2true24product, extended by include[0], include[1]
2e2e (ubuntu-latest, chromium, 2/2)ubuntu-latestchromium2/2true24product, extended by include[0], include[1]
3e2e (ubuntu-latest, firefox, 1/2)ubuntu-latestfirefox1/2--product
4e2e (ubuntu-latest, firefox, 2/2)ubuntu-latestfirefox2/2--product
5e2e (ubuntu-latest, webkit, 1/2)ubuntu-latestwebkit1/2--product
6e2e (ubuntu-latest, webkit, 2/2)ubuntu-latestwebkit2/2--product
7e2e (windows-latest, chromium, 1/2)windows-latestchromium1/2--product
8e2e (windows-latest, chromium, 2/2)windows-latestchromium2/2--product
9e2e (windows-latest, firefox, 1/2)windows-latestfirefox1/2--product
10e2e (windows-latest, firefox, 2/2)windows-latestfirefox2/2--product
11e2e (macos-latest, chromium, 1/2)macos-latestchromium1/2--product
12e2e (macos-latest, chromium, 2/2)macos-latestchromium2/2--product
13e2e (macos-latest, webkit, 1/2)macos-latestwebkit1/2--product
14e2e (macos-latest, webkit, 2/2)macos-latestwebkit2/2--product
15e2e (windows-latest, webkit)windows-latestwebkit---added by include[2]
Frequently Asked Questions(click to expand)

Why did my include entry add a job instead of changing one?

An include entry joins every original combination it can join without changing one of that combination's matrix values. If it names a variable with a value no remaining combination has, such as experimental: true against experimental: [false], it becomes its own job. Combinations that exclude removed do not count, because exclude runs first.

Why did it change two jobs when I meant one?

An entry that leaves out a variable matches every value of that variable. To target one job, give the entry a value for every matrix variable.

Where do the job names come from?

GitHub does not document the default name. The preview follows the names GitHub gave jobs in public workflow runs: the job's name or ID, then the original matrix values in brackets, leaving out keys include added and empty strings. A name with a ${{ matrix.* }} expression is used as written.

Why does 3.10 show as 3.1?

Unquoted, 3.10 is a YAML number and 8.0 is the number 8. Quote version strings. The YAML Formatter shows how any value parses.

How many combinations do I actually need?

Usually fewer than the product. Choosing JUnit parameter rows without a matrix explosion covers picking boundary rows instead of crossing every dimension, and the guide to failing CI on flaky Playwright tests covers merging sharded reports before gating on them.