On Bundler 2.0 compatibility

Jan Krutisch, Co-Founder at Depfu04 October 2017

Well that was awkward. When I wrote our last article about the transition from Gemfile to gems.rb, the “official document” about the Bundler 2.0 transition stated that Gemfile will be removed in Bundler 3.0 but since we published that article, the RFC has been changed to remove that note, probably due to pressure from the community. We’ve updated the article, but if you’re too lazy to read it again: Gemfile and Gemfile.lock are probably not going away any time soon ¯\_(ツ)_/¯.

Of course the main point of my article still stands: While it is trivial to migrate a single project by renaming the Gemfile to gems.rb and Gemfile.lock to gems.locked, it’s quite a different thing to make the whole eco system adapt to these changes.

So what else changes?

In this article I want to expand on that by looking at probably the most important change that’s coming to Bundler 2.0: The updated lock file format.

It’s probably also Bundler 2.0’s most controversial change and while the changes make a lot of sense from an abstract perspective, the hassle that will be introduced by this for the infrastructure providers especially is enormous and begs the question if this is worth it.

There are a couple of things that change under the hood which make a changed lock file necessary:

Multi-Platform support: Up until Bundler 2.0, lock files were pinned to the platform (a platform is a combination of the OS, the runtime (e.g. JRuby) and the CPU architecture) you’ve created the lock file on. This, in turn means that when bundling on a completely different platform, the lock file isn’t valid on that platform. Bundler 2.0 changes that by allowing the platforms within a lock file to be an array and by making it possible to specify several platform specific versions of a single gem in the lock file.

Source pinning: Pre 2.0 bundler has grouped all gems coming from gem sources (this could be rubygems.org, but also other gem repositories such as a private geminabox) into one list of gems. Bundler 2.0 will have individual lists of gems per source. The rationale for this is given in the old Trello ticket for it.

To sum it up quickly: Lock files written by Bundler 2.0 will not be readable by Bundler 1.x.

This is a problem

On one hand, this seems fair game. Semantic Versioning states very clearly that incrementing the major version signals breaking API changes.

For development teams this means that all members will have to upgrade at the same time. Challenging (especially for large teams) but certainly doable. For infrastructure providers on the other hand such as Heroku, Travis CI or even Depfu, this will be an “interesting” problem.

In some cases, simply upgrading to Bundler 2.0 may fix things - Bundler 2.0 will be able to read Gemfile.lock files written by Bundler 1.x and when run in deployment mode, it also won’t change the Gemfile.lock in these cases. Of course, this is somewhat of a risky move. Heroku, for example, has been very conservative in upgrading Bundler, but when Bundler 2.0 is released, they almost have no other choice but to upgrade to be able to serve apps written by people who upgraded.

But then, for example, we at Depfu will need to run our code based on either Bundler 2.0 or 1.x depending on what the pre update Gemfile.lock is bundled with, otherwise the results will be very confusing to our users (and will force them to upgrade as well). Other people may have similar scenarios where they run code on their CI that will actually change and commit the Gemfile.lock and they will run into the same problem.

Now what?

Would this have been avoidable? I am not really sure. Maybe these non backwards compatible changes are unavoidable in the long term. But it seems to be as if some parts of the Ruby community strongly disagree with the direction Bundler 2.0 (especially due to the incompatibilities) is taking:

Bundler exists so I don't have to worry about tracking dependency versions, but lately every update makes me worried about *its* version