Matrix expressions in GitLab CI/CD
Version history
- Introduced in GitLab 18.5.
Matrix expressions enable dynamic job dependencies based on parallel:matrix
identifiers, to create 1:1 mappings between parallel:matrix
jobs.
Matrix expressions have some limitations compared to inputs expressions:
- Compile-time only: Identifiers are resolved when the pipeline is created, not during job execution.
- String replacement only: No complex logic or transformations.
- Matrix identifiers only: Cannot reference CI/CD variables or inputs.
Syntax
Matrix expressions use the $[[ matrix.IDENTIFIER ]]
syntax to reference a
parallel:matrix
identifier in job dependencies. For example:
needs:
- job: build
parallel:
matrix:
- OS: ['$[[ matrix.OS ]]']
ARCH: ['$[[ matrix.ARCH ]]']
needs:parallel:matrix
Matrix expressions in You can use matrix expressions to dynamically reference matrix identifiers in job dependencies, enabling 1:1 mappings between matrix jobs without manually specifying all combinations.
For example:
linux:build:
stage: build
script: echo "Building linux..."
parallel:
matrix:
- PROVIDER: [aws, gcp]
STACK: [monitoring, app1, app2]
linux:test:
stage: test
script: echo "Testing linux..."
parallel:
matrix:
- PROVIDER: [aws, gcp]
STACK: [monitoring, app1, app2]
needs:
- job: linux:build
parallel:
matrix:
- PROVIDER: ['$[[ matrix.PROVIDER ]]']
STACK: ['$[[ matrix.STACK ]]']
This example creates a 1:1 dependency mapping between all linux:build
and linux:test
jobs:
-
linux:test: [aws, monitoring]
depends onlinux:build: [aws, monitoring]
-
linux:test: [aws, app1]
depends onlinux:build: [aws, app1]
- The same applies for all 6
parallel:matrix
value combinations.
With matrix.
expressions you do not need to manually specify each matrix combination.
Matrix expressions reference identifiers from the current job's matrix configuration only.
parallel:matrix
configuration
Use YAML anchors to reuse You can use YAML anchors to reuse the parallel:matrix
configuration across multiple jobs with complex parallel:matrix
configuration and dependencies.
For example:
stages:
- compile
- test
- deploy
.build_matrix: &build_matrix
parallel:
matrix:
- OS: ["ubuntu", "alpine"]
ARCH: ["amd64", "arm64"]
VARIANT: ["slim", "full"]
compile_binary:
stage: compile
script:
- echo "Compiling for $OS-$ARCH-$VARIANT"
<<: *build_matrix
integration_test:
stage: test
script:
- echo "Testing $OS-$ARCH-$VARIANT"
<<: *build_matrix
needs:
- job: compile_binary
parallel:
matrix:
- OS: ['$[[ matrix.OS ]]']
ARCH: ['$[[ matrix.ARCH ]]']
VARIANT: ['$[[ matrix.VARIANT ]]']
deploy_artifact:
stage: deploy
script:
- echo "Deploying $OS-$ARCH-$VARIANT"
<<: *build_matrix
needs:
- job: integration_test
parallel:
matrix:
- OS: ['$[[ matrix.OS ]]']
ARCH: ['$[[ matrix.ARCH ]]']
VARIANT: ['$[[ matrix.VARIANT ]]']
This configuration creates 24 jobs: 8 jobs in each stage (2 OS
× 2 ARCH
× 2 VARIANT
combinations),
with 1:1 dependencies between stages.
Use a subset of values
You can combine matrix expressions with specific values to create selective subset of dependencies:
stages:
- prepare
- build
- test
.full_matrix: &full_matrix
parallel:
matrix:
- PLATFORM: ["linux", "windows", "macos"]
VERSION: ["16", "18", "20"]
.platform_only: &platform_only
parallel:
matrix:
- PLATFORM: ["linux", "windows", "macos"]
prepare_env:
stage: prepare
script:
- echo "Preparing $PLATFORM with Node.js $VERSION"
<<: *full_matrix
build_project:
stage: build
script:
- echo "Building on $PLATFORM"
needs:
- job: prepare_env
parallel:
matrix:
- PLATFORM: ['$[[ matrix.PLATFORM ]]']
VERSION: ["18"] # Only depend on Node.js 18 preparations
<<: *platform_only
In this example:
-
prepare_env
usesparallel:matrix
to create 9 jobs: 3PLATFORM
× 3VERSIONS
. -
build_project
useparallel:matrix
to create 3 jobs: 3PLATFORM
values only. - Each
build_project
job depends only on Node.js18
(VERSION
) for all platforms (PLATFORM
).
Alternatively, you can configure all the dependencies manually.