Using conditionals

Using conditionals, you can run builds or steps only when specific conditions are met. Define boolean conditions using C-like expressions.

You can define conditionals at the step level in your pipeline.yml or at the pipeline level in your Buildkite version control provider settings.

Conditionals in pipelines

You can have complete control over when to trigger pipeline builds by using conditional expressions to filter incoming webhooks. You need to define conditionals in the pipeline's Settings page for your repository provider to run builds only when expressions evaluate to true. For example, to run only when a pull request is targeting the main branch:

Conditional Filtering settings

Pipeline-level build conditionals are evaluated before any other build trigger settings. If both a conditional and a branch filter are present, both filters must pass for a build to be created – first the pipeline-level limiting filter and then the conditional filter.

Conditionals are supported in Bitbucket, Bitbucket Server, GitHub, GitHub Enterprise, and GitLab (including GitLab Community and GitLab Enterprise). You can add a conditional on your pipeline's Settings page in the Buildkite interface or using the REST API.

Evaluating conditionals

Conditional expressions are evaluated at pipeline upload, not at step runtime.

Conditionals in steps

Use the if attribute in your step definition to conditionally run a step.

In the below example, the tests step will only be run if the build message does not contain the string "skip tests".

pipeline.yml
steps:
    - command: ./scripts/tests.sh
      label: tests
      if: build.message !~ /skip tests/

The if attribute can be used in any type of step, and with any of the supported expressions and parameters. However, it cannot be used at the same time as the branches attribute.

Be careful when defining conditionals within YAML. Many symbols have special meaning in YAML and will change the type of a value. You can avoid this by quoting your conditional as a string.

pipeline.yml
steps:
    - command: ./scripts/tests.sh
      label: tests
      if: "!build.pull_request.draft"

Multi-line conditionals can be added with the | character, and avoid the need for quotes:

pipeline.yml
steps:
    - command: ./scripts/tests.sh
      label: tests
      if: |
        // Don't when the message contains "skip tests"
        // Only run on feature branches
        build.message !~ /skip tests/ &&
          build.branch =~ /^feature\//

Since if conditions are evaluated at the time of the pipeline upload, it's not possible to use the if attribute to conditionally run a step based on the result of another step.

To run a step based on the result of another step, upload a new pipeline based on the if condition set up in the command step like in the example below:

pipeline.yml
steps:
  - label: "Validation check"
    command: ./scripts/validation_tests.sh
    key: "validation-check"
  - label: "Run regression only if validation check is passed"
    depends_on: "validation-check"
    command: |
      if [ $$(buildkite-agent step get "outcome" --step "validation-check") == "passed" ]; then
         cat <<- YAML | buildkite-agent pipeline upload
         steps:
           - label: "Run Regression"
             command: ./scripts/regression_tests.sh
      YAML
      fi

Conditional notifications

To trigger Build notifications only under certain conditions, use the same if syntax as in your Steps.

For example, the following email notification will only be triggered if the build passes:

pipeline.yml
notify:
  - email: "dev@acmeinc.com"
    if: build.state == "passed"

Note that conditional expressions on the build state are only available at the pipeline level. You can't use them at the step level.

Conditionals and the broken state

Jobs become broken when their configuration prevents them from running. This might be because their branch configuration doesn't match the build's branch, or because a conditional returned false. This is distinct from skipped jobs, which might happen if a newer build is started and build skipping is enabled. A rough explanation is that jobs break because of something inside the build and are skipped by something outside the build.

Variable and syntax reference

Evaluate expressions made up of boolean operators and variables.

Operator syntax

The following expressions are supported by the if attribute.

Comparators == != =~ !~
Logical operators || &&
Array operators includes
Integers 12345
Strings 'feature-branch' "feature-branch"
Literals true false null
Parentheses ( )
Regular expressions /^v1.0/
Prefixes !
Comments // This is a comment

Formatting regular expressions

When using regular expressions in conditionals, the regular expression must be on the right hand side, and the use of the $ anchor symbol must be escaped to avoid environment variable substitution. For example, to match branches ending in "/feature" the conditional statement would be build.branch =~ /\/feature$$/.

Variables

The following variables are supported by the if attribute. Note that you cannot use Build Meta-data in conditional expressions.

Unverified commits

Note that GitHub accepts unsigned commits, including information about the commit author and passes them along to webhooks, so you should not rely on these for authentication unless you are confident that all of your commits are trusted.

build.author.email String The unverified email address of the user who authored the build's commit
build.author.id String The unverified ID of the user who authored the build's commit
build.author.name String The unverified name of the user who authored the build's commit
build.author.teams Array An unverified array of the team/s which the user who authored the build's commit is a member of
build.branch String The branch on which this build is created from
build.commit String The commit number of the commit the current build is based on
build.creator.email String

The email address of the user who created the build. The value differs depending on how the build was created:

  • Buildkite dashboard: Set based on who manually created the build.
  • GitHub webhook: Set from the unverified HEAD commit.
  • Webhook: Set based on which user is attached to the API Key used.

For conditionals to use this variable, the user set must be a verified Buildkite user.

