Bundler and the cache

Keep the bundle in the project

By default Bundler installs gems into the user gem folder, next to every other project. A pipeline can cache that folder, but it is shared and the cache key becomes guesswork. The reliable way is to put the bundle inside the project:

bundle config set --local path vendor/bundle

--local writes the setting into the project, not into the user configuration, so the next person who clones the repository does not inherit your paths. The command prints nothing on success.

What bundler wrote

The setting lives in one small file. Read it and commit it:

cat .bundle/config

---
BUNDLE_PATH: "vendor/bundle"

One key, one value. A CI cache that keeps vendor/bundle but loses this file installs the gems somewhere else and restores nothing, which is the classic half-working cache.

What to cache

Install again and look at the folder:

bundle install

Fetching gem metadata from https://rubygems.org/...
Resolving dependencies...
Fetching rake 13.4.2
Installing rake 13.4.2
Fetching minitest 5.27.0
Installing minitest 5.27.0
Bundle complete! 2 Gemfile dependencies, 2 gems now installed.
Bundled gems are installed into `./vendor/bundle`

ls vendor/bundle/ruby/3.4.0/gems

minitest-5.27.0
rake-13.4.2

The folder name carries the Ruby version, which is why a cache built for 3.4 is useless for 3.3: the pipeline installs again there, and that is correct. Cache the whole vendor/bundle directory, keyed on Gemfile.lock.

Run from the local bundle

Nothing else changes: bundle exec finds the gems in the project folder.

bundle exec rake test

Run options: --seed 29433

# Running:

...

Finished in 0.001215s, 2469.1155 runs/s, 3292.1540 assertions/s.

3 runs, 4 assertions, 0 failures, 0 errors, 0 skips

What to watch for

A cache is not an artifact. The cache exists to save seconds on the next run and may be dropped at any time; the lock file and the gemspec are the truth. If a pipeline passes only with a warm cache, it is hiding a missing Gemfile entry.

Clear the cache once after editing the Gemfile and compare the log with the cached run. If the two logs differ in more than timings, something outside the lock file is being used.

Next: RuboCop in the pipeline

Article author: Arthur Isaev