C.W.K.
Stream
Lesson 10 of 14 · published

Dynamic Matrix

~12 min · matrix, dynamic, fromJSON

Level 0Apprentice
0 XP0/101 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

Compute the matrix at runtime

Sometimes the matrix can't be hardcoded — it depends on what changed in the PR, what packages exist in the monorepo, what tests are tagged, or what platforms a config file declares. Dynamic matrix computes the matrix in a setup job and feeds it to a downstream matrix job.

The pattern

  1. Setup job inspects the repo (changed files, package list, etc.).
  2. Emits a JSON array as a job output.
  3. Downstream matrix job sets strategy.matrix.<key>: ${{ fromJSON(needs.setup.outputs.<key>) }}.
  4. Each matrix cell runs the actual work.

Real examples

  • Monorepo — only test packages whose code changed in this PR.
  • Cross-platform builder — read platforms.json from the repo and run a matrix cell per entry.
  • Tag-based — list of test groups marked in the test framework, expanded into matrix cells.

Code

Monorepo — only test changed packages·yaml
jobs:
  detect:
    runs-on: ubuntu-latest
    outputs:
      packages: ${{ steps.changed.outputs.packages }}
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - id: changed
        run: |
          # Find unique top-level package directories changed in this PR
          base=${{ github.event.pull_request.base.sha || 'HEAD~1' }}
          pkgs=$(git diff --name-only "$base" | awk -F/ '/^packages\//{print $2}' | sort -u)
          json=$(echo "$pkgs" | jq -R . | jq -sc .)
          echo "packages=$json" >> $GITHUB_OUTPUT

  test:
    needs: detect
    if: needs.detect.outputs.packages != '[]'
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        package: ${{ fromJSON(needs.detect.outputs.packages) }}
    steps:
      - uses: actions/checkout@v4
      - run: cd packages/${{ matrix.package }} && npm ci && npm test

External links

Exercise

If you have a monorepo, build a 'changed packages' detection job and feed it into a matrix. Open a PR that touches only one package and confirm only that cell runs.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.