All of our projects have external dependencies.
It's always a good idea to keep them up-to-date. Here are a few reasons why:
Fortunately, dependabot is here to save the day.
It's a tool from GitHub that can be easily integrated with your repositories. If you haven't heard about it yet, go and check their awesome docs.
Dependabot monitors for vulnerabilities and updates in the dependencies of your project.
It opens PRs, to a target branch, on a scheduled period of time.
Each PR contains:
package.json
or the requirements.txt
file.The pull requests are opened per dependency, meaning that if there are 10 packages that need to be updated, dependabot will open 10 PRs.
Additionally, when we merge something, dependabot will rebase the rest of its opened PRs. This is great because dependabot will automatically make sure that the PR is against the latest version of the target branch.
We're free to decide what to do with the dependabot's PRs:
In this blog post, we'll tell you what's the process that we follow.
We'll go through the basic depentabot setup.
Create a dependabot.yml
file. It should be located in the .github/
directory of your repository.
your_repository/
|-- .github/
| |-- dependabot.yml
Add the following lines to the file and save it:
version: 2
updates:
# Enable version updates for Python
- package-ecosystem: "pip"
directory: "/"
# Check for updates once a week
schedule:
interval: "weekly"
NOTE! We're going to setup dependabot for a Python repository. Change the package-ecosystem
if you'd like to make it work for another language. Here is a list of all available options.
You can find a full list of the .yml
config options here.
Push this file to the default branch of your your origin and you're ready! Dependabot will start making PRs to your repository every week.
You can assert if everything is fine by checking the Dependency Graph
under the Insights
tab in your GitHub repository. Click on Dependabot
and you should see something like this:
In most cases, you'd be good to go with the default Dependabot configuration.
In case merging dependency updates straight to your default branch sounds a bit reckless to you, we can improve our setup.
The potential issues of merging straight to the default branch are:
If we want to avoid that, we have a couple of options:
We prefer the second option. Here is what we need to do next to accomplish that.
Create a new branch and push it to our origin.
$ git checkout master
$ git pull origin master
$ git checkout -b dependencies
$ git push origin dependencies
Now, go to the .github/workflows/dependabot.yml
file and add target-branch: "dependencies"
. Here is how the file should look like:
version: 2
updates:
# Enable version updates for Python
- package-ecosystem: "pip"
directory: "/"
# Check for updates once a week
schedule:
interval: "weekly"
target-branch: "dependencies"
That's it! The next time dependabot creates a new PR it'll be targeted to the new dependencies
branch.
Our goal is to merge all dependabot PRs into the dependencies
branch. This will allow us to test if everything is fine with them before we push them to our default branch.
Here is how a typical PR from the dependencies
branch would look like once we merge all of the dependabot PRs:
There are a couple of considerations that we need to take into account about our new dependencies
branch:
We have a branch rule in our repository - the branches of all PRs that are merged are being deleted after that. We don't want this for the dependencies
branch. We don't want to allow anybody to delete it at all.
We can prevent this from happening by adding a new branch protection rule.
Go to your GitHub repository settings and a new branch protection rule:
We also want to allow force pushes to your branch (it's disabled by default). This will let you fix the branch if there is a problem with the git history.
Here is what we've achieved so far:
dependencies
branch.dependencies
branch.dependencies
into the default branch and we are good to go.The problem here is at the 4th step.
We want dependencies
to always be up to date with our default branch.
This is something that we can easily forget to do, since it needs to be done by hand.
Wouldn't it be nice if we can keep dependencies
equal with the default branch without doing any extra manual actions?
Here is how we solved this. GitHub Actions is the tool that we're searching for!
Heads up 👀 We have additional GitHub Actions related articles - GitHub Actions in action - Setting up Django and Postgres and Optimize Django build to run faster on GitHub Actions
To set up a new GitHub action, we need to add a new .yml
file (we name it rebase_dependencies.yml
) to our .github
directory. It should be located in the workflows
folder.
your_repository/
|-- .github/
| |-- workflows/
| | | -- rebase_dependencies.yml
| |-- dependabot.yml
Here is the content of your file:
name: Automatic Rebase
on:
push:
branches:
- master
jobs:
rebase:
name: Rebase `dependencies` with `master`
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # otherwise, you will fail to push refs to dest repo
ref: dependencies
- run: |
git config user.name github-actions
git config user.email github-actions@github.com
git rebase origin/master
git push origin dependencies --force
Here is what this configuration means in simple words:
dependencies
branch--force
because of the rebase
It's fine if you prefer to use --force-with-lease
to prevent from some unexpected outcomes.
If you don't want to use the built-in github-actions
user, you can add a new PAT and configure the action to work with the user that's associated with it.
You can refer to the docs of the actions/checkout
base action if you want to change it to fit your needs. Here are the docs of GitHub Actions as well.
To assert that everything is fine with our new workflow, we can go to the Actions
tab in the GitHub Repository. The name of the workflow ("Automatic Rebase") should be visible in the left sidebar:
We should see a new workflow run on every new commit in the master
branch.
In this article, we showed you how we use the powers of GitHub Actions and dependabot to keep the external dependencies of our projects up-to-date.
We hope we make your dev life better!
Stay tuned to our blog for more posts like this!