Jenkins declarative pipeline: Sequential execution of an axis of a matrix-build

2 min read 06-10-2024
Jenkins declarative pipeline: Sequential execution of an axis of a matrix-build


Demystifying Matrix Builds and Sequential Execution in Jenkins Declarative Pipelines

Problem: You're working with a Jenkins declarative pipeline and need to run a series of tests on different configurations. You want to execute these configurations sequentially, one after the other, rather than running them in parallel.

Simplified: Imagine you need to test your software on various operating systems (Windows, Linux, macOS) and different browser versions (Chrome, Firefox, Safari). A matrix build lets you create these combinations and test them, but you want to run the Windows tests, then the Linux tests, and finally the macOS tests, rather than running them all at the same time.

Scenario and Code:

Let's assume you have a Jenkinsfile with a matrix build definition like this:

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                echo 'Building...'
            }
        }
        stage('Test') {
            matrix {
                axes {
                    axis {
                        name 'OS'
                        values 'Windows', 'Linux', 'macOS'
                    }
                    axis {
                        name 'Browser'
                        values 'Chrome', 'Firefox'
                    }
                }
                stages {
                    stage('Setup') {
                        steps {
                            echo "Setting up for ${OS} and ${Browser}..."
                        }
                    }
                    stage('Run Tests') {
                        steps {
                            echo "Running tests on ${OS} with ${Browser}..."
                        }
                    }
                }
            }
        }
    }
}

This code will create a matrix build with six combinations:

  • Windows, Chrome
  • Windows, Firefox
  • Linux, Chrome
  • Linux, Firefox
  • macOS, Chrome
  • macOS, Firefox

By default, these combinations run concurrently.

The Solution: Sequential Execution with 'parallel' and 'node'

To achieve sequential execution of each operating system's tests, we can leverage the parallel and node directives within the matrix definition:

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                echo 'Building...'
            }
        }
        stage('Test') {
            matrix {
                axes {
                    axis {
                        name 'OS'
                        values 'Windows', 'Linux', 'macOS'
                    }
                    axis {
                        name 'Browser'
                        values 'Chrome', 'Firefox'
                    }
                }
                stages {
                    stage('Setup') {
                        steps {
                            echo "Setting up for ${OS} and ${Browser}..."
                        }
                    }
                    stage('Run Tests') {
                        steps {
                            echo "Running tests on ${OS} with ${Browser}..."
                        }
                    }
                }
            }
            // Sequential execution
            parallel {
                stage('Windows Tests') {
                    node('windows') {
                        // Filter for Windows OS combinations
                        matrix {
                            axes {
                                axis {
                                    name 'Browser'
                                    values 'Chrome', 'Firefox'
                                }
                            }
                            stages {
                                stage('Setup') {
                                    steps {
                                        echo "Setting up for Windows and ${Browser}..."
                                    }
                                }
                                stage('Run Tests') {
                                    steps {
                                        echo "Running tests on Windows with ${Browser}..."
                                    }
                                }
                            }
                        }
                    }
                }
                stage('Linux Tests') {
                    node('linux') {
                        // Filter for Linux OS combinations
                        matrix {
                            axes {
                                axis {
                                    name 'Browser'
                                    values 'Chrome', 'Firefox'
                                }
                            }
                            stages {
                                stage('Setup') {
                                    steps {
                                        echo "Setting up for Linux and ${Browser}..."
                                    }
                                }
                                stage('Run Tests') {
                                    steps {
                                        echo "Running tests on Linux with ${Browser}..."
                                    }
                                }
                            }
                        }
                    }
                }
                stage('macOS Tests') {
                    node('macos') {
                        // Filter for macOS OS combinations
                        matrix {
                            axes {
                                axis {
                                    name 'Browser'
                                    values 'Chrome', 'Firefox'
                                }
                            }
                            stages {
                                stage('Setup') {
                                    steps {
                                        echo "Setting up for macOS and ${Browser}..."
                                    }
                                }
                                stage('Run Tests') {
                                    steps {
                                        echo "Running tests on macOS with ${Browser}..."
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

This code snippet leverages the following concepts:

  1. parallel: Executes the stages within the parallel block concurrently.
  2. node: Specifies a particular agent (e.g., 'windows', 'linux', 'macos') where the stage should run. This ensures that the stages within each operating system are executed sequentially on the appropriate agent.
  3. Filtering within the matrix: We use the matrix block within each node to filter the combinations based on the operating system. This ensures we only execute the desired combinations for each operating system.

Benefits of Sequential Execution:

  • Dependency Management: If your tests depend on a shared resource or state, sequential execution helps avoid conflicts and ensures a clean execution environment for each OS.
  • Test Analysis: Analyzing test results becomes easier when executed sequentially.
  • Logging and Debugging: Debugging becomes simpler as you have a clear timeline of each OS's execution.

Conclusion:

By utilizing the parallel and node directives, we can easily achieve sequential execution of an axis within a matrix build in Jenkins declarative pipelines. This provides a flexible and powerful way to manage complex test scenarios and ensures your tests are run in a controlled and organized manner. Remember to define your agents (e.g., 'windows', 'linux', 'macos') in Jenkins to ensure the pipeline correctly assigns the stages to the appropriate agents.