Using GitHub merge queues
Merge queues are a feature of GitHub to improve development velocity on busy branches. They automate the merging for pull requests while protecting the branch from failure due to incompatibilities introduced by different pull requests.
Buildkite supports creating builds for pull requests in a GitHub merge queue, and can automatically cancel redundant builds when the composition of the merge queue changes. These builds are uniquely identified in the Buildkite UI, and the behavior of the pipeline can be manipulated based on conditionals and environment variables that identify it as a merge queue build.
Before you start
Familiarize yourself with managing a merge queue in GitHub.
Enable merge queue builds for a pipeline
To enable merge queue builds for a pipeline:
- From your Buildkite dashboard, select your pipeline.
- Select Pipeline Settings > GitHub.
- In the GitHub Settings section, select the Build merge queues checkbox.
Ensure GitHub webhook has Merge groups events enabled
Buildkite relies on receiving merge_group
webhook events from GitHub to create builds for merge groups in the merge queue. Ensure your pipeline's webhook has the Merge groups event enabled before enabling merge queue builds.
That's it! Your pipeline now supports merge queues in GitHub. 🎉
Understanding merge queue behavior
When a GitHub Pull Request (PR) is added to the merge queue, a "merge group" is created. A merge group contains the changes for that PR, along with changes belonging to any PR ahead of it in the merge queue.
Each merge group is based on the HEAD commit of the merge group ahead of it in the queue, and the merge group at the front of the queue is based on the HEAD commit of the target branch.
The HEAD commit of a merge group is a speculative commit constructed based on the Merge method setting of the merge queue in GitHub. This commit is the exact commit that will end up on the target branch if the merge group is successfully merged into the target branch.
Builds created for merge groups
Every time GitHub creates a merge group, two webhook events are sent that Buildkite might respond to:
- A
push
webhook event for the temporarygh-readonly-queue/*
branch that was created. - A
merge_group
webhook event for the merge group.
If Build branches is enabled for the pipeline, then Buildkite will by default respond to the push
event by creating a build for the temporary branch. These builds will be no different to a build created for any other branch.
However, if Build merge queues is enabled, the push
event will be ignored and instead Buildkite will respond to the merge_group
event by creating a "merge queue build" that captures additional properties about that merge group:
These properties are exposed as conditionals and environment variables in the build:
Property | Conditional | Environment variable | |||
---|---|---|---|---|---|
Property | base_sha | Conditional | build.merge_queue.base_commit |
Environment variable | BUILDKITE_MERGE_QUEUE_BASE_COMMIT |
Property | base_ref | Conditional | build.merge_queue.base_branch |
Environment variable | BUILDKITE_MERGE_QUEUE_BASE_BRANCH |
Property | head_sha | Conditional | build.commit |
Environment variable | BUILDKITE_COMMIT |
Property | head_ref | Conditional | build.branch |
Environment variable | BUILDKITE_BRANCH |
Skipping a build is not supported for merge queue builds, as GitHub expects every merge group commit to receive a commit status update.
However, you can still use conditionals to prevent steps from running inside of a merge queue build.
Listing merge queue builds
Merge queue builds are listed separately at the top of the pipeline page:
This listing reflects all builds created for the merge queue, it is not representative of the current state of the merge queue in GitHub. For example, if a pull request is removed from the merge queue, the corresponding build will remain visible in Buildkite.
Failing builds in a merge queue
Builds for merge groups can post commit status updates like any other build:
If that commit status is a required check for the merge queue, then a "failing" (or "failed") update will cause GitHub to remove the corresponding pull request from the merge queue.
Behavior may differ based on GitHub merge queue settings
If you've disabled the Require all queue entries to pass required checks setting on the merge queue in GitHub, then a failing build will not always cause the pull request to be removed from the merge queue immediately.
Instead GitHub will first wait to see if the build for any merge group behind it in the queue succeeds. This option is intended to prevent flaky test failures from causing pull requests to be removed from the merge queue unnecessarily.
When this happens the merge groups for any merge groups behind it in the queue will be "invalidated" and replaced with new merge groups that exclude the removed pull request.
This will result in a new build being created for the newly created merge group:
Automatic cancellation of redundant builds
When a merge group is invalidated, GitHub sends a merge_group
webhook event that Buildkite can respond to by cancelling any running build for that merge group. Select Cancel builds for destroyed merge groups in the pipeline's GitHub settings to enable this behavior.
Interaction with if_changed agent behavior
The agent supports an if_changed
attribute that allows steps to be conditionally included in a build based on the files changed in the commit range for that build.
By default for merge queue builds this commit range will be the range of commits between the HEAD of the target branch and the HEAD of the merge group the build is for. That means it will also consider file changes from merge groups ahead of the build's merge group in the queue.
If your merge queue has the Require all queue entries to pass required checks setting enabled, it is safe for if_changed
to consider only the file changes belonging to the PR the merge group is for. Select Use base commit when making if_changed
comparisons in the pipeline's GitHub settings to enable this behavior.
After merge groups are merged
When a series of merge groups are successfully merged, GitHub fast-forwards the target branch of the queue to the HEAD of the last merge group being merged.
GitHub sends a push
webhook event for the updated target branch and a build will be created if Build branches is enabled in the pipeline's GitHub settings.
The creation of this build can be avoided by skipping existing commits or applying branch filtering.