Jenkins in practice – combinations of parallel and generic stages

Jenkins is a powerful tool that allows you to automate processes that would otherwise have to be done manually. So it’s good to use it and use its capabilities to make your work easier. In this article we will show you how to automate repetitive tasks in various ways. Some seemingly simple Jenkins solutions and […]

Jenkins is a powerful tool that allows you to automate processes that would otherwise have to be done manually. So it’s good to use it and use its capabilities to make your work easier. In this article we will show you how to automate repetitive tasks in various ways.

Some seemingly simple Jenkins solutions and functions may cause some difficulties when used simultaneously. Dynamically generated stages (stage) and parallel stages may be problematic. That is why today we will show how to create several types of streams (pipeline) using different combinations of these functionalities, present their pros and cons and answer the question whether it is worth using them at all.

Parallel stages

Let’s start with the easier topic, i.e. the parallelization of our stages. As the name suggests, this allows us to carry out many stages simultaneously:

pipeline {
    agent any
    stages {
        stage("tests") {
            parallel{
                stage("test1"){
                    steps{
                        sh "echo test1"
                    }
                }
                 stage("test2"){
                    steps{
                        sh "echo test2"
                    }
                }
            }
        }
    }
}

In the Blue Ocean view it looks like this:

Etapy równoległe

Parallel stages in this way can operate on the same agent and in the same work area (as above). We can also define a separate agent for each of them:

pipeline {
    agent none
    stages {
        stage("tests") {
	        parallel{
                stage("test1"){
                    agent {
                        label "test-agent1"
                    }
                    steps{
                        sh "echo test1"
                    }
                }
                 stage("test2"){
                    agent {
                        label "test-agent1"
                    }
                    steps{
                        sh "echo test2"
                    }
                }
            }
        }
    }
}

We also have the option of setting our stages so that some of them are still sequential or put inside one of the parallel stages the next ones run one by one:

Etapy równoległe sekwencja

Examples of using parallel stages:

  • performing many unrelated tests
  • performing the same test scenarios on many systems simultaneously.

Disadvantages of parallel stages:

– slightly reduces the transparency of streams
+ significantly reduces the time it takes to carry out various processes (such as tests, for example) if they consist of independent stages.

Matrix

The Matrix allows us to define a matrix of stages run in parallel. It is an ideal tool when we need to perform the same operations on many systems and with different configurations.

When defining the matrix, we start by defining the axis:

matrix {
                agent {label "${DISTRO}"}
                axes {
                    axis {
                        name 'DISTRO'
                        values 'eurolinux', 'centos', 'scientific'
                    }
                    axis {
                        name 'BROWSER'
                        values 'firefox', 'chrome', 'opera'
                    }
                }
                stages {
                    stage("Test") {
                        steps {
                            echo "Do Build for ${DISTRO} - ${BROWSER}"
                        }
                    }
                }
            }

We can define any number of axes. As a result, we get every possible combination of the values they contain:

Macierz

 

As you can see, we can easily get functionality that would otherwise require multiple text swearing. This solution allows you to control the agent at which the stage is to be started, depending on the values selected on the axis. It also allows you to exclude selected combinations of values using excludes and much more. However, there are many possibilities. To read them, we encourage you to use documentation ;-)

Matrix pros and cons:

– due to the lack of an easy way to dynamically change the names of stages, the matrix becomes not very transparent, and to find the right variant, we need to hover over it with the pointer (mouse) to display its name.
+ the code is legible and clean
+ allows you to easily add successive stages.

Generic stages

Sometimes, however, we need more control over the course of stages or there are so many that the use of matrices becomes impractical. We can then generate such stages from the list. This requires the use of scripts and is as follows:

def OS_list = ["linux", "windows", "IOS", "android"]

pipeline {
    agent eny
    stages {
        stage("Test all"){
            steps{
                script{
                    OS_list.each{ 
                        stage("$it"){
                            echo "$it"
                        }
                    }
                }
            }
        }
    }
}

Etapy generyczne

Parallelization of generic stages

Creating such a stream is unfortunately not so easy. We must remember that parallel inside the buckle script behaves differently than the one that occurs in an ordinary declarative stream. In this case, he accepts the map. The keys will be displayed as the branch name, and the values should be the stages that need to be parallelized. At this point, we recommend experimenting as ways to create a map in groovy’m there is a lot and different combinations give different effects. Below is an example of generic parallel stages:

def OS_list = ["linux", "windows", "IOS", "android"]

pipeline {
    agent none
    stages {
        stage("Test all"){
            steps{
                script{ 
                    parallel OS_list.collectEntries { OS -> [ "${OS}": {
                            stage("$OS") {
                                echo "$OS"
                            }
                        }]
                    }
                }
            }
        }
    }
}

Zrównoleglanie etapów generycznych:

This solution can be freely nested and parallelized:

def OS_list = ["linux", "windows", "IOS", "android"]
def BROWSERS = ["chrome", "firefox", "opera", "edge"]

pipeline {
    agent none
    stages {
        stage("Test all"){
            steps{
                script{ 
                    parallel OS_list.collectEntries { OS -> [ "${OS}": {
                        stage("$OS") {
                            BROWSERS.each{ 
                                stage("$it"){
                                    echo "$it"
                                }
                            }
                        }
                    }]}
                }
            }
        }
    }
}

Zrównoleglanie etapów generycznych

Pros and cons of generic stages:

– requires the use of scripts inside the creek, which may reduce code transparency
– the use of scripts deprives us of the possibility of using some functionalities of the declarative stream, such as when
– no solution of the type excludes forces us to implement complicated mechanisms or the so-called ifologji
+ gives great freedom
+ we can freely nest stages
+ allows you to easily add successive stages.

Summary

Comparing the above solutions, we can see that the cleanest solution, due to the code, is to use a matrix. Unfortunately, this solution does not generate a stream that is transparent in browsing. The dynamically generated stages look much better, but require us to use scripts, minimal language skills groovy and deprives us of the possibility of using some functionalities. We hope that this material will help you in the future design and creation of jenkin streams.

blank Authors

The blog articles are written by people from the EuroLinux team. We owe 80% of the content to our developers, the rest is prepared by the sales or marketing department. We make every effort to ensure that the content is the best in terms of content and language, but we are not infallible. If you see anything that needs to be corrected or clarified, we'd love to hear from you.