Is a given gem used in production?

TL; DR: To find out if a gem is needed in production, you can temporarily switch bundler’s config to exclude development and test, then bundle exec gem list. (Simply setting RAILS_ENV is not enough)

Suppose I want to update the version of capybara or selenium-webdriver that’s used in our Rails project. I perform the update and I see several of changes to Gemfile.lock.

Some of the changes are to other gems that are pulled in by Capybara and Selenium webdriver. For example I notice rubyzip has been upgraded to a newer version. These are updates to gems that I don’t directly use in my project, or mention in my Gemfile. i.e. they’re indirect dependencies.

I want to do a risk assessment and find out if any of these gems are also used at runtime.

Clearly rubyzip is used by one of the gems I use in my test environment, but there’s no immediately obvious way to see at a glance that it isn’t additionally required by one of the gems we use at runtime in production.

If the affected gems are only ever used in the test or development environment, my risk posture will be different from a situation where one or more of the affected gems is also used in production.

As with all things in Rails development there are no doubt many ways to do this, but here I’ve described one quick and dirty way that seems to do the trick.

How to do it

First, check bundler’s config:

bundle config

I’ll assume that like me you don’t have any special config for the ‘without’ setting. But if you do, make a note of it.

Next we’ll change the “without” config. (Don’t worry, we’ll put it back later)

bundle config without "development test"

Once we’ve done that, if we run gem list inside a bundle it’ll only list gems that are needed in production:

bundle exec gem list

This gives us a list of gems that would be loaded in the production environment, excluding any gems that are used only in development or test.

So for example

bundle exec gem list | grep rubyzip

In my case this tells me rubyzip is not used in production - in fact it’s needed only by selenium-webdriver which I only use in my test environment. No other gems are depending on it. That’s what I wanted to confirm, without having to carefully check each dependency in Gemfile.lock one by one.

If I them remove the “without” config, and get a bundled gem list`:

bundle config --delete without
bundle exec gem list | grep rubyzip

…the gem list will now include all gems, including those from development and test - and rubyzip is listed again.

Note that in all of this, Gemfile and Gemfile.lock do not change - Gemfile.lock continues throughout to contain a full list of gem versions, even though some of them are not needed in certain environments.

Valid HTML This page was handcrafted in Brighton by Codeface