Running Jenkins stages depending on the pipeline status

There are scenarios in which it’s useful to enable or disable stages in a Jenkins pipeline depending on the build status. This is about having different stages in a Jenkinsfile that will be executed depending on the `buildResult` and `stageResult` of the Jenkins pipeline and the different stages inside the Jenkins pipeline.

Usecase

One possible usecase is e.g. a complex testing setup that requires multiple stages in order to start and then after a test to tear down everything properly.

Example Scenario

The following example provides a solution based on the following scenario:

There is a build setup that may fail. There is a test that shall be executed only in case the build setup was ok. Then there is a tear down that shall be executed all the time, even in case the setup was not ok or the test failed.

The job build status then looks like:
– Failing test setup -> `UNSTABLE`
– Failing test -> `FAILURE`
– Failing tear down -> `UNSTABLE`

The following parts describes all the stages involved in the Jenkinsfile.

fail-unstable

The first stage `fail-unstable` describes creating a test setup that may fail. In case it fails the build will be marked as `UNSTABLE`. The result of the build then will be `UNSTABLE`. In case it’s `SUCCESFULL`, then everything goes like expected.

may-not-run

This represents another test setup stage. This stage will be skipped in case a stage before already failed and then marked the build as `UNSTABLE`. That could be the test itself that will be skipped as the build setup already is `UNSTABLE`.

must-run-on-unstable

This is for demonstration purpose only. This stage runs in case the build is `UNSTABLE` but not in case it’s in `FAILURE`.

fail-build

This is a failing build stage. For example a test that was not ok. It’s required to finish the rest of the pipeline in order to tear down the test resources.

must-run-after-failure

A tear down stage that must run after the failing test.

check-fail-build

Checks whether the test was ok or not. Then fails the pipeline in case the test was not ok.

How to do it

The following source code of the `Jenkinsfile` contains comments that describe each single step.

The Jenkinsfile

def test_failed = false // variable that stores the information whether the test was ok or not

pipeline {
	agent any
	
	stages {
		stage('fail-unstable') {
			
			// represents a failing setup step
			
			steps {
				// mark the build as unstable so all remaining stages will be executed
				catchError(buildResult: 'UNSTABLE', stageResult: 'UNSTABLE') {
					echo 'fail to unstable'
					sh "exit 1" // Return exit code 1 in order to fail the stage
				}
				
			}
		}
		stage('may-not-run') {
			
			// this stage will be ignored in case the build status is not ok
			
			when {equals expected: 'SUCCESS', actual: currentBuild.result} // check for the build status
			steps {
				echo 'may not run'
			}
		}
		stage('must-run-on-unstable') {
			
			// a stage that runs even in case the build is unstable
			
			steps {
				echo 'must run on unstable'
			}
		}
		stage('fail-build') {
			
			// represents a failing test stage
			
			steps {
				// mark as unstable so the following stages will be executed
				catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
					echo 'fail build'
					sh "exit 1" // fail the build
				}
			}
			post {
				unsuccessful {
					script {
						test_failed = true // store the information that the test failed
					}
				}
			}
		}
		stage('must-run-after-failure') {
			
			// a tear down task that will be executed even in case the test was not ok
			
			steps {
				catchError(buildResult: 'UNSTABLE', stageResult: 'UNSTABLE') {
					echo 'must run after failure'
				}
			}
		}
		stage('check-fail-build') {
			
			// checks whether the test stage was ok or not. Fails in case the test result was negative.
			
			when {equals expected: true, actual: test_failed}
			steps {
				sh 'check failed'
				sh 'exit 1' // make the stage and the build fail
			}
		}
	}
}

How the Jenkins pipeline looks like

The following image shows how the Jenkins pipeline looks like in case the pipeline that was described above will be executed.

Screenshot that shows the pipeline

Conditional pipeline

Differences to real world

– In case the stage `fail-unstable` does not work as expected then the stage `fail-build` shouldn’t be exeuted but skipped like the stage `may-not-run`.
– Imagine the only the test fails, then all stages but `fail-build` and `check-fail-build` would be green.
– Having a failing tear down should be prevented. E.g. cleaning up resources should be implemented in a resilient way.

Summary

I hope this was a useful piece of information for you. At least now it should be clear how to build a Jenkins pipeline that supports running stages depending on the question whether a stage before was ok or not.

Sources

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.