Create a Matrix-like flow with Pipeline

Article ID:115000088431
2 minute readKnowledge base

Issue

  • I would like to create a Pipeline that runs parallel task in the same way a Matrix job does

Environment

Resolution

You can run a pipeline that mocks the behavior of a Matrix jobs. You can trivially run the different combinations in parallel and express the structure like a Matrix.

In terms of Visualization however, Pipeline Stage View is not able to display the result in a Matrix structure. There are long standing improvement issues about this: JENKINS-27395 and JENKINS-33185.

Blue Ocean Plugin offer better visualization capabilities and is the way forward.

Example with "Flat" structure:

The following pipeline has 2 axes: Nodes and JDKs. Therefore there should be 4 tasks running in parallel:

  • osx-agent-1 / jdk7: Runs on node "osx-agent-1" and use the tool "jdk7"

  • osx-agent-1 / jdk8: Runs on node "osx-agent-1" and use the tool "jdk8"

  • osx-agent-2 / jdk7: Runs on node "osx-agent-2" and use the tool "jdk7"

  • osx-agent-2 / jdk8: Runs on node "osx-agent-2" and use the tool "jdk8"

def axisNode = ["osx-agent-1","osx-agent-2"]
def axisTool = ["jdk7","jdk8"]
def tasks = [:]

stage("Before") {
    node {
        echo "before"
    }
}

for(int i=0; i< axisNode.size(); i++) {
    def axisNodeValue = axisNode[i]
    for(int j=0; j< axisTool.size(); j++) {
        def axisToolValue = axisTool[j]
        tasks["${axisNodeValue}/${axisToolValue}"] = {
            node(axisNodeValue) {
                def javaHome = tool axisToolValue
                println "Node=${env.NODE_NAME}"
                println "Java=${javaHome}"
            }
        }
    }
}

stage ("Matrix") {
    parallel tasks
}

stage("After") {
    node {
        echo "after"
    }
}

Note that the "Matrix stage" is a simple parallel task and the matrix structure can be part of a bigger pipeline (as shown by this pipeline that is creating stages before and after the matrix structure).

Visualization in Blue Ocean

blueocean matrix pipeline flat

Example with "Nested" structure:

Another example is to run Nested Parallel tasks. The following pipeline do the exact same things except that we create a nest parallel tasks:

  • "osx-agent-1": Parent stage

    • osx-agent-1 / jdk7: Runs on node "osx-agent-1" and use the tool "jdk7"

    • osx-agent-1 / jdk8: Runs on node "osx-agent-1" and use the tool "jdk8"

  • "osx-agent-2": Parent stage

    • osx-agent-2 / jdk7: Runs on node "osx-agent-2" and use the tool "jdk7"

    • osx-agent-2 / jdk8: Runs on node "osx-agent-2" and use the tool "jdk8"

def axisNode = ["osx-agent-1","osx-agent-2"]
def axisTool = ["jdk7","jdk8"]
def tasks = [:]

stage("Before") {
    node {
        echo "before"
    }
}

for(int i=0; i< axisNode.size(); i++) {
    def axisNodeValue = axisNode[i]
    def subTasks = [:]
    for(int j=0; j< axisTool.size(); j++) {
        def axisToolValue = axisTool[j]
        subTasks["${axisNodeValue}/${axisToolValue}"] = {
            def javaHome = tool axisToolValue
            println "Node=${env.NODE_NAME}"
            println "Java=${javaHome}"
        }
    }
    tasks["${axisNodeValue}"] = {
        node(axisNodeValue) {
            parallel subTasks
        }
    }
}

stage ("Matrix") {
    parallel tasks
}

stage("After") {
    node {
        echo "after"
    }
}

Visualization in Blue Ocean

blueocean matrix pipeline nested
Improvement for the visualization of Nested stages is an open issue, see JENKINS-38442
This article is part of our Knowledge Base and is provided for guidance-based purposes only. The solutions or workarounds described here are not officially supported by CloudBees and may not be applicable in all environments. Use at your own discretion, and test changes in a safe environment before applying them to production systems.