Keep Track of Your Software’s Third-Party Libraries

Antonio Bajivić

Working in web development and having fun with electronics brings me joy. In my free time, I mix working out, socializing, and reading.

Last updated Dec 29, 2023

The more you put things off, the harder it gets to actually do them. That goes for dependencies too. Sure, dependencies need to be updated, but that doesn’t make the task any less miserable.

Before I start explaining what a dependency manager is, let me explain what a dependency is. 

Dependencies are third-party libraries that developers add to their projects so their lives would be easier. What that means is that someone wrote a piece of code that other people can use. It also means that it needs to be frequently updated. In most web projects the list of those libraries is located in the package.json file. 

Now that you know what dependency means, I want to introduce you to the idea of dependency management. 

What Is a Dependency Manager and What Issues Have We Confronted?

Did you ever get caught up with a lot of non-updated dependencies and when you began updating them, you realized you missed a lot of things? Some of those updates can be helpful, but some of them can make your life miserable. 

At Productive, as developers we encountered the same issue. Some of our dependencies were out-of-date by several major versions which can lead to real issues, such as deprecations. So we started to think of a way to keep everything up-to-date. 

Manually handling them was not an option anymore. We have several repositories just for front-end projects and it takes a lot of time to track all those dependencies with their release updates. So, we decided to implement a dependency management bot. 

A bot like that not only notifies you about new versions, but it notifies you if a certain package has vulnerabilities. It suggests changes by creating Pull Requests. You’re probably wondering how can dependencies have vulnerabilities now. Well, some of them are depending on other dependencies, or it may be that the developers just wrote some shady code.

Which Dependency Manager Did We Chose?

One of the problems we confront as developers is “notification noise”. 
Nobody likes to see a swamp of notifications and nobody has time to read them one by one. Therefore, we were trying to pick a configurable manager to control the level of noise. A few of them came up in my search—such as Dependabot, Renovate, Snyk, Dependencies.io, Depfu, etc. 

Dependabot is popular, mostly because it’s a GitHub manager, but it’s not quite as configurable as our final choice (wait for it!). One of the great things about Dependabot is that it can be used in combination with other managers (like Renovate). After comparing them, Renovate won. 

Renovate is more configurable and what I mean by that is that we can choose the dependencies that will be checked by it. We can set up a schedule for when the notifications will arrive, we can divide packages into all sorts of different groups we need. If you don’t like the way your PR looks, as you probably guessed—you can edit it. With this manager, you can also set an assignee who will get notified, and much more.

How Do We Use Renovate at Productive?

Task Management

Since we didn’t configure the manager to auto-merge new updates, we need to handle them ourselves. So, when it does its job, usually I handle most of the updates for the Productive app. If there are some dependencies which I’m not so familiar with, I create a task and assign the PR to my colleagues.

Because I read most of the Release notes, sometimes I stumble upon some useful information about how a new update will be helpful for someone and then I inform them because new updates may solve their current workarounds (read: hacky solutions).

When we start updating dependencies we approach them differently. For every major package, one PR is created. For non-major dependencies, there is one PR where all dependencies are handled because they are less likely to cause bigger problems. 

Of course, the person in charge sets his PR link in a task so if some errors are made because of it, it can be easily traceable. When the whole list of packages is up-to-date, the developer merges that PR. After merging, the Renovate bot will auto-update the created PRs and if there aren’t any other updates the bot will auto-close it.

Configuration

The issues we wanted to solve:

Reduce noise by setting up a schedule for when the notifications will arrive

Set an assignee for checking on those updates

Set a branch for checking updates

Divide packages into groups, where each group is for:

Reduced build and reload times

Version level update (PR for major, PR for non-major updates)

Packages that wouldn’t be checked

Meant for different colleagues

The first problem I wanted to solve was reducing the noise to a minimum. Since the notifications are not wanted every day, I set a schedule for when we get those notifications. The schedule is set by the “schedule” property. The value of “schedule“ will represent the fixed times when the pull requests get generated.

Because there are different time zones, don’t forget to implement a timezone for your or your company zone (ours is Europe/Zagreb) using the “timezone” property with this list: IANA Time Zone.

