Using the "When" Directive and Built-in Variables in CI for Conditional Execution
By using the “when” directive and built-in variables, users can use a single pipeline for similar use cases, rather than creating and maintaining multiple. Let's learn all about conditional execution!
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:
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.
condition: <+codebase.tag> ~/v.*/
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: