[DRE-maint] Bug#830958: ruby-bundler: System-wide ruby packages get predecedence over local ones (in some cases)

Gabriel Corona gabriel.corona at enst-bretagne.fr
Wed Jul 13 09:41:03 UTC 2016


Package: ruby-bundler
Version: 1.12.5-2
Severity: normal

Dear Maintainer,

When installing gem with Debian-packages Bundler, in some cases (when
using bundle exec) the system-wide version is used before the
Bundler-shipped version:

    cat > Gemfile <<EOF
    source 'https://rubygems.org'
    gem 'puppet', '~> 3.7.2'
    gem 'hiera', '~> 1.3.4'
    gem 'hiera-puppet', '~> 1.0.0'
    gem 'r10k', '~> 1.1.4'
    EOF
    
    bundle install --path vendor/bundle --binstubs
    puppet --version             # 4.5.2, this comes from Debian
    ./bin/puppet --version       # 3.7.2, this comes from Bundler    
    bundle exec puppet --version # 4.5.2, this comes from Debian

I'd expect `bundle exec puppet` to use the Bundler version instead.

The manpage of bundle-exec [2] claims that:

> If you use the `--binstubs` flag in `bundle install(1)`, Bundler
> will automatically create a directory (which defaults to
> `app_root/bin`) containing all of the executables available from
> gems in the bundle.
>
> After using `--binstubs`, <b>`bin/rspec spec/my_spec.rb` is
> identical to `bundle exec rspec spec/my_spec.rb`</b>.

So I'd expect the two last commands to behave the same.

It turns out [1] that Bundler adds its base directory
(/usr/lib/ruby/vendor_ruby) in RUBYLIB in order to make
RUBYOPT=-rbundler/setup work:

    def set_rubylib
      rubylib = (ENV["RUBYLIB"] || "").split(File::PATH_SEPARATOR)
      rubylib.unshift File.expand_path("../..", __FILE__)
      ENV["RUBYLIB"] = rubylib.uniq.join(File::PATH_SEPARATOR)
    end

The two methods of execution lead to a different $LOAD_PATH. With
./bin/puppet, we have:

    ["/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/r10k-1.1.4/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/systemu-2.5.2/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/puppet-3.7.5/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/log4r-1.1.10/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/hiera-puppet-1.0.0/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/hiera-1.3.4/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/json_pure-2.0.1/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/facter-2.4.6/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/cri-2.4.1/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/colored-1.2/lib", "/usr/lib/ruby/vendor_ruby/gems/bundler-1.12.5/lib", "/usr/local/lib/site_ruby/2.3.0", "/usr/local/lib/x86_64-linux-gnu/site_ruby", "/usr/local/lib/site_ruby", "/usr/lib/ruby/vendor_ruby/2.3.0", "/usr/lib/x86_64-linux-gnu/ruby/vendor_ruby/2.3.0", "/usr/lib/ruby/vendor_ruby", "/usr/lib/ruby/2.3.0", "/usr/lib/x86_64-linux-gnu/ruby/2.3.0"]

In this case, Bundler sets RUBYLIB (in require "bundler/setup") but
the Ruby interpreter is already initialized and it is not prepended to
$LOAD_PATH.

With bundle exec, we have:

    ["/usr/lib/ruby/vendor_ruby", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/r10k-1.1.4/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/systemu-2.5.2/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/puppet-3.7.5/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/log4r-1.1.10/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/hiera-puppet-1.0.0/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/hiera-1.3.4/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/json_pure-2.0.1/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/facter-2.4.6/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/cri-2.4.1/lib", "/home/foo/bar/vendor/bundle/ruby/2.3.0/gems/colored-1.2/lib", "/usr/lib/ruby/vendor_ruby/gems/bundler-1.12.5/lib", "/usr/local/lib/site_ruby/2.3.0", "/usr/local/lib/x86_64-linux-gnu/site_ruby", "/usr/local/lib/site_ruby", "/usr/lib/ruby/vendor_ruby/2.3.0", "/usr/lib/x86_64-linux-gnu/ruby/vendor_ruby/2.3.0", "/usr/lib/ruby/2.3.0", "/usr/lib/x86_64-linux-gnu/ruby/2.3.0"]

In this case, Bundlet sets RUBYLIB and then exec a new Ruby
interpreter. This Ruby interpreter sees RUBYLIB and prepends it to
$LOAD_PATH.

The problem is that in this case, all the Debian-packaged ruby libs
are used in preference to the Bundler-provided ones which is probably
not what the user intends to do.

Using a local version of bundler fixes the issue:

    gem install --user-install bundler
    ~/.gem/ruby/2.3.0/bin/bundle exec puppet --version # 3.7.5

[1] https://github.com/bundler/bundler/issues/4780

[2] http://bundler.io/v1.12/man/bundle-exec.1.html

-- System Information:
Debian Release: stretch/sid
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'testing'), (500, 'stable'), (90, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.6.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=fr_FR.utf8, LC_CTYPE=fr_FR.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages ruby-bundler depends on:
ii  ruby                        1:2.3.0+4
ii  ruby-molinillo              0.5.0-1
ii  ruby-net-http-persistent    2.9.4-1
ii  ruby-thor                   0.19.1-2
ii  ruby2.1 [ruby-interpreter]  2.1.5-2+deb8u2
ii  rubygems-integration        1.10

ruby-bundler recommends no packages.

ruby-bundler suggests no packages.

-- no debconf information



More information about the Pkg-ruby-extras-maintainers mailing list