Autoupdating Project Dependencies

Photo by Sigmund on Unsplash

Autoupdating Project Dependencies

The ultimate Dependabot setup guide with a working real-life project example.

Introduction

Most probably you've heard about Dependabot. It's a GitHub service that checks if your project dependencies have new releases, and updates your project, automatically.

I believe it's a great help to many, many developers.

However, it requires non-trivial configuration effort. This article is an ultimate go-to guide to set it up.

Throughout the article, I'll use my current pet project - osmianski/docs. It's a SaaS that turns Notion workspaces and GitHub repositories into beautiful documentation websites.

This project is a working example of the described configuration. Use it in your own project as is, or modify as needed.

All you need to know about dependencies

A "dependency" is just a fancy name for libraries and frameworks that you use in your project. For example, my project uses Laravel and Vue - these are my project dependencies.

Whatever the programming language, project dependencies are managed in a similar fashoin:

  1. Require project dependencies in certain files.

    For example, my project lists PHP and JavaScript dependencies in composer.json and package.json files, respectively:

     # composer.json
     {
         ...
         "require": {
             "laravel/framework": "^9.19",
             ...
         },
         ...
     }
    
     # package.json
     {
         ...
         "devDependencies": {
             ...
             "vue": "^3.2.39"
         },
         ...
     }
    

    Use version constraint syntax to specify what dependency version you need.

  2. Use a language-specific dependency management tool to install project dependencies. In my project, I use Composer to manage PHP dependencies, and NPM to manage JavaScript dependencies:

     composer install
     npm install
    

    Dependency managers download requested dependencies (and their dependencies, recursively). In my project, Composer stores downloaded dependencies in the vendor/ directory, and NPM - in the node_modules/ directory.

    Dependency managers also store information about exact installed dependency versions in "lock" files. Composer stores them in the composer.lock file, NPM - in the package-lock.json file.

  3. Use Composer and NPM to update project dependencies to the latest version:

     composer update
     npm update
    

How Dependabot works

Almost every single day a new version of some project dependency is released. Security fixes, bug fixes, new features - it makes total sense to get all of them into your project.

Updating dependencies on a periodical basis requires certain discipline, and often just doesn't happen.

Here is where Dependabot comes steps in. Using the configuration that is described in this article:

  1. Weekly, it checks if any security fixes, bug fixes or new features have been released in any of your dependencies.
  2. It opens a pull request for each new release to be installed into your project. In practice, Dependabot pull requests modify composer.lock and package-lock.json files.
  3. It checks if new depedency version, once installed doesn't break anything in your project.
  4. It merges the pull request into the current branch, closes the pull request, and deletes the temporary pull request branch.

Dependabot configuration

Sounds awesome, let's configure it!

dependabot.yml

First, specify which ecosystems and how often should be checked for updates in the .github/dependabot.yml file:

# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
  - package-ecosystem: "composer"
    directory: "/"
    schedule:
      interval: "weekly"

  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"

auto-merge.yml

Second, define a GitHub action that automatically merges and closes Dependabot pull requests in the .github/workflows/auto-merge.yml file:

# Automatically merges Dependabot pull requests
name: auto-merge

on:
  pull_request_target:

jobs:
  auto-merge:
    runs-on: ubuntu-latest
    if: github.actor == 'dependabot[bot]'

    steps:
      # bot approve
      - uses: hmarr/auto-approve-action@v2
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}

      # bot approve and merge request
      - uses: ahmadnassri/action-dependabot-auto-merge@v2
        with:
          target: minor
          github-token: ${{ secrets.AUTOMERGE_TOKEN }}

AUTOMERGE_TOKEN

Then, in your personal settings, define the personal GitHub token to be used in the auto-merge GitHub action, and add it to the Secrets section of the auto-merge GitHub action:

  1. In your GitHub profile Settings -> Developer Settings -> Personal access tokens -> Tokens (classic), press Generate new token -> Generate new token (classic) fill it in as shown below and press Generate token:

    New personal access token

    • Name: AUTOMERGE_TOKEN
    • Expiration: No expiration
    • Select scopes: check repo scope
  2. Copy the generated token to clipboard using the copy icon:

    Copy personal access token

  3. In the GitHub repository -> Settings -> Secrets -> Actions, press New repository secret, fill it in as shown below, and press Add secret:

    Add personal access token to repository secrets

    • Name: AUTOMERGE_TOKEN
    • Secret: paste the generated personal access token

Repository settings

Finally, change GitHub repository -> Settings -> General settings:

Repository settings

  • Allow auto-merge
  • Automatically delete head branches

Wrapping up

And this is it!

After implementing automatic dependency updates in my project, issues in my dependencies get fixed automatically without me even noticing.