Dependencies are exactly what it sounds like – things that you depend on. But take that undeniable statement into your software project and you soon find out that it’s not just you who depends on them. It’s entire teams, processes, projects, infrastructure, and, most important of all, your clients.
1. Map your dependencies.
2. Keep your dependencies up-to-date.
3. Trust but verify.
4. Remove old and unused dependencies.
5. React quickly to vulnerability alerts.
Let’s expand on these action items to get a better understanding of what’s considered solid dependency management.
Nowadays, with package managers such as maven, pip, npm and gradle, it’s easy to know which packages and libraries your code relies on.
With a little bit of automation, you can map your dependency usage.
Map your dependency usage to log the following:
Where certain packages and libraries are used, how frequently they are used across different projects and what version they align to.
All of the above can help you act quickly and efficiently to any issues that may arise with any given dependency.
Trust but verify
The devs and teams that work on the libraries and packages that you use, do their best to deliver code that does what you need it to do.
However, even with their best intentions, devs and teams make mistakes. With a single oversight, bugs and vulnerabilities easily creep in. Even if an update is clean, it might still introduce breaking changes and you need to make sure the update is backward compatible. So whenever it’s time to update dependencies, do the following:
1. See that the dependency is actively maintained and that there is an active community that uses it.
2. Make sure an update is backward compatible. Read the release notes to see if any changes to APIs might affect your code.
3. Follow up on open issues submitted by the community. This might sound a bit foul, but let others flush out the issues first.
4. Test it to exhaustion.
5. Gradually admit it to staging and production environments. Let it sit there for a while and monitor it ruthlessly.
To get started with automating dependency management, I personally recommend WhiteSource Renovate. It’s a free tool for automating dependency management that integrates with GitHub and GitLab, can be used as a CLI tool, and even has an on-premise version.
It scans repositories looking for package files such as package.json (Node.js), .yml (docker, travis) and requirements.txt (Python). It then submits a pull request with updated packages if any are found. You can easily configure it to scan and submit pull requests on schedule.
Remember trust but verify? You can safely install it in your GitHub or GitLab, use its CLI tool or install on-premise. To put it simply, WhiteSource Renovate submits pull requests and then you can decide what goes in and what stays out. Feeling brave? Configure auto-merge for dependencies that pass specific tests that satisfy the rules you set.
In that case, WhiteSource Renovate fulfils at least two action items of keeping packages up-to-date and trusting but verifying. That’s almost half the way. Keep in mind that it’s easy to dismiss dependency management in the face of growing demand to release here and now. But it might cost you dearly down the road. Choose wisely.
Keep your dependencies up-to-date
Whether you are using open source or in-house dependencies, you should make sure they are up-to-date. Updates to dependencies usually include improvements to the underlying source code and patches to bugs or vulnerabilities.
Keeping your dependencies up-to-date greatly increases the security and stability of your codebase. However, as we’ll see in the next point, vigilant dependency updates can be a double-edged sword.
Remove old and unused dependencies
This goes without saying. If you’re not using some libraries, remove them. If they are scarcely used throughout your code, find alternatives. There is no point in keeping an entire library for a couple of APIs that are rarely invoked.
This is relevant when working with open source libraries. Most of us are familiar with GitHub’s security alerts. Don’t wait for them to rear their ugly heads. Investigate the vulnerability, follow up on issues raised by the community, evaluate the risk and mitigate accordingly.
Easier said than done
We’ll admit that all of the above is easier said than done. Today’s software delivery world is moving fast. With agile methodologies, the need to reduce time to market, and constant demand from clients and stakeholders, dependency management can sometimes become a serious blocker for release cycles.
Still, a lot of the aspects of dependency management can be automated and integrated into pipelines and release cycles to ease the heavy burden it might bring with it.
It’s still worth taking a bit of heat from tech leads, stakeholders, and even clients, just to make sure that your code and its dependencies are well managed and maintained. This will save you a lot of headaches down the road.