Dependabot for private packages
At Multiverse, I work on our design system and related tooling.
One common issue I’ve come across is keeping our dependencies up to date.
Relying solely on manual updates from teams working in very different areas of the business can be time-consuming and error-prone. And, understandably, projects can find themselves falling behind on updates, especially when updates are coming in thick and fast!
Enter Dependabot
Dependabot is a great tool for keeping dependencies up to date. It works by opening Pull Requests when new versions of your dependencies are released. The frequency of these PRs can be configured to suit your needs.
Companies like Github, Shopify, and Gitlab use Dependabot to keep their dependencies up to date and secure. Urgent security patches are flagged immediately by Dependabot.
Although Dependabot is awesome, it has a big limitation: By default, it will only work with public packages.
To make full use of it’s capabilities, I need it to be able to work with private packages, hosted in Github’s Package Registry.
Setting up the config
Dependabot is configured using a .dependabot/config.yml
file in your repository. Here, you specify all sorts of options, like the package ecosystem, frequency of updates, and the branches to monitor.
Here’s a basic example config:
version: 2
updates:
- package-ecosystem: npm
open-pull-requests-limit: 3
schedule:
interval: daily
The above should be pretty self explanatory, but this config will check for updates to npm packages daily and open a maximum of 3 PRs at a time.
Simple!
Adding private packages
We need to tell Dependabot how to access our private packages. This is done by adding a registries
section to the config.
registries:
github-packages:
type: npm-registry
url: https://npm.pkg.github.com
token: ${{secrets.DEPENDABOT_GITHUB_PACKAGES_TOKEN}}
And reference that registry in the updates
section:
updates:
- package-ecosystem: npm
registries:
- 'github-packages'
# ...other options
The token
is a Github Personal Access Token with the read:packages
scope. This token should be stored as a secret in your repository in the “dependabot” section: https://github.com/ORG/REPO/settings/secrets/dependabot
Complete config example
version: 2
updates:
- package-ecosystem: npm
open-pull-requests-limit: 3
schedule:
interval: daily
registries:
- 'github-packages'
registries:
github-packages:
type: npm-registry
url: https://npm.pkg.github.com
token: ${{secrets.DEPENDABOT_GITHUB_PACKAGES_TOKEN}}
Existing yarn & npm configs
You probably already have a .npmrc
or .yarnrc.yml
file in your repository to authenticate with Github Packages. You can use the same token for Dependabot.
However there is one caveat: Dependabot does not understand environment variables in either of these files.
# .yarnrc.yml
npmScopes:
c-sinclair:
npmAlwaysAuth: true
npmAuthToken: ${GITHUB_PACKAGES_TOKEN}
npmRegistryServer: 'https://npm.pkg.github.com'
npmPublishRegistry: 'https://npm.pkg.github.com'
The above will cause Dependabot to fail with an error, so you’ll need to omit the npmAuthToken
line from the file.
My solution was to use .yarnrc.yml
and .npmrc
which live in my home ~
directory, so my local machine can fetch private packages, which dependents relies on its own ${{secrets. }}
token provided by Github.
The in CI, I have a line before the yarn install
to copy the .yarnrc.yml
file to the root of the CI container.
# .github/workflows/ci.yml
jobs:
build:
runs-on: ubuntu-latest
env:
GITHUB_READ_PACKAGES_TOKEN: ${{secrets.GITHUB_TOKEN}}
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Add Github token to yarn and npm config
run: |
echo "//npm.pkg.github.com/:_authToken=${GITHUB_READ_PACKAGES_TOKEN}" > ~/.npmrc
echo "npmScopes:
c-sinclair:
npmAlwaysAuth: true
npmAuthToken: ${GITHUB_READ_PACKAGES_TOKEN}
npmRegistryServer: 'https://npm.pkg.github.com\'
" > ~/.yarnrc.yml
- name: Install dependencies
run: yarn install
Conclusion
I hope this guide is an aid to you when setting up Dependabot for your private packages. So far I only have positive feedback from my team, and let’s just say we’re all a lot more up to date with our dependencies now!