Jenkins pipelines don’t just run steps sequentially; they can be incredibly smart about when to run entire stages.

Let’s see a pipeline in action. Imagine you have a multi-stage pipeline for building and deploying a Java application. You want to deploy to production only when a specific branch is being built and the build itself has passed all tests.

pipeline {
    agent any
    stages {
        stage('Checkout') {
            steps {
                echo 'Checking out code...'
                // git checkout logic here
            }
        }
        stage('Build') {
            steps {
                echo 'Building the project...'
                // maven or gradle build logic here
            }
        }
        stage('Test') {
            steps {
                echo 'Running unit tests...'
                // test execution logic here
            }
        }
        stage('Deploy to Staging') {
            steps {
                echo 'Deploying to staging environment...'
                // staging deployment logic here
            }
        }
        stage('Approve Production Deploy') {
            when {
                expression { env.BRANCH_NAME == 'main' }
            }
            steps {
                echo 'Waiting for manual approval for production deployment...'
                input message: 'Deploy to Production?', submitter: 'authorized_users'
            }
        }
        stage('Deploy to Production') {
            when {
                expression { env.BRANCH_NAME == 'main' && currentBuild.result == 'SUCCESS' }
            }
            steps {
                echo 'Deploying to production environment...'
                // production deployment logic here
            }
        }
    }
}

In this example, the Deploy to Production stage has a when directive. This directive tells Jenkins, "Only execute the steps within this stage if the following conditions are met." The expression block evaluates a Groovy script. Here, it checks two things:

  1. env.BRANCH_NAME == 'main': This checks if the current build is running on the main branch. env.BRANCH_NAME is an environment variable automatically provided by Jenkins that holds the name of the branch being built.
  2. currentBuild.result == 'SUCCESS': This checks if the entire pipeline up to this point has completed successfully. currentBuild.result reflects the outcome of the preceding stages. If any previous stage failed, this condition would be false, and the production deploy would be skipped.

The Approve Production Deploy stage is a bit different. It also checks if the branch is main, but instead of automatically proceeding, it pauses the pipeline and waits for explicit manual approval. This is a common pattern: use when to gate sensitive stages and then use an input step to require human intervention. The submitter parameter restricts who can approve the build, adding an extra layer of security.

The core problem when directives solve is managing complex release workflows without writing brittle shell scripts or duplicating pipeline logic. Instead of having separate pipelines for different branches or environments, you can have one pipeline that intelligently navigates its own execution path. You control the flow by defining conditions that must be true for a stage to run.

Internally, Jenkins evaluates these when directives before it starts executing the steps within a stage. If the condition evaluates to false, Jenkins marks the stage as skipped and moves on to the next stage. This evaluation happens at the pipeline orchestration level, not within individual steps, making it highly efficient. The when directive can take several forms, including expression, branch, changeRequest, environment, credentials, allOf, anyOf, and not. For instance, when { branch 'develop' } is a shorthand for when { expression { env.BRANCH_NAME == 'develop' } }.

A particularly powerful, though often overlooked, aspect is combining conditions. You can use allOf, anyOf, and not to build sophisticated logic. For example, to deploy to production only if it’s the main branch, the build was successful, and a specific environment variable DEPLOY_TO_PROD is set to true:

stage('Deploy to Production') {
    when {
        allOf {
            expression { env.BRANCH_NAME == 'main' }
            expression { currentBuild.result == 'SUCCESS' }
            environment name: 'DEPLOY_TO_PROD', value: 'true'
        }
    }
    steps {
        echo 'Deploying to production environment...'
        // production deployment logic here
    }
}

This allows for fine-grained control. The environment directive is particularly useful for toggling deployments without changing the pipeline code itself. You can set DEPLOY_TO_PROD to true or false as a build parameter or via a Jenkins configuration.

The next logical step after mastering conditional stage execution is understanding how to parameterize these conditions, allowing users to influence pipeline behavior at runtime.

Want structured learning?

Take the full Jenkins course →