‘bundle update’ – why we run it regularly and automatically to update our dependencies?

(Everyday Code – instead of keeping our knowledge in an README.md let’s share it with the internet)

Today it’s Wednesday and on Wednesday we have an automatic Jenkins job that would run ‘bundle update’. This will be 567-th time this build is run. It has saved us a lot of work and this article I would like to share why and how we automatically do ‘bundle update’

What is ‘bundle update’?

In the Ruby and Ruby on Rails world the dependencies are called gems. Gems could be installed with the ‘gem’ command. ‘bundle’ is a command provider by the Bundler tool. It automates this process. To quote from the Bundler web site

Bundler provides a consistent environment for Ruby projects by tracking and installing the exact gems and versions that are needed.

Bundler is an exit from dependency hell, and ensures that the gems you need are present in development, staging, and production. Starting work on a project is as simple as bundle install.

https://bundler.io/

With Bundler you can have two different projects working with two different sets of dependencies and Bundler will make sure the right dependencies are available for each project.

What is ‘$ bundle install’?

Both FLLCasts and BuildIn3D are Rails platforms. Before starting the platforms we should install all the dependencies. We use Bundler and the command is

$ cd platform/
$ bundle install

‘$ bundle install’ will make sure that all the gems that we are dependent on are available on our machine.

FLLCasts and BuildIn3D for example are dependent on:

# FLLCasts Gemfile contains
gem "rails", '~> 6.0.3'
gem "webpacker", "~> 5.0"
gem 'turbolinks', '~> 5.2.0'

This means that we are happy to work with any version of turbolinks that is 5.2.X. It could be 5.2.0, 5.2.1, 5.2.2 and so on. The last digit could change.

‘bundle install’ makes sure that you have a compatible version. But what if there is a new version of turbolinks – 5.2.5?

What is ‘$ bundle update’?

‘$ bundle update’ for me is the real deal. It will check what new compatible versions are released for the gems we depend on. If we are currently using turbolinks 5.2.0 and there is 5.2.1 ‘bundle update’ will check this and will fetch the new version of turbolinks for us to use. It will write the specific versions that are used in the Gemfile.lock.

For the turbolinks example the Gemfile.lock contains:

# Gemfile.lock for FLLCasts and BuildIn3D
    turbolinks (5.2.1)
      turbolinks-source (~> 5.2)

When should one run ‘$ bundle update’?

That’s a thought question and a hard sale. Every team member on our team has at a certain point asked this question or made a statement like ‘But this is not automatic. I want to update dependencies when I want to update dependencies!” or has in some way struggle with ‘$ bundle update’. Myself included.

The answer is:

As the rails and ruby communities are live and vibrant things are improved quite often. One should run ‘$ bundle update’ regularly and one should do it automatically to make sure the dependencies are up to date.

But updating the dependencies could break the platform!

Automatic ‘bundle update’ could break any platform?

Yes. It could. That’s why the are doing

# Run bundle update
$ bundle update

# Commit the new result to a new branch
$ git push elvis pr_fllcasts_update --force

# Try to merge the new branch like any other branch. Run merge and then the specs
$ git merge ...
$ rake spec (on the merge)
# If rake is successful continue with the merge. If it is not, then abort the merge. 

We update and commit the changes to a new Branch (or create a Pull Request, depending on the project), and we then run the normal build.

It will pull from this Branch (or PR) and will run the specs. If the specs pass successfully we continue with the merge.

In this way we are constantly up to date

What is the benefit of automatic ‘$ bundle update’?

As I’ve written before the main benefit is the allocation of resources and keeping the developers context – https://kmitov.com/posts/the-benefits-of-running-specs-against-nightly-releases-of-dependencies/

If a change in a gem breaks something that we are dependent on we can identify this in a week. We are not waiting months and we can report it now. The gem owners are probably still in the context of the change they’ve introduced and could faster understand and resolve the issue.

Additionally we no longer have ‘migrates’ on our team. We are not dedicating any resource to ‘migrating to new dependencies’ as it happens automatically.

#  Here are just the gems from Jan 13, 2021 7:00:00 AM
Installing aws-partitions 1.416.0 (was 1.413.0)
Installing chef-utils 16.9.20 (was 16.8.14)
Installing autoprefixer-rails 10.2.0.0 (was 10.1.0.0)
Installing omniauth 2.0.0 (was 1.9.1)
Installing http-parser 1.2.3 (was 1.2.2) with native extensions
Installing dragonfly 1.3.0 (was 1.2.1) Installing aws-sdk-core 3.111.0 (was 3.110.0)
Installing omniauth-oauth2 1.7.1 (was 1.7.0)
Installing aws-sdk-kms 1.41.0 (was 1.40.0)
Installing globalize 5.3.1 (was 5.3.0) Installing money-rails 1.13.4 (was 1.13.3)

Every Wednesday we update the gems and if there are problems we know at the middle of the week to be able to address them at the moment or to schedule them appropriately for the next weeks.