A Buildkite plugin to build the merged state of pull requests.
Why would I want this?
- Parity with other CI setups. Including TeamCity, Travis, and Jenkins.
- Can help avoid building stale branches, as CI is done against the target branch at the time of the PR being raised rather than when the source branch was created
- Reduce the risk of failed builds from reaching master, due to bad merges (See the example at the bottom of this document)
While this approach doesn't mitigate breaking changes made to the target branch branch after the PR is raised, it does help reduce the [time] window in which bad merges can appear -- the thinking being the age of a PR is clearly visible on GitHub unlike the age of the parent commit for a PR branch.
The plugin has two modes:
mode: trigger
to async trigger another build (of the current pipeline); andmode: checkout
to merge the PR after checking out source
Ensure Skip pull request builds for existing commits
is set to false
in your Pipeline settings, as BuildKite will build the branch and skip the PR build.
When using checkout
mode, the plugin should be specified on each build step (e.g. where a checkout happens).
plugins: &plugins
stellargraph/github-merged-pr#v0.0.6:
mode: checkout
steps:
- label: 'Make something'
commands:
- make something
plugins:
<<: *plugins
- label: 'Make something else'
commands:
- make something-else
plugins:
<<: *plugins
An example of how to use it with the docker plugin
steps:
- label: "test"
command: ".buildkite/script.sh"
plugins:
<<: *plugins
docker#v1.3.0:
image: "stellargraph/image"
environment:
- BUILDKITE_BRANCH=${BUILDKITE_BRANCH?}
- BUILDKITE_PULL_REQUEST=${BUILDKITE_PULL_REQUEST?}
agents:
- "aws:instance-type=t2.medium"
In trigger
mode the plugin should only be specified on one step, to prevent triggering multiple builds.
steps:
- label: 'Make something'
commands:
- make something
plugins:
stellargraph/github-merged-pr#v0.0.6:
mode: trigger
- label: 'Make something else'
commands:
- make something-else
To run the tests of this plugin, run
docker-compose run --rm tests
MIT (see LICENSE)
An example of why it may be desirable to build the merged commit. Let's say you're raising a PR to implement an add
function to a calculator that can already subtract
:
origin/master
(commit 1abcdef
): calculator.js
class Calculator {
constructor() {
this.currentAnswer = 0;
}
subtract(value) {
this.currentAnswer -= value;
}
}
(Tests omitted for brevity).
You create a branch locally to implement your feature
feature/add
(commit feba123
) (parent commit 1abcdef
): calculator.js
class Calculator {
constructor() {
this.currentAnswer = 0;
}
subtract(value) {
this.currentAnswer -= value;
}
add(value) {
this.currentAnswer += value;
}
}
In the meantime, origin/master
is updated to rename currentAnswer
to answer
.
origin/master
(commit 56789ab
) (parent commit 1abcdef
): calculator.js
class Calculator {
constructor() {
this.answer = 0;
}
subtract(value) {
this.answer -= value;
}
}
You then raise your PR for feature/add
, but:
- CI will run against the
HEAD
of the branch (commitfeba123
); and - The PR will likely be merged (as tests pass) -- unless someone on your team notices; and
- The
git merge
will succeed (as there's no text conflicts); and - The target branch (
master
) will be broken :(