Skip to content

bundle check corrupts gem's Gemfile.lock by moving gems between sources #5339

@ZimbiX

Description

@ZimbiX

Describe the problem as clearly as you can

We have a private gem that depends on other gems: some public, some private.

We use a Dockerised development environment, and in the repo for this gem, as part of our Docker entrypoint, we have it install the bundle, but first run bundle check for a performant check to see if we need to do so:

bundle check || bundle install --jobs=100

Unfortunately, it seems that Bundler now corrupts the Gemfile.lock when we run bundle check after updating the gem's version. The command succeeds, but the public gems get moved to the private source in Gemfile.lock. This results in failure from the next bundle install which needs to install gems.

I had no idea that bundle check could modify the Gemfile.lock at all, let alone corrupt it.

As a workaround, we are now using bundle check --dry-run there, which actually doesn't modify/corrupt the Gemfile.lock.

Did you try upgrading rubygems & bundler?

Yes

Post steps to reproduce the problem

Given it's a sources issue, this seems to require running a secondary gem server to reproduce; I am not experienced in setting one up that's accessible from outside our organisation to create an easy reproduction =\ However, I have come up with minimal reproduction steps using two dependency-less gems for simplicity:

  • Create a new gem, e.g.:

    bundle gem bundle-check-issue
  • Make the gem bundle-able by commenting out, in the gemspec, the spec.metadata lines, TODO lines, and add spec.summary = ""

  • Add a public gem dependency to the gemspec, e.g.:

    spec.add_runtime_dependency 'awesome_print'
  • Add a private gem dependency to the Gemfile, e.g.:

    source 'https://rubygems.pkg.github.com/greensync' do
      gem 'dex-dispatch-engine'
    end

    but one that you have access to.

  • Create a Gemfile.lock:

    bundle
  • Update the version of the gem, e.g. on Linux:

    sed -i -E 's/[0-9.]+/9999/' **/version.rb`
  • Run bundle check

    Resolving dependencies...
    The Gemfile's dependencies are satisfied
    

    Gemfile.lock has now been corrupted, and the next bundle install that needs to install awesome_print will fail:

    ➜ gem uninstall -a -I awesome_print
    Successfully uninstalled awesome_print-1.9.2
    
    ➜ bundle install                   
    Fetching gem metadata from https://rubygems.pkg.github.com/greensync/..
    Your bundle is locked to awesome_print (1.9.2) from rubygems repository https://rubygems.pkg.github.com/greensync/ or installed locally, but that version can no longer be found in that source. That means the author of awesome_print (1.9.2) has removed it. You'll need to
    update your bundle to a version other than awesome_print (1.9.2) that hasn't been removed in order to install.
    

Which command did you run?

Update the gem's version number, then:

bundle check

What were you expecting to happen?

Gemfile.lock not to be modified at all by bundle check, let alone corrupted

What actually happened?

Gemfile.lock was corrupted by bundle check:

diff --git a/Gemfile.lock b/Gemfile.lock
index 5afa4e9..6385ddb 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,17 +1,17 @@
 PATH
   remote: .
   specs:
-    bundle-check-issue (0.1.0)
+    bundle-check-issue (9999)
       awesome_print
 
 GEM
   remote: https://rubygems.org/
   specs:
-    awesome_print (1.9.2)
 
 GEM
   remote: https://rubygems.pkg.github.com/greensync/
   specs:
+    awesome_print (1.9.2)
     dex-dispatch-engine (0.7.0)
 
 PLATFORMS

Version which introduced the bug

The bug was introduced in Bundler 2.2.26, as determined using:

➜ v=2.2.25; gem install bundler -v $v; bundle _${v}_ install; git add .; sed -i -E 's/[0-9.]+/9999/' **/version.rb; bundle _${v}_ check; git diff Gemfile.lock; git checkout .
Successfully installed bundler-2.2.25
1 gem installed
Using awesome_print 1.9.2
Using bundle-check-issue 0.1.0 from source at `.`
Using bundler 2.2.25
Using dex-dispatch-engine 0.7.0
Bundle complete! 2 Gemfile dependencies, 4 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Resolving dependencies...
The Gemfile's dependencies are satisfied
diff --git a/Gemfile.lock b/Gemfile.lock
index c64da60..961321f 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,7 +1,7 @@
 PATH
   remote: .
   specs:
-    bundle-check-issue (0.1.0)
+    bundle-check-issue (9999)
       awesome_print
 
 GEM
Updated 2 paths from the index

➜ v=2.2.26; gem install bundler -v $v; bundle _${v}_ install; git add .; sed -i -E 's/[0-9.]+/9999/' **/version.rb; bundle _${v}_ check; git diff Gemfile.lock; git checkout .
Successfully installed bundler-2.2.26
1 gem installed
Using awesome_print 1.9.2
Using bundle-check-issue 0.1.0 from source at `.`
Using bundler 2.2.26
Using dex-dispatch-engine 0.7.0
Bundle complete! 2 Gemfile dependencies, 4 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Resolving dependencies...
The Gemfile's dependencies are satisfied
diff --git a/Gemfile.lock b/Gemfile.lock
index c64da60..a669110 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,17 +1,17 @@
 PATH
   remote: .
   specs:
-    bundle-check-issue (0.1.0)
+    bundle-check-issue (9999)
       awesome_print
 
 GEM
   remote: https://rubygems.org/
   specs:
-    awesome_print (1.9.2)
 
 GEM
   remote: https://rubygems.pkg.github.com/greensync/
   specs:
+    awesome_print (1.9.2)
     dex-dispatch-engine (0.7.0)
 
 PLATFORMS
@@ -22,4 +22,4 @@ DEPENDENCIES
   dex-dispatch-engine!
 
 BUNDLED WITH
-   2.2.25
+   2.2.26
Updated 2 paths from the index

If not included with the output of your command, run bundle env and paste the output below

Environment

Bundler       2.3.6
  Platforms   ruby, x86_64-linux
Ruby          2.7.3p183 (2021-04-05 revision 6847ee089d7655b2a0eea4fee3133aeacd4cc7cc) [x86_64-linux]
  Full Path   /home/brendan/.rbenv/versions/2.7.3/bin/ruby
  Config Dir  /home/brendan/.rbenv/versions/2.7.3/etc
RubyGems      3.3.6
  Gem Home    /home/brendan/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0
  Gem Path    /home/brendan/.gem/ruby/2.7.0:/home/brendan/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0
  User Home   /home/brendan
  User Path   /home/brendan/.gem/ruby/2.7.0
  Bin Dir     /home/brendan/.rbenv/versions/2.7.3/bin
Tools         
  Git         2.35.1
  RVM         not installed
  rbenv       rbenv 1.2.0
  chruby      not installed

Bundler Build Metadata

Built At          2022-01-26
Git SHA           056f64c33a
Released Version  true

Bundler settings

gem.changelog
  Set for the current user (/home/brendan/.bundle/config): false
gem.ci
  Set for the current user (/home/brendan/.bundle/config): false
gem.coc
  Set for the current user (/home/brendan/.bundle/config): false
gem.linter
  Set for the current user (/home/brendan/.bundle/config): "rubocop"
gem.mit
  Set for the current user (/home/brendan/.bundle/config): false
gem.test
  Set for the current user (/home/brendan/.bundle/config): "rspec"
https://rubygems.pkg.github.com/greensync/
  Set for the current user (/home/brendan/.bundle/config): "ZimbiX:[REDACTED]"
jobs
  Set via BUNDLE_JOBS: 100

Gemfile

Gemfile

source 'https://rubygems.org'

source 'https://rubygems.pkg.github.com/greensync' do
  gem 'dex-dispatch-engine'
end

gemspec

Gemfile.lock

PATH
  remote: .
  specs:
    bundle-check-issue (0.1.0)
      awesome_print

GEM
  remote: https://rubygems.org/
  specs:
    awesome_print (1.9.2)

GEM
  remote: https://rubygems.pkg.github.com/greensync/
  specs:
    dex-dispatch-engine (0.7.0)

PLATFORMS
  x86_64-linux

DEPENDENCIES
  bundle-check-issue!
  dex-dispatch-engine!

BUNDLED WITH
   2.3.6

Gemspecs

bundle-check-issue.gemspec

# frozen_string_literal: true

require_relative "lib/bundle/check/issue/version"

Gem::Specification.new do |spec|
  spec.name = "bundle-check-issue"
  spec.version = Bundle::Check::Issue::VERSION
  spec.authors = ["Brendan Weibrecht"]
  spec.email = ["brendan@weibrecht.net.au"]

  spec.summary = ""
  # spec.summary = "TODO: Write a short summary, because RubyGems requires one."
  # spec.description = "TODO: Write a longer description or delete this line."
  # spec.homepage = "TODO: Put your gem's website or public repo URL here."
  spec.required_ruby_version = ">= 2.6.0"

  # spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"

  # spec.metadata["homepage_uri"] = spec.homepage
  # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
  # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."

  # Specify which files should be added to the gem when it is released.
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
    `git ls-files -z`.split("\x0").reject do |f|
      (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
    end
  end
  spec.bindir = "exe"
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
  spec.require_paths = ["lib"]

  # Uncomment to register a new dependency of your gem
  # spec.add_dependency "example-gem", "~> 1.0"

  spec.add_runtime_dependency 'awesome_print'

  # For more information and examples about making a new gem, check out our
  # guide at: https://bundler.io/guides/creating_gem.html
end

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions