Implementing Jenkins Matrix Projects with Scripted and Declarative Pipelines
This article explains how to configure Jenkins Matrix projects to run parallel builds across multiple platforms and browsers using both scripted and declarative pipeline syntax, including label setup, axis generation, task parallelization, and user‑driven selection of combinations.
The Matrix project concept allows independent builds to run in parallel, making it easy to test the same code against different Java versions, platforms, or browsers. By assigning labels to nodes (e.g., os:linux && browser:firefox ), Jenkins can select appropriate agents for each axis.
First, define the matrix axes as a map and generate the Cartesian product while filtering unsupported combinations:
// Define a map storing platform and browser information
Map matrix_axes = [
PLATFORM: ['linux', 'windows', 'mac'],
BROWSER: ['firefox', 'chrome', 'safari', 'edge']
]
@NonCPS
List getMatrixAxes(Map matrix_axes) {
List axes = []
matrix_axes.each { axis, values ->
List axisList = []
values.each { value ->
axisList << [(axis): value]
}
axes << axisList
}
// calculate cartesian product
axes.combinations()*.sum()
}
// Filter out invalid combinations (Safari on Linux, Edge not on Windows)
List axes = getMatrixAxes(matrix_axes).findAll { axis ->
!(axis['BROWSER'] == 'safari' && axis['PLATFORM'] == 'linux') &&
!(axis['BROWSER'] == 'edge' && axis['PLATFORM'] != 'windows')
}Next, create a parallel task map where each axis is converted into environment variables and a node label, then run build and test stages on the selected agent:
Map tasks = [failFast: false]
for (int i = 0; i < axes.size(); i++) {
Map axis = axes[i]
List axisEnv = axis.collect { k, v -> "${k}=${v}" }
String nodeLabel = "os:${axis['PLATFORM']} && browser:${axis['BROWSER']}"
tasks[axisEnv.join(', ')] = {
node(nodeLabel) {
withEnv(axisEnv) {
stage('Build') {
echo nodeLabel
sh 'echo Do Build for ${PLATFORM} - ${BROWSER}'
}
stage('Test') {
echo nodeLabel
sh 'echo Do Test for ${PLATFORM} - ${BROWSER}'
}
}
}
}
}
stage('Matrix builds') {
parallel(tasks)
}To let users choose specific platform‑browser combinations at runtime, an input step can be added:
Map response = [:]
stage('Choose combinations') {
response = input(
id: 'Platform',
message: 'Customize your matrix build.',
parameters: matrix_axes.collect { key, options ->
choice(
choices: ['all'] + options.sort(),
description: "Choose a single ${key.toLowerCase()} or all to run tests.",
name: key
)
}
)
}Finally, the same matrix can be expressed in a declarative pipeline (Jenkins 1.5.0‑beta1 or later) using the matrix block, which lists the axes and runs shared build and test stages for each combination:
pipeline {
agent none
stages {
stage('BuildAndTest') {
matrix {
agent any
axes {
axis { name 'PLATFORM'; values 'linux', 'windows', 'mac' }
axis { name 'BROWSER'; values 'firefox', 'chrome', 'safari', 'edge' }
}
stages {
stage('Build') { steps { echo "Do Build for ${PLATFORM} - ${BROWSER}" } }
stage('Test') { steps { echo "Do Test for ${PLATFORM} - ${BROWSER}" } }
}
}
}
}
}The article also includes screenshots illustrating node labels, matrix configuration, and the final pipeline view, as well as a brief FAQ about permission issues that may arise during execution.
DevOps Cloud Academy
Exploring industry DevOps practices and technical expertise.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.