Sorbet: `srb rbi gems` errored in Docker "Official Image" for ruby

Created on 22 Apr 2020  路  4Comments  路  Source: sorbet/sorbet

Input

  • running srb rbi gems in Docker "Official Image" for ruby
  • used image: Dockerfile

Observed output

root@249a7b937fd8:/app# srb rbi gems
Running command: gems
Generating: sorbet/rbi/gems/
Please report a bug if this causes problems.
LoadError: cannot load such file -- action_controller/middleware
LoadError: cannot load such file -- image_processing
LoadError: cannot load such file -- rack/session/dalli
LoadError: cannot load such file -- railties
LoadError: cannot load such file -- spring
LoadError: cannot load such file -- spring-watcher-listen
LoadError: cannot load such file -- sprockets-rails
Can't find gem for /usr/local/bundle/gems/railties-6.0.2.2/lib/rails/ruby_version_check.rb
Can't find gem for /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/constants.rb
Can't find gem for /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/utility/engine.rb
Can't find gem for /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb
Can't find gem for /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb
Can't find gem for /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/mri_object.rb
Can't find gem for /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/jruby_object.rb

...

Can't find gem for /usr/local/bundle/gems/simplecov-0.18.5/lib/simplecov/combine/results_combiner.rb
Can't find gem for /usr/local/bundle/gems/simplecov-0.18.5/lib/simplecov/useless_results_remover.rb
Can't find gem for /usr/local/bundle/gems/simplecov-0.18.5/lib/simplecov/simulate_coverage.rb
Can't find gem for /usr/local/bundle/gems/simplecov-html-0.12.2/lib/simplecov-html/version.rb
Can't find gem for /usr/local/bundle/gems/simplecov-html-0.12.2/lib/simplecov-html.rb
Can't find gem for /usr/local/bundle/gems/simplecov-0.18.5/lib/simplecov/profiles/root_filter.rb
Can't find gem for /usr/local/bundle/gems/simplecov-0.18.5/lib/simplecov/defaults.rb
Can't find gem for /usr/local/bundle/gems/simplecov-0.18.5/lib/simplecov.rb

root@249a7b937fd8:/app# ls sorbet/rbi/gems
ls: cannot access 'sorbet/rbi/gems': No such file or directory

Expected behavior

generating rbi files in sorbet/rbi/gems


Problem

default gem install path unmatch regexp

https://github.com/docker-library/ruby/blob/a564feaaee4c8647c299ab11d41498468bb9af7b/2.6/buster/Dockerfile#L80-L82

root@249a7b937fd8:/app# gem environment gemdir
/usr/local/bundle

https://github.com/sorbet/sorbet/blob/51681e5ae80275a16ddc126916c93d64a8b88faf/gems/sorbet/lib/gem-generator-tracepoint/tracepoint_serializer.rb#L217-L221

irb(main):001:0> location = '/usr/local/bundle/gems/railties-6.0.2.2/lib/rails/ruby_version_check.rb'
=> "/usr/local/bundle/gems/railties-6.0.2.2/lib/rails/ruby_version_check.rb"
irb(main):002:0> match = location&.match(/^.*\/(ruby)\/([\d.]+)\//) || # ruby stdlib
irb(main):003:0*         location&.match(/^.*\/(jruby)-([\d.]+)\//) || # jvm ruby stdlib
irb(main):004:0*         location&.match(/^.*\/(site_ruby)\/([\d.]+)\//) || # rubygems
irb(main):005:0*         location&.match(/^.*\/gems\/(?:(?:j?ruby-)?[\d.]+(?:@[^\/]+)?(?:\/bundler)?\/)?gems\/([^\/]+)-([^-\/]+)\//i) # gem
=> nil

Proposed solution

additional regexp

^.*\/gems\/([^\/]+)-([^-\/]+)\/ or ^\/usr\/local\/bundle\/gems\/([^\/]+)-([^-\/]+)\/

irb(main):006:0> match = location&.match(/^.*\/gems\/([^\/]+)-([^-\/]+)\//)
=> #<MatchData "/usr/local/bundle/gems/railties-6.0.2.2/" 1:"railties" 2:"6.0.2.2">
irb(main):007:0> match = location&.match(/^\/usr\/local\/bundle\/gems\/([^\/]+)-([^-\/]+)\//)
=> #<MatchData "/usr/local/bundle/gems/railties-6.0.2.2/" 1:"railties" 2:"6.0.2.2">
bug srb unconfirmed

Most helpful comment

Bump on this. Anyone using Docker with official ruby image as a primary development environment is blocked by this.

All 4 comments

I had this same issue and added a comment in the Sorbet Slack

image

Slack Text Content

So, I've got a new Rails project that's being worked on at my company. We've got about 15 engineers with all different backgrounds, OS's etc, so we decided to do a Docker development environment. It's 2020, after all, right? The thing is, that the default ruby docker image puts all gems into a unique path: /usr/local/bundle/gems. An installed gem may look like /usr/local/bundle/gems/sorbet-0.5.5510 . The problem comes up when I try to run bundle exec srb rbi gems inside my Docker container, as these gem paths match none of these regular expressions: https://github.com/sorbet/sorbet/blob/4712ebb040fec410dc6843cfbd2056e50c2f2e7c/gems/sorbet/lib/gem-generator-tracepoint/tracepoint_serializer.rb#L218-L221

So, we tried configuring a bundle config path, but that has weird results, too. By default, bundler puts gems in a directory like /Users/kyle/.rvm/gems/ruby-2.7.1/gems/mongoid-7.0.6 (which matches the aforementioned "gem" regex), but if you configure a path, bundler changes its directory structure, such that it looks like /Users/kyle/.rubygems/ruby/2.7.0/gems/sorbet-0.5.5472. This matches the "ruby stdlib" regex above, but not the gem regex. In either case, gems aren't recognized and loaded into Sorbet.

I've done a little digging/fidgeting, and I've come up with the following:

  • TracepointSerializer takes a list of Gem file paths, and is looking to return the path, version, and name based off those paths.
  • it gets called from GemGeneratorTracepoint, which seemingly monitors file paths as they are required from the Gemfile.
  • That requiring seems to happen here, and I think the Tracer is trying to extrapolate the file paths as they get required.
  • Toying around in Sorbet::Private::GemLoader.require_all_gems, it seems I'm able to get a gem path directly from a gem spec by running spec.__materialize__; spec.full_gem_path
  • If that's the information we're looking for, then a spec also provides #name and #version

Is it possible to refactor this to harvest the path, name, and version directly from the Gem Spec? I'm sure I'm simplifying and missing _something_, but maybe this sparks an idea at the very least

Bump on this. Anyone using Docker with official ruby image as a primary development environment is blocked by this.

Just got this issue too.

Was this page helpful?
0 / 5 - 0 ratings