1. Overview

Effective Jenkins pipelines rely heavily on conditional constructs to control the execution flow. Using these constructs, we get the flexibility to change the flow of execution based on dynamic criteria, such as environment variables, results from previous steps, or any other condition.

In this tutorial, we’ll learn to use conditional constructs such as ifelse by writing a set of Jenkins pipelines primarily in the Groovy language.

2. Declarative Pipeline

The declarative nature of writing pipelines in Jenkins allows us to define the pipeline jobs in a simplified and structured way. In this section, let’s explore different ways to write conditional logic in declarative pipelines.

2.1. test Command With sh Step

Jenkins offers several built-in steps, such as sh, to facilitate writing pipelines conveniently. Further, we can use the sh block to write shell commands. Later, at the execution time, Jenkins executes these shell commands as shell scripts on one of the Jenkins nodes.

Let’s write a simple Jenkins pipeline named job-1 with a build stage that must execute the build steps only when the SKIP_BUILD variable isn’t set:

pipeline {
    agent any

    stages {
        stage('build') {
            steps {
                sh """
                    test -z \$SKIP_BUILD && echo 'starting to build ...'
                """
            }
        }
    }
}

We can see that having access to shell commands allows us to use the test command for the conditional execution of the build steps after it. Further, we must note that the SKIP_BUILD variable is expected to be defined somewhere outside the steps section, so we need to use \$ escaping so that Jenkins interprets it as a shell variable.

Next, let’s save our pipeline job and execute it using the “Build Now” button in the sidebar:

Started by user admin
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/job-1
[Pipeline] {
[Pipeline] stage
[Pipeline] { (build)
[Pipeline] sh
+ test -z
+ echo starting to build ...
starting to build ...
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

Since we didn’t define the SKIP_BUILD variable, we expected the “starting to build …” text in the console output, which is precisely the case.

2.2. if-else With sh Step

Similar to the test command, we can use other shell commands and constructs within the sh block.

Let’s go ahead and write the job-2 Jenkins pipeline that uses an ifelse logic to trigger the build stage:

pipeline {
    agent any

    stages {
        stage('build') {
            steps {
                script {
                    sh """
                        if [ -z \${SKIP_BUILD} ]
                        then
                          echo "starting build ..."
                        else
                          echo "skipped build ..."
                        fi
                    """
                }
            }
        }
    }
}

Moving on, let’s trigger our job-2 pipeline and check its console output:

Started by user admin
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /home/jenkins/workspace/job-2
[Pipeline] {
[Pipeline] stage
[Pipeline] { (build)
[Pipeline] script
[Pipeline] {
[Pipeline] sh
+ [ -z ]
+ echo starting build ...
starting build ...
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

From the console output, we can infer that *the code within the if-block executed successfully because the SKIP_BUILD environment is unavailable* in this run.

2.3. if-else Within Groovy Script

Since Jenkins uses Groovy for writing the pipeline script, we can use an ifelse block within the script block.

Let’s take a look at the job-3 Jenkins pipeline where we’re going to define the skipBuild variable within the Groovy script and use it within an ifelse block:

pipeline {
    agent any
    stages {
        stage('build') {
            steps {
                script {
                    def skipBuild=env.SKIP_BUILD
                    if (skipBuild == null || skipBuild.isEmpty()) {
                        echo 'starting build ...'
                    } else {
                        echo 'skipping build ...'
                    }
                }
            }
        }
    }
}

We must note that we used the def keyword to define the variable and initialized it with the value from the SKIP_BUILD environment variable.

Next, let’s run our job-3 Jenkins and see it in action:

Started by user admin
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/job-3
[Pipeline] {
[Pipeline] stage
[Pipeline] { (build)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
starting build ...
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

Great! It works as expected.

2.4. Ternary Operator Within Groovy Script

We can also use the ternary operator (?:) within the Groovy script block to execute code conditionally.

Let’s write a new Jenkins pipeline under the name job-4 that uses the ternary operator within a build stage:

pipeline {
    agent any
    stages {
        stage('build') {
            steps {
                script {
                    def skipBuild = env.SKIP_BUILD
                    (skipBuild == null || skipBuild.isEmpty()) ? println('starting the build ...') : println('skipping the build ...')
                }
            }
        }
    }
}

Further, we’re using the standard println() function available in Groovy to print the message.

Lastly, let’s execute the job-4 pipeline and check if it works as expected:

Started by user admin
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /home/jenkins/workspace/job-4
[Pipeline] {
[Pipeline] stage
[Pipeline] { (build)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
starting the build ...
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

Great! It looks like we’ve nailed this.

3. Scripted Pipeline

While the declarative pipeline allows us to write Groovy code only within the script block, the scripted pipeline is more flexible when adding Groovy code. Let’s rewrite some of the declarative pipelines using scripted syntax to build a better understanding.

First, let’s write the scripted-job-1 pipeline that uses the sh step:

node {
    stage('build') {
        sh """
            test -z \$SKIP_BUILD && echo 'starting to build ...'
        """        
    }
}

It’s interesting to note that although the scripted pipeline’s building blocks look different, the code that uses the sh step is the same.

Further, let’s run the scripted-job-1 pipeline and verify that it works as expected:

Started by user admin
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /home/jenkins/workspace/scripted-job-1
[Pipeline] {
[Pipeline] stage
[Pipeline] { (build)
[Pipeline] sh
+ test -z
+ echo starting to build ...
starting to build ...
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

Next, let’s see how to add an ifelse block using the Groovy script in the scripted-job-2 pipeline:

node {
    stage('build') {
        def skipBuild=env.SKIP_BUILD
        if (skipBuild == null || skipBuild.isEmpty()) {
            echo 'starting build ...'
        } else {
            echo 'skipping build ...'
        }
    }
}

In this pipeline code, we must note that we don’t need to add a script block to add the Groovy script.

Finally, let’s run this pipeline and see the console output:

Started by user admin
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/scripted-job-2
[Pipeline] {
[Pipeline] stage
[Pipeline] { (build)
[Pipeline] echo
starting build ...
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

It works as expected.

4. when Directive

For some scenarios, we may want to execute a stage only when a specific condition is met. For such purposes, we can use the when directive and extract the conditional logic from the script block.

Let’s write the when-job-1 pipeline that uses the when directive to define a conditional expression:

pipeline {
    agent any
    stages {
        stage('build') {
            when {
                expression {
                    def skipBuild=env.SKIP_BUILD 
                    return skipBuild == null || skipBuild.isEmpty()
                }
            }
            steps {
                script {
                    echo 'starting build ...'
                }
            }
        }
    }
}

We must note that we’ve simplified the script block keeping the code that must execute when the expression block evaluates to true.

Now, let’s run our pipeline and check the console output to verify that it’s working as expected:

Started by user admin
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/when-job-1 when expression
[Pipeline] {
[Pipeline] stage
[Pipeline] { (build)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
starting build ...
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

It works fine.

With this, we’ve learned one more mechanism to control the execution of code.

5. Conclusion

In this article, we learned about using conditional constructs in the Jenkins pipeline. Further, we explored declarative and scripted ways of writing the Jenkins pipeline using ifelse blocks, the sh step, and the when directive.