Quick Tutorial: Build A Basic Dependency Manager Like Dependabot In 5 Minutes
Scope:_ This project focuses purely on JavaScript and, sure, Typescript 😎 but the same patterns could be applied to other languages and/or systems.
Preface, AKA The Problem
Dependabot is great! Why did I learn how I could replace it?
Over the past 2 years, my beloved tool for updating dependencies seems to be focused on other features, like security alerts, or has abandoned features I used every day, like it's Github app and app interfaces. At the very least, it hasn't provided easy ways to update dependencies for 2 features which are fairly standard for JavaScript development—pnpm and monorepos.
Wait! What is Dependabot?
Well, first off. This post is written from the context of code, using Git, and using code libraries which excel the capability of code. If this is not clear or of interest to you, stop reading now!
Dependabot is tool for managing coding project dependencies that are maintained in a git service. Mainly Github. This is important for security and keeping code up to date! Dependabot does this using release, cron, or other events which are performed by git management tools (Github for this post). When a git management tool event triggers Dependabot to update dependencies, Dependabot does this specked to a yml file configuration, where is runs update commands and will create an update pull request if there are updates.
How Can We Make Our Own Dependabot?
In the paragraph above, I mentioned how Dependabot works. It perfects tasks based on git management events. The cool thing is we can use those events too—just like Dependabot.
1. Create an action that is triggered by a Git event
To build our own Dependabot in 5 mins, let's use cron and a github action like so:
name: update dependencies
on:
schedule:
# This will run at 5am on Monday's
- cron: '0 5 * * 1'
# The cron reference below is for every 5 minutes (useful for debugging)
# - cron: '*/5 * * * *'
Cool. Now we are using a Github Action to run a cron job in a time range that we control!
2. Run a script to update our dependencies
Next up, we'll want to update our dependencies. For this I'm using pnpm—but npm and yarn work the same. Use what you like!
All JavaScript package managers have update commands that can be run to update dependencies!
...
steps:
- uses: actions/checkout@v3
- uses: pnpm/[email protected]
with:
version: latest
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- run: pnpm install --no-frozen-lockfile
- run: pnpm update
3. Finally, we should create a pull request with our updates
Lastly, we'll want to create a PR with our updates. For this, the fastest way is using Peter Evans Create Pull Request Action.
You could build this yourself using the Github API. You can also replicate this functionality using the GH cli but that will take a bit more than 5 minutes.
...
- name: Create Pull Request
uses: peter-evans/create-pull-request@v4
with:
token: ${{ secrets.PR_CREATE_TOKEN }}
commit-message: Update dependencies
title: "[dependencies] update dependencies"
body: |
## Dependency updates
Auto-generated using [create-pull-request][2]
[1]: https://github.com/<org/user name>/<repo name>
[2]: https://github.com/peter-evans/create-pull-request
branch: update-dependencies
Quick note: You'll notice there is a required token in order to be able to create a pull request. That might be another post but here's a link for now!
Here's a summary (aka all the yml)
name: update dependencies
on:
schedule:
- cron: '0 5 * * 1'
# - cron: '*/5 * * * *'
jobs:
udpate-deps:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
steps:
- uses: actions/checkout@v3
- uses: pnpm/[email protected]
with:
version: latest
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- run: pnpm install --no-frozen-lockfile
- run: pnpm update
- name: Create Pull Request
uses: peter-evans/create-pull-request@v4
with:
token: ${{ secrets.PR_CREATE_TOKEN }}
commit-message: Update dependencies
title: "update dependencies"
body: |
## Dependency updates
[1]: https://github.com/<org/user name>/<repo name>
[2]: https://github.com/peter-evans/create-pull-request
branch: update-dependencies
This post is in progress! More to come!