Skip to content

Commit

Permalink
Merge pull request #11 from seek-oss/explicit-merge
Browse files Browse the repository at this point in the history
Explicitly merge PRs rather than relying on GitHub refs
  • Loading branch information
zsims authored Sep 26, 2018
2 parents 5e70201 + 0e870ce commit ec1871f
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 92 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# GitHub Pull Request Plugin

A [Buildkite plugin](https://buildkite.com/docs/agent/v3/plugins) to build the merged state of GitHub pull requests.
A [Buildkite plugin](https://buildkite.com/docs/agent/v3/plugins) to build the merged state of pull requests.

Why would I want this?
1. Parity with other CI setups. Including [TeamCity](https://blog.jetbrains.com/teamcity/2013/02/automatically-building-pull-requests-from-github-with-teamcity/), Travis, and [Jenkins](https://wiki.jenkins.io/display/JENKINS/GitHub+pull+request+builder+plugin).
Expand All @@ -13,7 +13,7 @@ While this approach doesn't mitigate breaking changes made to the target branch

The plugin has two modes:
- `mode: trigger` to async trigger another build (of the current pipeline); and
- `mode: checkout` to checkout the PR merged ref (`refs/pull/123/merge`) rather than the head (`refs/pull/123/head`)
- `mode: checkout` to merge the PR after checking out source

# Example

Expand Down
59 changes: 59 additions & 0 deletions hooks/post-checkout
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env bash

set -euo pipefail

function trigger() {
local pr="$1"
local branch="$2"
local slug="${BUILDKITE_PIPELINE_SLUG}"
echo "Triggering merged build of ${slug} for PR ${pr}"
cat <<EOL | buildkite-agent pipeline upload
steps:
- label: "Merge build"
trigger: "${slug}"
async: true
build:
message: "Merge build for Pull Request ${pr}"
branch: "${BUILDKITE_BRANCH}"
env:
GITHUB_MERGED_PR_FORCE_BRANCH: "${2}"
EOL
}

function merge() {
local target_branch="$1"
if [[ -z "${target_branch}" ]] ; then
echo "No pull request target branch"
exit 1
fi

git fetch -v origin "${target_branch}"
git checkout FETCH_HEAD
GIT_COMMITTER_NAME="github-merged-pr-buildkite-plugin" git merge "${BUILDKITE_COMMIT}"
}

force_merge="${GITHUB_MERGED_PR_FORCE_BRANCH:-}"
if [[ -n "$force_merge" ]]; then
echo "Forcing merge into ${force_merge}"
merge "${force_merge}"
exit $?
fi

# this is a pull request build
pull_request="${BUILDKITE_PULL_REQUEST:-false}"
if [[ "${pull_request}" == "false" ]] ; then
echo "Not a pull request, skipping"
exit 0
fi

mode="${BUILDKITE_PLUGIN_GITHUB_MERGED_PR_MODE:-checkout}"
if [[ "${mode}" == "checkout" ]]; then
merge "${BUILDKITE_PULL_REQUEST_BASE_BRANCH:-master}"
exit $?
elif [[ "${mode}" == "trigger" ]]; then
trigger "${pull_request}" "${BUILDKITE_PULL_REQUEST_BASE_BRANCH:-}"
else
echo "Invalid mode: ${mode}"
exit 1
fi

42 changes: 0 additions & 42 deletions hooks/pre-checkout

This file was deleted.

78 changes: 78 additions & 0 deletions tests/post-checkout.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env bats

load '/usr/local/lib/bats/load.bash'

post_checkout_hook="$PWD/hooks/post-checkout"

@test "Triggers a build if PR number set and mode is trigger" {
export BUILDKITE_PULL_REQUEST=123
export BUILDKITE_PLUGIN_GITHUB_MERGED_PR_MODE="trigger"
export BUILDKITE_PIPELINE_SLUG="my-pipeline"
export BUILDKITE_BRANCH="dev"

stub buildkite-agent \
"pipeline upload : echo UPLOADED_PIPELINE"

run "$post_checkout_hook"

assert_success
assert_output --partial "Triggering merged build of my-pipeline for PR 123"
assert_output --partial "UPLOADED_PIPELINE"
unstub buildkite-agent
}

@test "Merges with target PR branch" {
export BUILDKITE_PULL_REQUEST=123
export BUILDKITE_PLUGIN_GITHUB_MERGED_PR_MODE="checkout"
export BUILDKITE_PULL_REQUEST_BASE_BRANCH="dev"
export BUILDKITE_COMMIT="deadbeef"

stub git \
"fetch -v origin dev : echo FETCHED" \
"checkout FETCH_HEAD : echo CHECKED_OUT" \
"merge deadbeef : echo MERGED"

run "$post_checkout_hook"

assert_success
assert_output --partial "FETCHED"
assert_output --partial "CHECKED_OUT"
assert_output --partial "MERGED"
unstub git
}

@test "Forces merges when GITHUB_MERGED_PR_FORCE_BRANCH is set" {
export BUILDKITE_COMMIT="deadbeef"
export GITHUB_MERGED_PR_FORCE_BRANCH="master"

stub git \
"fetch -v origin master : echo FETCHED" \
"checkout FETCH_HEAD : echo CHECKED_OUT" \
"merge deadbeef : echo MERGED"

run "$post_checkout_hook"

assert_success
assert_output --partial "FETCHED"
assert_output --partial "CHECKED_OUT"
assert_output --partial "MERGED"
unstub git
}

@test "Does nothing if no PR number set" {
export BUILDKITE_PULL_REQUEST=""

run "$post_checkout_hook"

assert_success
assert_output --partial "Not a pull request"
}

@test "Does nothing if PR is false" {
export BUILDKITE_PULL_REQUEST="false"

run "$post_checkout_hook"

assert_success
assert_output --partial "Not a pull request"
}
48 changes: 0 additions & 48 deletions tests/pre-checkout.bats

This file was deleted.

0 comments on commit ec1871f

Please sign in to comment.