Fully Automated Dependency Upgrades with Dependabot and GitHub Actions
5 min read

Fully Automated Dependency Upgrades with Dependabot and GitHub Actions

Dependabot is an app for GitHub that automates dependency upgrades through pull requests. When maintaining many or large projects, manually merging these pull requests can take quite some time. Luckily, the process can be fully automated with the help of one or two GitHub Actions.
Fully Automated Dependency Upgrades with Dependabot and GitHub Actions

BLUF

For readers interested in the briefest of summaries, here is the bottom line up front:

  1. (Optional) Set up Label Syncer to create an issue label for Dependabot
  2. Assign the label to each pull request Dependabot opens
  3. Set up probot-auto-merge to automatically merge pull requests with this label

Motivation

I consider Dependabot one of the most valuable tools for (open source) maintainers and use it in almost all my projects. It automates an important but very mundane task that is often neglected until issues arise. But enabling Dependabot for many projects can create a lot of work as maintainers have to manually merge its pull requests.

I have been exploring different ways to reduce the support burden of my (open source) projects, and started to invest more in configuration-as-code and automation. As part of this I set up three different tools on GitHub to fully automate Dependabot and create a configuration that I can easily copy to new repositories.

Step 1 – Labels-as-Code

The end result of the first step must be an Issue Label that can be used with Dependabot. The label can be created manually or managed automatically with a GitHub Action. Free free to skip to step 2 if managing the issue labels is not of interest to you.

For me, automating the management of issue labels on GitHub was a small but important step to achieve consistency across my repositories. Many different tools exist to either sync or create labels, and after evaluating a few my choice fell on Label Syncer. Most importantly, its fully configured in code and as a GitHub Action part of the repository it manages.

Configure the Issue Labels

Setting up Label Syncer is pretty straightforward. Make sure to check its repository to learn about all its features and the different ways it can be configured.

First, create a file for the labels in the repository. The file can be placed anywhere, but I picked .github/labels.yml as the path and name. Inside the file list your labels. Each label is given a name, a color, and a description. Please note that Label Syncer will remove any label that is not listed here.

I set up three different labels. The first indicates that the pull request is about a dependency upgrade, and the second two indicate whether the pull request should be merged. You only need the last label to set up this workflow, and you are free to customize this as much as you like. Most importantly, you can name it whatever you want as long as you use the same name throughout the later steps.

# The labels in this file are automatically synced with the repository
# using the micnncim/action-label-syncer action.
---
- name: C-dependency
  color: 1abc9c
  description: "Category: Dependency"
- name: PR-block
  color: 3498db
  description: "Pull Request: Do not merge"
- name: PR-merge
  color: 3498db
  description: "Pull Request: Merge when ready"
.github/labels.yml

Set up the GitHub Action

After configuring the labels we need to run Label Syncer whenever the labels change. The following can again be customized to match your style, but I created a new GitHub Action in .github/workflows/repository.yml that is run whenever new labels are pushed to the default branch.

---
name: Repository

on:
  push:
    branches:
      - main
    paths:
      - .github/labels.yml

jobs:
  labels:
    name: Labels
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Sync labels
        uses: micnncim/action-label-syncer@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          manifest: .github/labels.yml
.github/workflows/repository.yml

After committing and pushing the two files, GitHub will run the action and create the labels.

Step 2 – Dependabot

Dependabot as an app for GitHub that automatically updates project dependencies whenever new versions become available. For each update a new pull request is opened, which can be reviewed and merged by the maintainers of the project.

Dependabot is configured through a YML file in the repository, and I highly recommend reading through the configuration options to understand how it can be customized. Below is an example of my .github/dependabot.yml that updates the GitHub Actions of the repository.

---
version: 2

updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "daily"
    labels:
      - "C-dependency"
      - "PR-merge"
.github/dependabot.yml

The package-ecosystem defines what gets updated in the repository. I tend to have at least two of these blocks, one for GitHub Actions and another for the programming language used in the repository. The directory specifies where the manifest file (e.g. package.json) can be found, and the schedule defines when to check for upgrades.

The part most relevant for this article are the labels, which define what labels are added to the pull request. Add the label that you created in step 1 here. Above, PR-merge is the important label that we will use in step 3.

Commit and push the file. GitHub will immediately run Dependabot, so you might get your first pull request.

Step 3 – Auto-merge Pull Requests

The final step is setting up a GitHub App that automatically merges pull request that have the right label. I am using probot-auto-merge, which is simple to set up but quite powerful if you ever need more control. Check out its repository to learn about its features and configuration.

To set the app up, first go to https://github.com/apps/probot-auto-merge and install it into your account. Then create a new configuration file at .github/auto-merge.yml.

---
requiredLabels:
  - PR-merge

reportStatus: true

probot-auto-merge can be customized quite heavily, but the above is the minimal configuration that is required to automatically merge Dependabot's pull requests. It instructs probot-auto-merge to merge any pull request with the label PR-merge, and report the status of its runs as a check on the pull request. The latter is not required, but very helpful to understand and debug the configuration.

If you have branch protection enabled, the pull request will only be merged if all checks have succeeded. And if you are adding probot-auto-merge to an organization, you need to allow it to push to matching branches.

Branch protection rule

Commit and push the configuration file for probot-auto-merge, and if you received a pull request after step 2, you can test that everything works by assigning the new label to the pull request.

It took me two or three pull requests to get everything hooked up correctly, but Dependabot's comments on the pull request and probot-auto-merge's status check were very helpful to resolve any issues.

Summary

The setup described here has worked really well for me. The fact that all configuration is in code has made it easy to enable the same functionality across all the repositories that I maintain–simply by copying a few files. And automating the mundane task of merging Dependabot's pull requests has freed up time to focus on more impactful work instead.

I have not had any issue with automatic upgrades yet, because my project typically enjoy quite a good test coverage and incompatible versions have always been caught when compiling or testing the code. You might need to test and evaluate if the same is true for your own projects as well. Automatically merging dependency upgrades brings with it certain risks, and you have to assess these risks for yourself.

Lastly, template repositories are another feature of GitHub that you might want to explore if you are interested in consistency across new projects. Adding the configuration from this article to a template repository ensures that every new project created from the template automatically has the right labels and auto-upgrades configured.