The “when” directive enables Pipelines to determine whether a step or a stage should be executed depending on a given condition.

Why is it needed?

Let’s say we need to build a pipeline that executes the following logic:

  1. Build and push an image of an application  
  2. Run integration tests to test the application is working properly // Only for Pull Requests 
  3. Create a Jira ticket // Only if a failure occurred during the execution 

This is a very common use case. 

When building, testing, and pushing applications, users often need to run/skip steps and stages based on the type of build. Some variations in the pipeline logic might be needed when pushing to feature branches, when changing a PR, or when building a Tag. 

The way to achieve this is by using the “when” directive. The “when” directive allows the user to set:

  1. Status-based condition: Execute based on the status of the step/stage – on success (default behavior), always, or on failure.
  2. JEXL condition: User can set additional conditions on top of the status. 

For example, a stage with the conditions configured as below, will run only for Pull Request builds if errors have not occurred prior to that stage execution.  

"When" Directive Example - PR Builds

In the pipeline YAML, the condition would look like this:

when:
    pipelineStatus: Success
    condition: <+codebase.build.type> == "PR"

In the example above, we are combining the “when” directive with built-in variables. You can also use the JEXL condition with other variables, such as pipeline variables, stage variables, and step output variables, to conditionally determine when a stage/step should execute.  

Best Practices When Using Built-in Variables With “When” Conditions 

We have multiple types of built-in variables; Pipeline, user variables, triggers, and codebase. 

Variables with the format <+codebase.X> hold information related to the clone operation performed as a part of the CI stage. Variables with the format <+trigger.X> hold information related to how the pipeline was triggered. 

Some built-in variables might not get resolved in run time, depending on how the pipeline is triggered (manual, webhook, etc.) and the build type (Tag, Branch, PR). For example, <+codebase.tag> is only populated when building a tag, while <+trigger.prTitle> is only populated if the pipeline was triggered by a Pull Request Git event. 

To make working with variables easier, built-in variables have a default value of the string “null”. This means that you can test whether a variable value equals “null” to see if a value was populated.  

So, if you have a stage that should only execute for tags that start with a certain pattern like “v.”, you can easily achieve that using a JEXL that matches a regex pattern to <+codebase.tag>. You can still use this pipeline for building a PR , or a branch, and this stage will be skipped in these cases, as the <+codebase.tag> will be resolved to the string “null,” which does not match the pattern. 

when:
    pipelineStatus: Success
    condition: <+codebase.tag> ~/v.*/

Conclusion

In this blog post, we learned all about conditional execution, using the “when” directive and built-in variables. 

We demonstrated how users can use a single pipeline for similar but slightly different use cases, rather than authoring and maintaining multiple pipelines. 

To learn more, please refer to: