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"
Want more? Sign up for my weekly newsletter