See here for a high-level introduction.
github-review-helper is a little bot that you can set up GitHub hooks for to improve your project's PR review flow. It currently does 4 things:
- It observes all PRs and detects if any
fixup!orsquash!commits are included in the PR. If there are, it uses the GitHub status API to mark the PR as pending withreview/squashcontext. If there are no fixup or squash commits, it marks the PR as success. This allows one to set thereview/squashsuccess status as required in the repo's GitHub settings to make sure no PR that includes fixup or squash commits gets accidentally merged. - It observes all PR comments (comments on the unified diff or the individual
commits don't count) and if it sees a command of
!squash, it tries to autosquash (equivalent of runninggit rebase --interactive --autosquashmanually and instantly closing and saving the interactive rebase editor) all the commits in the PR. Success/failure will be reflected by thereview/squashstatus. - Similarly to
!squash, it also listens for!checkcommands. The!checkcommand can be used to force the bot to (re-)check the current PR forfixup!andsquash!commits. This can be useful when some webhooks didn't reach the bot properly or when you have reason to believe that the bot didn't correctly evaluate your PR automatically. Which can sometimes happen, because the bot is fast and can at times fetch data from the GitHub API before that data has been updated, causing the bot to make it's judgment based on outdated data. - It listens for
!mergecommands.!mergecommand will squash the PR (exactly like!squashwould) if needed and will then merge the PR as soon as all required status checks are marked as "success". If any of the status checks fail after that, the bot will cancel the merging process (indicated by a 'merging' label on the PR) and will notify the PR's author.
The bot supports two authentication methods. You must configure exactly one.
This is the simpler option. Create a token following GitHub's
documentation
and note it down. You will use it as the GITHUB_ACCESS_TOKEN environment variable.
A GitHub App provides fine-grained permissions and doesn't tie the bot to a personal account. To set one up:
- Go to GitHub Settings > Developer settings > GitHub Apps > New GitHub App
- Fill in the required fields:
- GitHub App name: choose a name (e.g.
review-helper) - Homepage URL: any URL
- Webhook URL: the bot's public URL (e.g. the ngrok address from a later step)
- Webhook secret: the same secret you will use for
GITHUB_SECRET
- GitHub App name: choose a name (e.g.
- Under Repository permissions, grant:
- Contents: Read & write (for git push during squash/rebase)
- Commit statuses: Read & write (for creating and reading status checks)
- Issues: Read & write (for comments and labels)
- Pull requests: Read & write (for reading PR data and merging)
- Metadata: Read-only (automatically included)
- Under Subscribe to events, select:
- Issue comment
- Pull request
- Status
- No organization or user permissions are needed
- Click Create GitHub App
- On the app's settings page, note the App ID
- Generate a private key and download the
.pemfile - Click Install App, install it on the target organization/account, and note
the Installation ID (visible in the URL:
https://github.com/settings/installations/<ID>)
With a Personal Access Token:
docker run \
-e GITHUB_ACCESS_TOKEN="the-access-token-you-created-above" \
-e GITHUB_SECRET="a-secret" \
-v ~/.ssh:/etc/secret-volume \
-p 4567:80 \
salemove/github-review-helper
With a GitHub App:
docker run \
-e GITHUB_APP_ID="12345" \
-e GITHUB_APP_PRIVATE_KEY_FILE="/etc/private-key.pem" \
-e GITHUB_APP_INSTALLATION_ID="67890" \
-e GITHUB_SECRET="a-secret" \
-v /path/to/private-key.pem:/etc/private-key.pem:ro \
-v ~/.ssh:/etc/secret-volume \
-p 4567:80 \
salemove/github-review-helper
Note that both snippets mount your local ~/.ssh folder as a volume into the
Docker container. This is required for the bot to be able to connect to your
repositories using git (via SSH). It will use the known_hosts file from that
mounted folder for making sure that your connection to github.com is secure and
the id_rsa file for the SSH identity.
The following commands expect you to have Go installed and your GOPATH to be properly set up. To compile and install the bot, run the following commands:
go get github.com/salemove/github-review-helper
cd $GOPATH/github.com/salemove/github-review-helper
go install
The bot requires some environment variables to be set for it to function. Let's quickly go over each one to see what it is and why it's needed.
PORT: The port the bot will be listening for connections onGITHUB_SECRET: A secret token used to verify that webhook requests are coming from GitHub. GitHub suggests runningruby -rsecurerandom -e 'puts SecureRandom.hex(20)'to generate this token.
For Personal Access Token auth:
GITHUB_ACCESS_TOKEN: The token created in the authentication step above.
For GitHub App auth (all three are required):
GITHUB_APP_ID: The App ID from the GitHub App's settings page.GITHUB_APP_PRIVATE_KEY_FILE: Path to the.pemprivate key file generated for the app.GITHUB_APP_INSTALLATION_ID: The installation ID for the target organization or account.
Now let's start the bot (you can replace $GOPATH/bin/github-review-helper with just github-review-helper if you have
go executables on your path):
With a Personal Access Token:
PORT=4567 GITHUB_ACCESS_TOKEN="the-access-token-you-created-above" GITHUB_SECRET="a-secret" $GOPATH/bin/github-review-helper
With a GitHub App:
PORT=4567 GITHUB_APP_ID="12345" GITHUB_APP_PRIVATE_KEY_FILE="/path/to/key.pem" GITHUB_APP_INSTALLATION_ID="67890" GITHUB_SECRET="a-secret" $GOPATH/bin/github-review-helper
PS: The bot also needs git to be available on path and it expects the user the command is run under to have ssh access to the repositories it is used for.
Leave the bot running and let's now set up a tunnel to localhost. This example depends on ngrok being installed and available on the system (as do the official GitHub webhook docs) to make the bot publicly accessible by GitHub. So go ahead and install it if you haven't already. When you're done, you can create a tunnel by running:
ngrok 4567
You should see something like the following in the output:
Forwarding http://7e9ea9dc.ngrok.com -> 127.0.0.1:4567
Note down the http://*.ngrok.com URL.
Note: If you are using GitHub App authentication, the webhook is configured as part of the app setup. You can skip this section.
To set up a repository webhook on GitHub, head over to the Settings page of your repository, and click on Webhooks & services. After that, click on Add webhook. Then:
- Enter the ngrok address you marked down earlier as the Payload URL
- Leave Content type to be
application/json - Enter the secret token you created before and used to start the bot as the Secret
- Use the Let me set individual events option and select the Issue comment, Pull Request, and Status events from the list that gets opened
- Enable the webhook by leaving the Active checkbox checked
Click on Add webhook to finish the process.
See the GitHub documentation on creating webhooks for more info.
If you wish to have the merge button disabled for PRs with fixup and squash commits in them, then make this status
required. This can be done by going to the repo's Settings on GitHub, then going to the Branches section and
selecting the branch you wish to protect from the Protected branches dropdown (or clicking on Edit next to the
branch, if it's already protected). Now checking the Require status checks to pass before merging checkbox and then
the review/squash context from the displayed list. NB: The bot must have had a change to check at least one PR for the
context to appear in the list.
See the GitHub documentation for a visual guide.
To try it out you can make some changes to your code on a feature branch that you've opened a PR for. Then stage these
changes with git add. Now create a fixup commit for you current HEAD with git commit --fixup=@ and push the
changes. You should see a pending status next to the fixup commit. (If you don't, check the Recent Deliveries
section in your webhook's settings to see what went wrong)
Now to try squashing the fixup commit, try leaving a comment on the PR with a message of only !squash. The bot
should squash the fixup commit and push the new changes. It should also update the last commit's status to success
saying that all fixup commits have been successfully squashed.