Skip to main content

My Dependabot configuration for Drupal (and other PHP projects)

Published on

I use GitHub to host my repositories, such as this website. To keep my dependencies up-to-date, I leverage Dependabot. The product has matured a lot over the past few years. Before, it was a standalone service and then acquired by GitHub. It did not support dependencies managed by Composer. It was pretty spammy and very noisy. However, it has drastically improved over the past few years. Thanks to all of those at GitHub who have worked to improve it (that includes you, Mike Crittenden.)

My Dependabot configuration consists of a few items, nothing overly specific.

  • Defining each ecosystem in my repository (GitHub Actions, Composer, NPM)
  • Specifying a schedule for that ecosystem
  • Setting up ignore rules, such as avoiding major version bumps
  • Defining groups to combine packages that have batched releases.

I'll walk through the different configuration options. At the end of the blog post, I have two examples: one for my blog and another for a Laravel application with a Vue.js frontend. I recommend reading the full documentation for the dependabot.yml configuration options, as I barely scratch the surface of my usage.

To configure Dependabot, you must have the dependabot.yml file in your .github directory.

First, all dependabot.yml files must start with the version key and contain an updates key. All of the package ecosystem configurations will go as an array under updates.

version: 2
updates:
  -

Now we can start flushing out the file.

Defining ecosystems for dependency updates

Since we're working with a Drupal site, we have Composer as a package ecosystem.

version: 2
updates:
  - package-ecosystem: "composer"
    directory: "/"

The directory key is required; Dependabot doesn't provide a default. This tells Dependabot that there is a composer.json and composer.lock file in the root of the repository (/).

More than likely, the Drupal theme uses tooling for CSS and JavaScript, so we need to add NPM as an ecosystem. In my experience, projects end up having the package.json in the theme directory rather than in the project's root.

version: 2
updates:
  - package-ecosystem: "composer"
    directory: "/"

  - package-ecosystem: "npm"
    directory: "/web/themes/custom/mytheme"

This assumes the package.json and relevant lock file (yarn.lock or package-lock.json) is located at web/themes/custom/mytheme. If you're using Yarn or pnpm over NPM, the ecosystem key is still npm.

Let's say your Drupal project uses GitHub Actions for its continuous integration workflows. If you're using any GitHub Actions, those are also versioned and must stay updated. We can add the GitHub Actions ecosystem for that.

version: 2
updates:
  - package-ecosystem: "composer"
    directory: "/"

  - package-ecosystem: "npm"
    directory: "/web/themes/custom/mytheme"
    
  - package-ecosystem: "github-actions"
    directory: "/"

Note, for GitHub Actions, you do not need to specify the directory as .github/workflows, only /.

Now, we'll begin to receive automatic updates for dependency! But, Dependabot will assign a random schedule for delivering them. Leading to chaos and a lot of frustration with earlier versions of Dependabot.

Specifying a schedule to more easily manage dependency updates

I like to receive my updates weekly. You can have it run daily, weekly, or monthly. Dependabot seems to have a limit on the number of updates it'll provide, so I wish you could configure specific days, like Monday and Thursday in case you have a lot of dependencies that may have been updated.

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

  - package-ecosystem: "npm"
    directory: "/web/themes/custom/mytheme"
    schedule:
      interval: "weekly"    

  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"

By default, weekly updates are delivered on Monday but can be configured to a specific day of the week.

  - package-ecosystem: "composer"
    directory: "/"
    schedule:
      interval: "tuesday"

Now, we've got scheduled updates to wrangle in dependency management chaos.

Setting up ignore rules to wrangle unwanted version bumps

What irritates me about Dependabot is how it will make a pull request to bump a dependency to a whole new major version when it does not match your semantic version constraints. For example, I had drupal/core-recommended set to ~9.5.0 in my composer.json. When Drupal 10.0.0 was released, I received a pull request bumping drupal/core-recommended to 10.0.0. That's not a valid update.

Luckily, we can use ignore to specify rules for ignoring specific dependencies or types of updates.

version: 2
updates:
  - package-ecosystem: "composer"
    directory: "/"
    schedule:
      interval: "weekly"
    ignore:
      - dependency-name: "drupal/core*"
        update-types: ["version-update:semver-major"]

This uses a wildcard to tell Dependabot to ignore major version updates for drupal/core, drupal/core-recommended, drupal/core-composer-scaffold, and drupal/core-dev. In the examples at the end, I also use the same for Symfony and Laravel.

Instead of using update-types you can also use versions to ignore specific versions. I don't recommend this for Composer dependencies, as you should use the conflict package links.

Now, let's group related updates to reduce pull requests for framework packages.

Grouping dependency updates

I was excited once Dependabot rolled out the grouped version updates. When working with frameworks that have multiple packages released simultaneously, it combines the updates into one pull request. This helps avoid spam when Drupal core has a release, and you have to upgrade drupal/core and drupal/core-composer-scaffold along with the metapackages drupal/core-recommended and drupal/core-dev. The same goes for other frameworks with various components that may be released simultaneously, such as Symfony or Laravel.

version: 2
updates:
  - package-ecosystem: "composer"
    directory: "/"
    schedule:
      interval: "weekly"
    ignore:
      - dependency-name: "drupal/core*"
        update-types: ["version-update:semver-major"]
    groups:
      drupal-core:
        patterns:
          - "drupal/core*"

We can use * for wildcards here, as well.

Examples

Here is the dependabot.yml for my Drupal site. I use the Gin theme, which has companion modules, Gin Toolbar and Gin Login, also released at similar intervals. So I grouped them as well.

version: 2
updates:
  - package-ecosystem: "composer"
    directory: "/"
    schedule:
      interval: "weekly"
    ignore:
      - dependency-name: "drupal/core*"
        update-types: ["version-update:semver-major"]
    groups:
      drupal-core:
        patterns:
          - "drupal/core"
          - "drupal/core-composer-scaffold"
          - "drupal/core-recommended"
          - "drupal/core-dev"
      gin:
        patterns:
          - "drupal/gin"
          - "drupal/gin_login"
          - "drupal/gin_toolbar"
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"

Here is one from a Laravel application that uses a Vue.js frontend. I grouped the Symfony and Laravel updates and ignored major version updates.

version: 2
updates:
  - package-ecosystem: "composer"
    directory: "/"
    schedule:
      interval: "weekly"
    ignore:
      - dependency-name: "symfony/*"
        update-types: ["version-update:semver-major"]
      - dependency-name: "laravel/*"
        update-types: ["version-update:semver-major"]
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"

Here is my configuration file for drupal-mrn.dev, a monorepo containing a backend API and single page application frontend.

version: 2
updates:
  - package-ecosystem: "composer"
    directory: "/api"
    schedule:
      interval: "weekly"
  - package-ecosystem: "npm"
    directory: "/api"
    schedule:
      interval: "weekly"
  - package-ecosystem: "npm"
    directory: "/app"
    schedule:
      interval: "weekly"
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"

I'm available for one-on-one consulting calls – click here to book a meeting with me 🗓️