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:
Build and push an image of an application
Run integration tests to test the application is working properly // Only for Pull Requests
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:
Status-based condition: Execute based on the status of the step/stage - on success (default behavior), always, or on failure.
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.
In the pipeline YAML, the condition would look like this:
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.