As an experienced full-stack developer, I utilize Jenkins pipelines extensively for CI/CD and find the when expression to be invaluable. With it, you can implement sophisticated conditional logic to control exactly when stages, steps and other blocks execute.

In this comprehensive guide drawn from real-world experience, we’ll dive deep on advanced when expression techniques for dynamic Jenkins pipelines.

Why Conditional Logic Matters

First, let‘s discuss why mastering conditional logic is critical for Jenkins pipelines.

As pipelines grow in complexity, you need fine-grained control over what executes when. A few common reasons:

1. Handle multiple environments – Only deploy to staging under X conditions but deploy to production with more checks.

2. Branch-specific logic – Run UI tests only for dev branch as they‘re slower.

3. Error handling – Custom failure handling for different scenarios.

4. Dynamic parameters – Execute pipeline sections based on parameter values.

Without when expressions, the best you can do is wrapper shell scripts with if/else statements. This loses the elegance and visibility of a Jenkins pipeline.

Understanding Groovy Closures

The key to understanding when expressions is to recognize they encapsulate Groovy closures. A closure in Groovy is essentially a code block that can accept input parameters and return a value.

Here is a simple Groovy closure:

def codeBlock = {
    println "Hello World" 
}

codeBlock() //Call the closure

When you wrap code inside {} in Groovy, it creates a closure. This closure can then be executed by adding parentheses () like a method call.

Inside a Jenkinsfile, when expressions leverage this concept of closures.

Best Practices for Readability

Since when expressions involve Groovy code, it‘s extra important they are formatted cleanly for readability.

Here are some best practices I follow in my Jenkinsfiles:

1. Use Braces – Always wrap the when condition in braces:

when {
   //condition here   
}

2. Proper Indentation – Indent nested closures an extra level:

when {
    allOf {
        //conditions here
    } 
}

3. Separate Lines – Put each condition on a separate line:

when {
  allOf {
      condition1  
      condition2   
  }
}

4. Descriptive Conditions – Use variable names that describe the condition:

when {
    expression { skipPerformanceTests == true }   
}

Handling Parameterized Pipelines

One extremely powerful technique is using when expressions to handle parameterized pipelines.

By parameters, I mean String parameters that are passed when the Jenkins job is triggered manually or via API:

Jenkins Parameters

This allows for dynamic pipelines based on user input.

Here is an example that leverages parameters:

parameters {
  string(name: ‘ENVIRONMENT‘, defaultValue: ‘staging‘, description: ‘‘) 
  booleanParam(name: ‘DEBUG_BUILD‘, defaultValue: false, description: ‘‘)
}

stages {

  stage(‘Build‘) {
    when {
      expression { 
        params.ENVIRONMENT == ‘prod‘ || params.DEBUG_BUILD == true  
      }
    }      
    steps {
      // build steps here
    }
  }

}

Here the Build stage will only happen if:

  1. ENVIRONMENT parameter equals "prod" OR
  2. DEBUG_BUILD parameter is true

This dynamically controls pipeline execution without messy shell script wrappers.

Implementing Conditional Build Failure Handling

Another key use case for when expressions is custom handling for different build failures.

For example:

stages {

  stage(‘Lint Tests‘) {
     steps {
        sh "make lint"  
     }
  }

  stage(‘Unit Tests‘) {
    steps {
       sh "make unittest"
    }
  } 


  stage(‘Error Handling‘) {
     when {
       expression { 
         currentBuild.currentResult == "UNSTABLE" 
       }
     }
     steps {
       // custom steps to handle unstable build
     }
  }


}

Here if the Lint Tests or Unit Tests fail and cause the build to be marked "UNSTABLE", the error handling stage will activate to perform any needed recovery.

This pattern prevents having to wrap all test stages in complex try/catch blocks.

Controlling Deployments by Environment

A very useful technique in CI/CD pipelines is using when expressions to only deploy to certain environments when criteria is met.

For example:

stage(‘Deploy‘) {

  when {
     anyOf {
        branch ‘main‘ 
        environment ‘prod‘
     }
  }

  steps {
    //production deploy steps
  }

}

stage(‘Deploy‘) {

  when {
      branch ‘develop‘       
  }  

  steps {
     // lower environment deploy steps
  }

}

This ensures the production deploy stage only happens for main branch OR if already executing in the prod environment.

The development deploy stage is then only for the develop branch.

Debugging Failures

When first getting started with complex when expressions, you need to be prepared for failures and know how to debug issues.

Here are a few tips:

1. Check Console Output – Carefully read console logs for errors during pipeline execution. Red text indicates issues.

2. Use Small Validations – Test with very simple when conditions first like hardcoded strings to validate syntax.

3. Print Debug Messages – Sprinkle pipeline with echo steps to output variable values helping isolate problems.

4. Use Replay – Fix code then hit “Replay” on failed runs to re-execute from scratch.

With time, you will become proficient at parsing pipeline execution logs to uncover flaws in when conditional logic.

Sample When Expression Recipes

To help master advanced when syntax, here are some useful code "recipes" that can be adapted for pipeline projects:

Run on Tagged Builds Only

when {
  expression { 
    env.GIT_BRANCH.startsWith("refs/tags/") 
  }
}

Deploy Main Branch on Mondays Only

when {
  allOf {
    branch "main" 
    expression { 
      def dayOfWeek = new Date().format("EEEE")
      dayOfWeek == "Monday"
    }
  }  
}

Custom Stage for PRs Against Release Branches

when {
  expression {
    (env.CHANGE_ID != null) && 
    (env.GIT_BRANCH ==~ /release-\d+\.\d+$/) 
  }  
}

These demonstrate more complex nested logic supported with the Jenkinsfile when expression.

Wrapping Up

The ability to implement conditional logic is what takes Jenkins pipelines from basic linear execution to extremely sophisticated orchestration engines. Mastering the when expression is a key milestone for unlocking the power of Jenkinsfile pipelines.

In addition to the comprehensive examples discussed here, I recommend reviewing the official Jenkins documentation for even more on when expressions.

Now go unleash dynamic pipelines on your projects!

Similar Posts