Using Conditionals

Using conditionals, you can run builds or steps only when specific conditions are met. Define boolean conditions using C-like expressions. Note that you cannot use Build Meta-data in conditional 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

Define conditionals in the Pipeline Settings for your repository provider to run builds only when expressions evaluate to true. For example, to run only when a branch is tagged Approved:

Conditional Filtering settings

Conditionals are supported in Bitbucket, Bitbucket Server, GitHub, GitHub Enterprise, and GitLab (including GitLab Community and GitLab Enterprise).

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

Supported syntax

The below 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$$/.

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"

Supported variables

The below variables are supported by the if attribute:

build.author.email String The email address of the user who authored the build's commit
build.author.id String The ID of the user who authored the build's commit
build.author.name String The name of the user who authored the build's commit
build.author.teams Array An 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 of the user who created the build
build.creator.id String The ID of the user who created the build
build.creator.name String The name of the user who created the build
build.creator.teams Array An array of the team/s which the user who created the build is a member of
build.env() String, null This function returns the value of the environment passed as the first argument, otherwise null if the environment variable has not been set
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: scheduled, running, passed, failed, blocked, canceling, canceled, skipped, not_run, fixed, finished
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.

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. Broadly, jobs break because of something inside the build, and are skipped by something outside the build.

Example expressions

To run only when the branch is master or production:

build.branch == "master" || 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 build creator is in the deploy team:

build.creator.teams includes "deploy"

To run only non-draft pull requests:

!build.pull_request.draft