build.creator.id String

The ID of the user who created the build. The value differs depending on how the build was created:

  • Buildkite dashboard: Set based on who manually created the build.
  • GitHub webhook: Set from the unverified HEAD commit.
  • Webhook: Set based on which user is attached to the API Key used.

For conditionals to use this variable, the user set must be a verified Buildkite user.

build.creator.name String

The name of the user who created the build. The value differs depending on how the build was created:

  • Buildkite dashboard: Set based on who manually created the build.
  • GitHub webhook: Set from the unverified HEAD commit.
  • Webhook: Set based on which user is attached to the API Key used.

For conditionals to use this variable, the user set must be a verified Buildkite user.

build.creator.teams Array

An array of the teams which the user who created the build is a member of. The value differs depending on how the build was created:

  • Buildkite dashboard: Set based on who manually created the build.
  • GitHub webhook: Set from the unverified HEAD commit.
  • Webhook: Set based on which user is attached to the API Key used.

For conditionals to use this variable, the user set must be a verified Buildkite user.

build.env() String, null This function returns the value of the environment passed as the first argument if that variable is set, or null if the environment variable is not set.
build.env() works with variables you've defined, and the following BUILDKITE_* variables:
BUILDKITE_BRANCH
BUILDKITE_TAG
BUILDKITE_MESSAGE
BUILDKITE_COMMIT
BUILDKITE_PIPELINE_SLUG
BUILDKITE_PIPELINE_NAME
BUILDKITE_PIPELINE_ID
BUILDKITE_ORGANIZATION_SLUG
BUILDKITE_TRIGGERED_FROM_BUILD_ID
BUILDKITE_TRIGGERED_FROM_BUILD_NUMBER
BUILDKITE_TRIGGERED_FROM_BUILD_PIPELINE_SLUG
BUILDKITE_REBUILT_FROM_BUILD_ID
BUILDKITE_REBUILT_FROM_BUILD_NUMBER
BUILDKITE_REPO
BUILDKITE_PULL_REQUEST
BUILDKITE_PULL_REQUEST_BASE_BRANCH
BUILDKITE_PULL_REQUEST_REPO
BUILDKITE_GITHUB_DEPLOYMENT_ID
BUILDKITE_GITHUB_DEPLOYMENT_TASK
BUILDKITE_GITHUB_DEPLOYMENT_ENVIRONMENT
BUILDKITE_GITHUB_DEPLOYMENT_PAYLOAD
build.id String The ID of the current build
build.message String, null The current build's message
build.number Integer The number of the current build
build.pull_request.base_branch String, null The base branch that the pull request is targeting, otherwise null if the branch is not a pull request
build.pull_request.id String, null The number of the pull request, otherwise null if the branch is not a pull request
build.pull_request.draft Boolean, null If the pull request is a draft, otherwise null if the branch is not a pull request or the provider doesn't support draft pull requests
build.pull_request.labels Array An array of label names attached to the pull request
build.pull_request.repository String, null The repository URL of the pull request, otherwise null if the branch is not a pull request
build.pull_request.repository.fork Boolean, null If the pull request comes from a forked repository, otherwise null if the branch is not a pull request
build.source String The source of the event that created the build
Available sources: ui, api, webhook, trigger_job, schedule
build.state String The state the current build is in
Available states:, started, scheduled, running, passed, failed, failing, started_failing, blocked, canceling, canceled, skipped, not_run
build.tag String, null The tag associated with the commit the current build is based on
pipeline.default_branch String, null The default branch of the pipeline the current build is from
pipeline.id String The ID of the pipeline the current build is from
pipeline.repository String, null The repository of the pipeline the current build is from
pipeline.slug String The slug of the pipeline the current build is from
organization.id String The ID of the organization the current build is running in
organization.slug String The slug of the organization the current build is running in

Using build.env() with custom environment variables

To access custom environment variables with the build.env() function, ensure that the YAML pipeline steps editor has been enabled in the Pipeline Settings menu.

Example expressions

To run only when the branch is main or production:

build.branch == "main" || build.branch == "production"

To run only when the branch is not production:

build.branch != "production"

To run only when the branch starts with features/:

build.branch =~ /^features\//

To run only when the branch ends with /release-123, such as feature/release-123:

build.branch =~ /\/release-123\$/

To run only when building a tag:

build.tag != null

To run only when building a tag beginning with a v and ends with a .0, such as v1.0:

// Using the tag variable
build.tag =~ /^v[0-9]+\.0\$/

// Using the env function
build.env("BUILDKITE_TAG") =~ /^v[0-9]+\.0\$/

To run only if the message doesn't contain [skip tests], case insensitive:

build.message !~ /\[skip tests\]/i

To run only if the build was created from a schedule:

build.source == "schedule"

To run when the value of CUSTOM_ENVIRONMENT_VARIABLE is value:

build.env("CUSTOM_ENVIRONMENT_VARIABLE") == "value"

To run when the unverified build creator is in the deploy team:

build.creator.teams includes "deploy"

To run only non-draft pull requests:

!build.pull_request.draft