A good year ago it was announced that Dependabot is being integrated natively into GitHub. This task is soon complete, as the old Dependabot ("Dependabot Preview") will be shut down on August 3rd, 2021.1
A feature that is still missing in the native GitHub integration is the option to auto merge Dependabot Pull Requests after a successful CI run.
As so often these days, I've solved this problem by using GitHub Actions. Here's how I've done it.
Before we begin#
On March 1st, 2021 GitHub changed how permissions work in GitHub Actions runs triggered by Dependabot. Since March 1st the GITHUB_TOKEN
is ready only.
This means that any Workflow run that is triggered by Dependabot can not change anything in your repository. It can't add new files nor can it auto merge the Pull Request. (This change broke my previous approach to auto-merge which ran in the same Workflow as my normal Continous Integration checks)
The Workflow#
First you need a GitHub Actions Workflow that tests that the introduced changes didn't break anything.
This Workflow ususally runs your test suite or generates a new build of your software.
In this article we're going to use my Alfred Emoji pack project as an example. It's a PHP console application that generates an Emoji snippet pack for Alfred.
I've called the Workflow "Integrate" and it looks like this:
name: Integrate
on:
push:
branches:
- main
pull_request:
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.0
extension: zip, json
- name: Install dependencies
run: composer install --prefer-dist --no-interaction --no-suggest
- name: Generate new Emoji Pack
run: php app generate
If you're new to GitHub Actions, this syntax might look confusing. But don't worry, it's easy to understand. The code above tells GitHub Actions:
- To run this Workflow whenever a commit is made to the
main
-branch or when a Pull Request is opened or a new commit is made to a Pull Request. - To run this Workflow on a server running Ubuntu.
- To install PHP 8.0 and the project's dependencies
- And to execute
php app generate
to create a new Snippet pack
This simple Workflow ensures that the app works as expected. In an application with a Phpunit test suite you would run vendor/bin/phpunit
instead of php app generate
. Or if you work in Node you might run something like npm run test
.
Now that we can be sure that nothing breaks when Dependabot opens a Pull Request, we want to automatically merge it.
For this we create a new Workflow which uses the fantastic ridedott/merge-me Action. First create a new file in .github/workflows
called auto-merge.yml
.
Inside we add the following code:
name: Merge me!
on:
workflow_run:
types:
- completed
workflows:
- 'Integrate'
jobs:
merge-me:
name: Merge me!
runs-on: ubuntu-latest
steps:
- name: Merge me!
if: ${{ github.event.workflow_run.conclusion == 'success' }}
uses: ridedott/merge-me-action@v2
with:
# Depending on branch prodtection rules, a manually populated
# `GITHUB_TOKEN_WORKAROUND` secret with permissions to push to
# a protected branch must be used.
#
# When using a custom token, it is recommended to leave the following
# comment for other developers to be aware of the reasoning behind it:
#
# This must be used as GitHub Actions token does not support pushing
# to protected branches.
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PRESET: DEPENDABOT_MINOR
The code is straight from the example of the Action itself. But I would like to go through the Workflow quickly and explain what it does.
on:
workflow_run:
types:
- completed
workflows:
- 'Integrate'
At the beginning, we tell the Workflow to listen to the completed
event of other Workflows. As you can see under the workflows
array, I've added the name of my previously mentioned Workflow "Integrate". This means that this Workflow will be triggered, whenever my "Integrate" run is completed.
steps:
- name: Merge me!
if: ${{ github.event.workflow_run.conclusion == 'success' }}
uses: ridedott/merge-me-action@v2
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PRESET: DEPENDABOT_MINOR
Next to the core of the Workflow. Before the ridedott/merge-me-action
is executed, we check if the "Integrate" run – that triggered this Workflow run – was successful. This protects us from auto merging Dependabot Pull Requests which break our application.
As my repository doesn't use protected branches, I use the default token GitHub provides by using secrets.GITHUB_TOKEN
. (Read the merge-me-action
docs for more details on how to use it with protected branches).
The PRESET
is set to DEPENDABOT_MINOR
. This will tell the Action to merge minor and patch dependency updates automatically. If you want to go the safer route, use DEPENDABOT_PATCH
to only merge patch dependency updates. (Read more about this feature in the docs)
And that's it!
Commit and push the new auto-merge.yml
Workflow to your GitHub repository and when new Dependabot Pull Requests come in, they will be automatically be merged if your test suite or build is successful.
Example Pull Request#
As mentioned earlier, the "Integrate" Workflow is from my "alfred-emoji-pack" project. In #17 you find a Pull Request that has been created by Dependabot and has then been automatically merged by GitHub Actions.
Conclusion#
As you can see, adding an auto-merge feature to your GitHub repository isn't that complicated at all. All you need is an existing Workflow that checks if everything in your app works and a second Workflow that "listens" to your first "Continous Integration" Workflow.
I hope that the native integration of Dependabot in GitHub is now stable enough that this approach will still work in 12 months time and will save me countless hours of merging Pull Requests.
Before I leave you, there is one caveat: The "auto-merge" Workflow run will not be shown in the Pull Request "checks" list, as the Workflow is not triggered through the pull_request
Event.
- I've learned about the end of Dependabot Preview through a Pull Request in my dotfiles repository. ↩
Top comments (1)
Might want to simplify this with some branch protection rules, the GitHub cli (gh), and a really simple GitHub workflow: dev.to/jpoehnelt/automatically-app...