How to conservatively update a single gem with bundler
I was recently called for help to update a gem in a Rails application I wrote a couple of months ago. It was important to only update a single gem (which had a known security vulnerability) and not touch any others, as this would have triggered a complete cycle of QA.
Unfortunately, I cannot share the full
Gemfile, but I’ve found a similar example in an application I’m currently working on:
sidekiq with its dependencies on
Gemfile.lock looks like this:
sidekiq (4.1.1) concurrent-ruby (~> 1.0) connection_pool (~> 2.2, >= 2.2.0) redis (~> 3.2, >= 3.2.1) ... concurrent-ruby (1.0.1) redis (3.2.2) sidekiq (4.1.1)
Everybody that has been in the same situation knows that a
bundle update will not yield the desired result as it will update all the dependencies.
The awesome folks at LivingSocial have released a project called
bundler-patch which updates your gems conservatively.
Before we go into more details, let’s see if it gives us the desired result. First, we need to install it via
gem install bundler-patch and then run
bundle patch sidekiq.
Here’s the extract of our
concurrent-ruby (1.0.1) redis (3.2.2) sidekiq (4.1.2)
Awesome! It only updated
sidekiq to version
The explanation? As opposed to
bundle update, which will try to get the latest version of all your gems and its dependencies,
bundler-patch will prefer the latest release from the current version of the gem. Be sure to check out their README for the full description and additional options!
bundle update --source does not (reliably) work
There are various blog posts and Stack Overflow articles suggesting that
bundle update --source will only update the gem specified. Let’s try it out:
bundle update --source sidekiq:
concurrent-ruby (1.0.1) redis (3.3.0) sidekiq (4.1.2)
Passing a gem to the source option will update a gem and all of its dependencies except those that are specified elsewhere in the Gemfile or are depended on by other gems.
That means that updates with
--source will work fine for gems with popular dependencies and on larger projects.