How and when do you decide to update your app's dependencies?
Tags: discuss, security, dependencies
Published: 2019-07-10 05:44:33

_Cover Photo Credit: [Francisco Jacquier](https://unsplash.com/@franjacquier) on [Unsplash](https://unsplash.com)_

Whether you have Ruby gems, npm packages, or JARs from a Maven repository, all but the simplest of projects have external dependencies. Over time these dependencies can get stale, outdated, and even insecure.

**On what cadence do you update your project's dependencies? Monthly? Weekly? Only as needed for new functionality or security updates?**

**How do you vet your dependency upgrades to ensure they do not break things or that they are not malicious?** _(see the recent [strong_password gem hijacking](https://withatwist.dev/strong-password-rubygem-hijacked.html) as a cautionary tale)_

---
## My Approach

On the Ruby project I spend most of my time working on, Cloud Foundry's [Cloud Controller](https://github.com/cloudfoundry/cloud_controller_ng), as well as some for some of my personal projects I do the following.

### Rely on External Tools for Alerts and PRs

I've found services like [Snyk](https://snyk.io/) and [Github's own security alerts](https://help.github.com/en/articles/about-security-alerts-for-vulnerable-dependencies) to be invaluable for keeping gems up to date from a security perspective. These tools constantly monitor the latest CVEs and cross-reference them with the versions of dependencies your project is relying on. When there are issues they alert you and can even submit automated pull requests to bump the dependencies.

Apart from security alerts, I've also found [Dependabot](https://dependabot.com/#how-it-works) to be helpful. It automatically submits pull requests for dependency updates in general and tries its best to include the relevant changelog entries.

### Rely on Continuous Integration to Catch Regressions

![Github Pull Request Travis CI and Code Climate integration](https://thepracticaldev.s3.amazonaws.com/i/zuk9a6an1cuecxvc4dxi.png)

The nice thing about these services that submit pull requests is that you can hook up CI systems (e.g. [Circle CI](https://circleci.com/) or [Travis CI](https://travis-ci.org/)) to run on all PRs. You can configure these to run your test suites and give some initial feedback on the impact of the update.

![Concourse CI pipelines](https://thepracticaldev.s3.amazonaws.com/i/ohrtw1h69e0weigvcf9n.png)

With sophisticated enough automation, like my team's Concourse CI pipelines you can even do things like auto-bump certain dependencies (we [auto-bump our Golang version](https://github.com/cloudfoundry/capi-ci/blob/feda6e5a6e0324f32be8e35d212e93f38250e491/ci/update-packages/update_golang_package.sh) for example) and rely on the continuous builds and deployments to our integration environments.

### Manually Read CHANGELOG and Browse Recent Commits

Of course for major version bumps (or minor for dependencies that have bitten me in the past) I like to manually read through the project's CHANGELOG or browse through the project's new commits. This can be tedious and time consuming, but it alerts me to any breaking changes and helps give me some peace of mind when upgrading.

That's the gist of my (kinda Ruby-centric) approach to dependency management. What do you do?

I'm particularly interested in learning more about what folks do in other language ecosystems and reading your upgrade philosophies! 😊