#!/bin/bash -e
# CircleCI Automerge GitHub Pull Request Script
# Ensure in PR
if [ -z "$CIRCLE_PULL_REQUEST" ]; then
>&2 echo 'Not in pull request, skipping automerge'
exit 1
fi
# Ensure all required environment variables are present
if [ -z "$CIRCLE_PROJECT_REPONAME" ] || \
[ -z "$CIRCLE_PROJECT_USERNAME" ] || \
[ -z "$CIRCLE_PULL_REQUEST" ] || \
[ -z "$CIRCLE_BRANCH" ] || \
[ -z "$CIRCLE_SHA1" ] || \
[ -z "$GITHUB_SECRET_TOKEN" ]; then
>&2 echo 'Required variable unset, automerging failed'
exit 1
fi
# Extract GitHub PR number
github_pr_number="$(echo "$CIRCLE_PULL_REQUEST" | sed -n 's/^.*\/\([0-9]\+\)$/\1/p')"
if [ -z "$github_pr_number" ]; then
>&2 echo 'GitHub PR number not found'
exit 1
fi
# Fetch target branch name
curl -L "https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64" -o jq
chmod +x jq
url="https://api.github.com/repos/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/pulls/$github_pr_number"
target_branch=$(curl -H "Authorization: $GITHUB_SECRET_TOKEN" "$url" | ./jq '.base.ref' | tr -d '"')
if [ -z "$target_branch" ]; then
>&2 echo 'Failed to fetch GitHub PR target branch'
exit 1
fi
echo : "
CircleCI Automerge Pull Request
Repo: $CIRCLE_PROJECT_REPONAME
Pull Request: $github_pr_number
Merging: $CIRCLE_BRANCH >> $target_branch
"
# Merge PR via GitHub API
curl \
-X PUT \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $GITHUB_SECRET_TOKEN" \
"https://api.github.com/repos/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/pulls/$github_pr_number/merge" \
-d '{"commit_title":"CircleCI automerge '"$CIRCLE_BRANCH >> $target_branch"'", "sha": "'"$CIRCLE_SHA1"'"}'
CircleCI Automerge Github PR
Automatically Merge Successful GitHub Pull Requests on CircleCI
Add script to project
Add to project in suitable scripts directory:
./scripts/circle-ci/circle-ci-github-pr-automerge.sh
Make sure it is excutable:
chmod +x ./scripts/circle-ci/circle-ci-github-pr-automerge.sh
Configure CircleCI
Then add the run the script after tests have completed in the project .circle-ci/config.yml
. For example:
jobs:
test:
docker:
- image: circleci/ruby:2.7.2-node-browsers
steps:
- checkout
- ruby/install-deps
- ruby/rspec-test
- run:
name: Automerge PR
command: |
set +e
./scripts/circle-ci/circle-ci-github-pr-automerge.sh
if [ $? = 0 ]; then
echo 'Merge successful'
else
echo 'No merge'
fi
The 'Automerge PR' run command first sets the shell -e
flag to prevent immediate exiting if the automerge script returns a non-zero exit code (which it will if there is no need for merge or fails). Next, it runs the script and echos the outcome.
Set environment in CircleCI
Generate a GitHub Personal Access Token in github.com/settings/tokens with public or private repo access. This allows the script to fetch information about the pull request from GitHub, and process the merge.
Ensure the required secret environment variables are set in the build by adding them using the CircleCI project settings:
GITHUB_SECRET_TOKEN=<github-personal-access-token>
Create GitHub action
CircleCI does not automatically trigger a pipeline (build) on the creation of a github pull request, meaning if the pipeline for the commit has already been triggered in CircleCI before the pull request is created (which is common), the required pull request environment variables will not be present, and the automerge script will fail.
To get around this, create a basic GitHub action for the project which triggers a new CircleCI pipeline.
Add a new GitHub action workflow in GitHub workflows .github/workflows/main.yml
:
name: CI
on:
pull_request:
types: [opened,reopened]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: 'Trigger CircleCI PR Build'
env:
CIRCLECI_API_TOKEN: ${{ secrets.CIRCLECI_API_TOKEN }}
run: |
curl -X POST \
-H "Circle-Token: $CIRCLECI_API_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d "{\"branch\":\"$GITHUB_HEAD_REF\"}" \
"https://circleci.com/api/v2/project/gh/$GITHUB_REPOSITORY/pipeline"
Create a CircleCI API token to allow GitHub to trigger the pipeline. Then save the token as an encrypted secret called CIRCLECI_API_TOKEN
in the GitHub project settings.