Intro
As Software Engineers we love to automate stuff, especially if tasks are repeating and boring. Automated dependency updates are a very good example for such a task.
Luckily, we don't have to develop our own solution as there are multiple (free to use) bots at the market. The most popular ones are Greenkeeper, Dependabot (meanwhile integrated in GitHub) and Renovate Bot.
I personally like Renovate the most, because it comes with tons of features and configuration capabilites. While in a first view, those bots feel powerful and helpful, we quickly feel overwhelmed by the noise produced by them. Also our CI-system needs to deal with the heavy load.
Just have a look on the latest Onboarding PR
in my current repository. Allthough it is quite young, Renovate wants to create 27 (!) PRs right away:
For me, it is clear, that we have to come up with some strategies to better control the automation. Renovate also recognized this problem and provides some useful tips on their documentation page. The following 5 + 1 tips are based on Renovates documentation and my practical experience of running Renovate in a Nx-based monorepository at my company.
1. Tip: Build Package Groups
The first tip is - for me - the most obvious, but also the most powerful configuration option of Renovate: Package Grouping.
If you get started with Renovate and you extend the config:base
preset, you already make use of this feature, because the base-config itself contains the group:monorepos
preset. This ruleset in turn contains the logic to group Dependency updates of multiple packages from one monorepository in just one PR. Here you can see an all supported packages. The most famous ones are for sure @angular/*
or react
packages.
If you like to extend this logic, you can simply create your own groups:
{
"packageRules": [
{
"matchPackagePatterns": ["eslint"],
"groupName": "eslint"
}
]
}
The reason, why I think this feature is so powerful is, that you not only reduce the amount of PRs with ease, you can also apply most of the configuration options for that specific group while you follow totally different strategies in other groups.
2. Tip: Scheduling
The second tip is about scheduling. You could either use an existing scheduling preset or you configure the intended behaviour by hand.
I personally prefer the existing presets, because they already cover my needs. See the schedule nonOfficeHours
as an example:
{
"schedule": [
"after 10pm every weekday",
"before 5am every weekday",
"every weekend"
]
}
Usually we don't work during this time. This means we can be sure, that builds caused by Renovate don't steal resources from our CI-system when we need it and we can focus on feature development.
Another strategy could be to apply different scheduling strategies for different dependency groups. Maybe it is suficient for you to update devDependencies
just once a month while you want to stay up to date in your production dependencies
asap.
3. Tip: Automerging
What are the best dependency updates? Those you didn't even notice, right? Automerging is a feature, which could help you there.
If you set automergeType=branch
, you can achieve exactly this.
Renovate will first open a new branch with the update and waits for your CI system to pass all pipeline checks. If everything still works and all tests are passing, the branch is directly integrated without creating a PR. Only if the Pipeline fails, Renovate will take care to create a PR to notify you about the update and its state.
In general, I would not recommend you to use this for every dependency and update type. But for some non-critical ones, it can be very helpful. Also you need to ensure, that you can rely on your CI pipeline.
4. Tip: Limiting amount of PRs
Another useful tip is to limit the amount of (concurrent) PRs. Renovate knows two different types of limitation.
The first limitation is by hour. You can configure it with "prHourlyLimit": 3
.
The second limitation is meant in total, so that you will never receive more than the configured amount of concurrent PRs. You can configure it with "prConcurrentLimit": 5
This setting might also save you some valuable resources in your CI system. Also, if you combine it with the Dashboard
feature, you will most likely not loose the overview about open PRs. Instead, Renovate will open a GitHub Issue in your repository, where you can get an overview of updates, that are currently hold back by your rate limit.
On top of it, you can combine it with another configuration called priority. Here you can basically set a priority index
for a dependency (group). The higher the number, the earlier an update is applied.
5. Tip: Excluding Dependencies and Update Types
The last tip might also seem obvious, but let me explain it to you.
Let's begin with exluding entire dependencies
. Of course you can simply disable a entire dependency, but what I am acually aiming for are dependencies in subdirectories of your repository. Especially if you work in a monorepository, maybe with Lerna or Nx, you will most likely have multiple package.json
files.
It's not always the case, that we want renovate considering these dependencies as well.
Therefore you can use the ignorePath configuration:
{
"ignorePaths": ["**/examples/**"]
}
Other avoidable PRs are those, which you better update by hand, like major
updates of your used framework, possibly with breaking changes
. In many cases, framework authors provide some code mods
or updaters
, like the schematics
in the area of Angular and Nx. Also typescript sometimes requires manual steps even for minor
updates.
You can use the matchUpdateType configuration to set your intended strategy:
{
"packageRules": [
{
"matchUpdateTypes": ["major"],
"labels": ["UPDATE-MAJOR"]
}
]
}
5 + 1 Tip: Disable Renovate
Last but not least, take into consideration, that you disable Renovate entirely. Allthough it is an automation solution, which should save you time, it still requires time from you.
For me, it only makes sense to use Dependency Bots within repositories, which are long-living and you really want to work on the project continuously. If that's not the case, maybe in the case of a sideproject or a learning project, I would not recommend to enable it. In these cases, the focus should be different and you most likely don't need the latest updates in your project and if you come back after weeks or months to continue, you don't want to be bothered by thousands of open PRs.
Bonus Tip: Renovate Config Validator
Have you heard about the renovate-config-validator
?
If you now want to change your existing config, it is worth to verify the config before you integrate it into your main branch.
Therefore you can use the renovate-config-validator:
# Install renovate globally
npm install renovate -g
# Execute this command in the root of your repo
npx renovate-config-validator
That's all from my side. Do you know other helpful tips or strategies? If yes, write them in the comments below.
Happy Coding :-)
Top comments (0)