Since I’m not the only one who should be warned about updates, I found the “assignees” property which will set assignees who will be notified. For this property, you can use GitHub’s username or email.

Although I am the main assignee for dependency updates on all of our front-end projects, I didn’t want to read each PR independently. I started to look at how dependencies can be grouped, sorted, or something like that. 

So I found “One array to rule them all” which saved me from a lot of buzzing noises on Friday , and it was the packageRules array. Each object in that array specifies which updates I want in each PR. In one PR it was necessary to receive updates only for major versions, the other was for patch and minor versions and it looks like this:

or

Each group can be named whatever you want and prioritized by prPriority. I wanted to assign some groups to other colleagues so I don’t have to deal with everything. Because I am lazy. Just kidding. 

Other colleagues had different assignments because they were more familiar with some specific libraries, so I used matchPackageNames and matchPackagePatterns

The matchPackagePatterns came very useful because you can use RegEx. I almost forgot to mention that for some of the dependencies, it wasn’t necessary for them to be on the list of updates. 

Why? Well, because there’s a Core team that deals with them every day at Productive, so I can set enabled: false to stop Renovate from notifying me or them. 

For example: 

Also, one of the useful commands is baseBranches. With that command, you set which branch will be checked by the bot. That can be useful because most software products are not updated daily and the companies have specific procedures until some feature goes out to the public.

Here’s an example of the renovate.json file with the basic configuration previously mentioned: 

For every other option you want to add or explore, feel free to read Renovate’s documentation.

Below, an example of one PR with a table (photo 1) and Release notes (photo 2).

The table is pretty self-explanatory. You can see which package or whatever you want to call it can be updated to which version with some other data. The table itself is configurable, so you can tailor it to your preferences.

Then there’s a section with the release notes in which you can inspect each update individually with their specific commits and proper descriptions.

What Issues Did We Encounter and How Did We Solve Them?

Lastly, not everything is perfect. There were some issues we encountered in the implementation process. 

For instance, there are two types of PRs, normal and immortal ones. A normal PR is a PR with only one dependency. When you close a normal PR, the main problem is that the manager will “think” that you maybe do not want to use that version of dependency and it will not notify you again. Immortal PRs can be closed because the manager will reopen them again, in our case those are grouped PRs. So, how do we deal with that feature/issue? We don’t close PRs until each package is up-to-date.

Another issue I encountered is that PRs will be created inside a schedule, but the manager will notify you outside of a schedule when updates are made. For example, the PR schedule for creating PRs is on Friday, but in the meantime, a new version of a certain dependency would be published and I would receive a notification. That could be useful, but since I update versions on a weekly basis I added the :noUnscheduledUpdates property, which limits notifications only inside the schedule.

One issue that still bothers me is that I receive vulnerability warnings for dependencies in one PR for every warning. I wanted to group them, but it seems nobody figured out a solution for that, yet. Depending on when you read this article and if this problem is solved, please contact me. Our method is to update only the dependencies to stable versions and use that as a workaround.

The last issue we encountered was with the range strategy. Renovate will not update packages if there’s a range indicator such as ^. That was weird to me, but they have a solution for that—you can set a rangeStrategy and Renovate has various options so that you can adjust to your app as you wish. We solved it by adding a “bump” rangeStrategy. We started with “replace” but when the manager reopened an immortal PR, dependencies that were on the closed PR’s list wouldn’t show up.

Should You Use Renovate?

In conclusion, if you ever get assigned to manage dependencies, for the love of God, use a dependency manager. If you have to ask why, please read this blog post again, or contact me to remove this post. 

But, for real, it just makes your life easier. Renovate is a solution that was best suitable for us. Because of it, I do not need to go to the NPM’s website to track every package if it has a new version available.

One of the annoying issues it also solved for me was that it keeps the noise to a minimum because of the “schedule” property. The noise was also reduced with the creation of groups for different types of versions.

Also, PRs are very easy to read and last, but not least, one of the best features of it is—it’s FREE.

Antonio Bajivić

Working in web development and having fun with electronics brings me joy. In my free time, I mix working out, socializing, and reading.
More From This Author

Related articles

Related jobs