Matrix expressions in GitLab CI/CD
On GitLab Self-Managed, by default this feature is not available. To make it available, an administrator can enable the feature flag named ci_matrix_expressions
.
On GitLab.com and GitLab Dedicated, this feature is not available.
This feature is not ready for production use.
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 ]]']
Matrix expressions in needs:parallel:matrix
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.
Use YAML anchors to reuse parallel:matrix
configuration
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.