Cached gems can't be found in next job


#1

I’m using the latest gitlab (it auto-updates) and gitlab CI runner that uses Docker. The project in question in a Rails project, and I simply want to cache the deployed gems for future use. I thought it would be as easy as this .gitlab-ci.yml:

image: ruby:2.4

stages:
  - build
  - test

build:
  stage: build
  tags: [docker]
  script:
    - bundle install --jobs $(nproc) --deployment
    - bundle show rake
    - ls -R vendor/bundle/
  # Cache the installed gems for the following job
  cache:
    key: gems
    paths:
      - vendor/bundle

test:
  stage: test
  tags: [docker]
  cache:
    key: gems
    paths:
      - vendor/bundle
    policy: pull
  script:
    - ls -R vendor/bundle/
    - bundle exec rake test

The build job has the output expected. It installs all the gems and then has the following:

...
$ bundle show rake
/builds/kyrofa/<project>/vendor/bundle/ruby/2.4.0/gems/rake-12.0.0
$ ls -R vendor/bundle/
vendor/bundle/:
ruby

vendor/bundle/ruby:
2.4.0

vendor/bundle/ruby/2.4.0:
bin
build_info
cache
doc
extensions
gems
specifications
# ... you get the idea

The output of the second job ALMOST looks as expected

Checking cache for gems...
Successfully extracted cache
$ ls -R vendor/bundle/
vendor/bundle/:
ruby

vendor/bundle/ruby:
2.4.0

vendor/bundle/ruby/2.4.0:
bin
build_info
cache
doc
extensions
gems
specifications
# ... looks the same

But then the bundle exec rake test results in this at the end:

$ bundle exec rake test
Bundler::GemNotFound: Could not find concurrent-ruby-1.0.5 in any of the sources
  /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.15.3/lib/bundler/spec_set.rb:87:in `block in materialize'
  /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.15.3/lib/bundler/spec_set.rb:81:in `map!'
  /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.15.3/lib/bundler/spec_set.rb:81:in `materialize'
  /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.15.3/lib/bundler/definition.rb:159:in `specs'
  /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.15.3/lib/bundler/definition.rb:218:in `specs_for'
  /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.15.3/lib/bundler/definition.rb:207:in `requested_specs'
  /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.15.3/lib/bundler/runtime.rb:109:in `block in definition_method'
  /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.15.3/lib/bundler/runtime.rb:21:in `setup'
  /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.15.3/lib/bundler.rb:101:in `setup'
  /usr/local/lib/ruby/gems/2.4.0/gems/bundler-1.15.3/lib/bundler/setup.rb:19:in `<top (required)>'
  /usr/local/lib/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require'
  /usr/local/lib/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require'
bundler: failed to load command: rake (/usr/local/bin/rake)

Adding a bundle show rake confirms that it can’t find it. I thought this would work, am I doing something stupid?


#2

What’s particularly frustrating is that this works in practice. I can clone my code twice, once to a/ and once to b/, and run bundle install --deployment in a/, copy a/vendor/bundle to b/vendor/bundle and then hop in b/ and run bundle exec rake test with no issues. I just can’t figure out what’s happening in the pipeline to not make this work.


#3

I tried using artifacts for this as well, and ended up with the exact same results.


#4

Another interesting tidbit: if I make the test job run bundle install --deployment before trying to bundle exec rake test, it finishes very quickly (of course) and then works fine. I’d say it must be writing to some file that I also need to cache, but my local testing doesn’t seem to. Until someone comes up with a better idea, I’ll use that for my path forward.


#5

Gemfile.lock?