Baeldung Pro – Ops – NPI EA (cat = Baeldung on Ops)
announcement - icon

Learn through the super-clean Baeldung Pro experience:

>> Membership and Baeldung Pro.

No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.

Partner – Orkes – NPI EA (cat=Kubernetes)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

1. Overview

Jenkins pipelines report the status of builds and build stages to indicate their success or failure. This can be handy for notifying team members about the state of the build, which reflects the stability of the code.

In some scenarios, we might need to manually set the status of a specific stage, regardless of its execution results. For example, we can have a step that runs a command that’s not critical for the overall build process. To avoid failing the whole build if this command fails, we can set the stage or build status to SUCCESS, regardless of the step result.

In this tutorial, we’re going to cover the concept of a pipeline stage in Jenkins and its different statuses. We’ll explain what each status means and how to manually set a stage status.

2. What Is a Pipeline Stage?

Pipeline stages represent a specific phase in the software delivery flow. For example, we can have a stage for building the application, another one for testing, and another one for deployment. These stages are linked together to form our complete pipeline.

Each of these stages contain the steps that we need to implement to achieve the goal of the stage. We can have a stage that executes some commands, copies files, or deploys an artifact. Let’s see an example of a Jenkins pipeline that has multiple stages:

pipeline{    
    agent any 
    stages{
        stage("clone repo"){       
            steps {               
                git branch: "main" , url: "https://github.com/spring-projects/spring-petclinic.git"
            }
        }
        stage("build"){            
            steps {                
                sh "mvn compile"
            }
        }
        stage("test"){           
            steps{                
                sh "mvn test"
            }
        }
    }
}

In the above code, we have a stages{} block that includes all pipeline stages inside it. Then, each stage{} block inside represents a specific phase in the application deployment. So, we first have a clone repo stage to check out the source code from GitHub, then a build stage that compiles the code, and finally, a test stage to run our tests. This structure makes it easy to understand and create a pipeline flow.

3. Stage Status

As the pipeline progresses and moves through the different stages, each of these stages reports its status. The stage status represents the result of executing the steps inside the stage. Let’s check the most common Jenkins stage statuses and what they represent.

3.1. SUCCESS

As the name implies, a SUCCESS status means that the steps inside the stage executed with no errors. All the steps inside the stage need to succeed in order to report the stage as SUCCESS. If these steps are executing some commands, all commands need to report a zero exit code.

Let’s check this with an example:

pipeline {
    agent any
    stages{
        stage("Success"){
            steps{
                sh "exit 0"
                sh "ls -l"
            }
        }
    }
}

In the above code, we have a single stage pipeline. Inside the stage, there are two steps, which are shell commands that should execute successfully. Let’s trigger the pipeline and see the results:

jenkins success stage

In the above image, we can see the stage is showing green color, which denotes that its status is SUCCESS. When a stage status is SUCCESS, the pipeline execution will continue to the next stage.

3.2. FAILED

In contrast to the SUCCESS status, a FAILED status indicates that there’s an issue with the execution of the steps inside the stage. The stage status is reported as FAILED if any of the steps inside it didn’t execute successfully. If the steps are running some commands, the stage will fail if any of the commands reports a non-zero exit code.

Let’s test this in our pipeline:

pipeline {
    agent any
    stages{
        stage("Success"){
            steps{
                sh "exit 0"
                sh "ls -l"
            }
        }
        stage("Fail"){
            steps{
                sh "ls -l"
                sh "exit 1"
            }
        }
    }
}

Here, we added a stage to our pipeline. The new stage executes two commands, where one of them should succeed and the other should fail. Let’s trigger our pipeline:

jenkins failed stage

We can see here that our second stage is showing a red color, which denotes that its status is FAILED. When a stage status is FAILED, the pipeline execution will not progress to the next stage.

3.3. UNSTABLE

The UNSTABLE status reports that an error has happened, but it’s not critical to fail the stage. For example, if we want to execute a command that creates a file aside from the main pipeline flow, we wouldn’t want a failure in this command to impact the whole pipeline.

We can use a Jenkins step called warnError to produce an UNSTABLE status. warnError tries to execute the commands inside its block, and if there’s an issue, it’ll report the stage status as UNSTABLE. Let’s check this in our pipeline:

pipeline {
    agent any
    stages{
        stage("Success"){
            steps{
                sh "exit 0"
                sh "ls -l"
            }
        }
        stage("Unstable"){
            steps{
                warnError("The command failed"){
                    sh "Wrong command"
                }
            }
        }
        stage("Continue execution"){
            steps{
                sh "exit 0"
            }
        }
    }
}

In the above code, we added a stage with the name Unstable. Inside the stage, we use the warnError step to execute a command that should fail. Let’s trigger our pipeline:

jenkins unstable stage

As we can see, the Unstable stage produces a yellow color, which indicates that the stage status is UNSTABLE. An important thing to note here is that the pipeline execution continued normally to the next stage. This is in contrast to the FAILED status, which stops the pipeline execution.

4. Manually Set the Stage Status

Jenkins allows us to manually set a stage status as per our needs. So, we can manipulate the default status that should be produced from a stage execution, and force a different status.

We can achieve this by using Jenkins’ catchError step. The catchError step tries to execute the commands inside its block, and we provide it with a specific stage and build status to set in case the commands fail.

Let’s try this in our pipeline:

pipeline {
    agent any
    stages{
        stage("Success"){
            steps{
                sh "exit 0"
                sh "ls -l"
            }
        }
        stage("Set Stage Status"){
            steps{
                catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
                    sh "exit 1"
                }
                }
            }
        stage("Continue execution"){
            steps{
                sh "exit 0"
            }
        }
    }
}

Here, we use the catchError step to execute a command, and if the command fails, we’ll set the stage and build status to SUCCESS. Let’s trigger our pipeline:

set stage status

In the above image, we can see that the stage and the build status are SUCCESS, although our command actually fails, resulting in an exit code of 1. We can see this from the console output:

set stage status in jenkins

We can see that the console output shows an error in the stage but reports the status as SUCCESS. This is because we’ve set the status manually in the catchError step.

We can also set other statuses, like the UNSTABLE status:

pipeline{
    agent any
    stages{
        stage("Success"){
            steps{
                sh "exit 0"
                sh "ls -l"
            }
        }
        stage("Set Stage Status"){
            steps{
                catchError(buildResult: 'UNSTABLE', stageResult: 'UNSTABLE') {
                    sh "exit 1"
                }
            }
        }
        stage("Continue execution"){
            steps{
                sh "exit 0"
            }
        }
    }
}

Here, we have the same code, but we changed the status in the catchError step from SUCCESS to UNSTABLE. Let’s trigger our pipeline again:

set unstable status

Again, the stage status is reported as UNSTABLE because we’ve set it in the catchError step. We can also see this from the console logs:

set stage status as unstable

As we can see, although the command throws an error, the console output reports the status as UNSTABLE.

5. Conclusion

In this article, we showed how to manually set a stage status in Jenkins. We explained the concept of a pipeline stage, which represents a specific phase in the software delivery.

We covered the different statuses for a stage and what each of them indicate, including SUCCESS, FAILED, or UNSTABLE. Finally, we manipulated the pipeline code using the catchError step to set the stage status, regardless of its execution results.