SlideShare a Scribd company logo
1 of 54
Download to read offline
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
How resolve
Gem dependencies
in your code?
Hiroshi SHIBATA
2023/05/12 RubyKaigi 2023
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Self Introduction
Hiroshi SHIBATA
https://hsbt.org
@hsbt
Ruby core team
ANDPAD Fellow
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
ANDPAD のご紹介
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
ANDPAD のご紹介
Construction service in
Japan have many many
of problems in the future.
It’s time to provide DX
experiences to them.
図解入門業界研究 最新建設業界の動向とカラクリがよ
~
くわかる本[第4版]
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
What's Dependency Resolution
with RubyGems/Bundler?
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Knowledge & Definition
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
What's package manager?
• User interface
• Provide user interface to install package
• Dependency Resolution
• Resolve dependencies of package and provide list of name and
version of package
• Version locking (NEW!)
• Provide environment to lock specified versions of package
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Terminology
• Gem
• A package/library for the Ruby programming language
• Gem::Specification
• Class for defining metadata including name, version, platform, etc.
• gemspec
• File describing the Gem::Specification in RubyGems/Bundler
• This file is written by you for releasing gem
• This file is created at gem install time by RubyGems
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Terminology
• Resolution
• Ensuring that the dependency constraint are satisfied the combinatorial constraints of
multiple libraries.
• Resolver Engine
• Performs dependency resolution with library name and version combinations and provides a
list of libraries if resolved. RubyGems uses Mollinilo, Bundler uses PubGrub
• Resolver
• Provides the Resolver Engine with the necessary data abstraction and library dependency
resolution
• Provides list of libraries including their names and versions to be installed.
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
The current issues of
RubyGems and Bundler
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Architecture of RubyGems/Bundler
Update Install
Commands
Bundler.definition
Extended classes
of RubyGems
Resolver
Resolver Engine
PubGrub
Update
Commands
Install
Resolver
Resolver Engine
Molinillo
Gem::Specification
Request::Set
Etc...
RubyGems Bundler
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Performance issues
• Both RubyGems and Bundler are
slow
• Ruby startup time is also slow with
RubyGems
• RubyGems extends `require`,
`gem` and `warn`
• Users uses a trick that is `--
disable-gems`
def require(path) # :doc:
return gem_original_require(path) unless
Gem.discover_gems_on_require
begin
RUBYGEMS_ACTIVATION_MONITOR.enter
path = path.to_path if path.respond_to? :to_path
if spec = Gem.
fi
nd_unresolved_default_spec(path)
# Ensure -I beats a default gem
resolved_path = begin
rp = nil
(snip)
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Infinitely `bundle update`
$ bundle update
Fetching gem metadata from https://rubygems.org/............
Resolving
dependencies.................................................................................................................................
.......................................................................................................................................................
.......................................................................................................................................................
.......................................................................................................................................................
.......................................................................................................................................................
.......................................................................................................................................................
.......................................................................................................................................................
.......................................................................................................................................................
.......................................................................................................................................................
.......................................................................................................................................................
.......................................................................................................................................................
.......................................................................................................................................................
......................................................................^C
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Case Studies
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
`gem install *.gem`
does not work as expected
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
We are not sure why `gem install` is not working
We can't install the same version of default gems with local install
(`gem install pkg/foo.gem`) when default gems is the latest version.
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Deep dive into `gem install` command
def install(options, &block) # :yields: request, installer
(snip)
sorted_requests.each do |req|
if req.installed?
req.spec.spec.build_extensions
if @always_install.none? {|spec| spec == req.spec.spec }
yield req, nil if block_given?
next
end
end
`install_command.rb` > `install_gem` > `Gem::RequestSet#install`
Compared to the case where I just ran `gem install foo` and succeeded, it
looks like this `req.spec.spec.build_extensions` is skipped.
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
How works build_extensions
def build_extensions # :nodoc:
return if extensions.empty?
return if default_gem?
return if File.exist? gem_build_complete_path
return if !File.writable?(base_dir)
return if !File.exist?(File.join(base_dir, "extensions"))
(snip)
ui = Gem::SilentUI.new
Gem::DefaultUserInteraction.use_ui ui do
builder = Gem::Ext::Builder.new self
builder.build_extensions
end
ensure
ui&.close
Gem::Speci
fi
cation.unresolved_deps.replace unresolved_deps
end
This case skipped all
of guard conditions
and raise build error
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Success/Failure cases of gem install
• When you run `gem install foo`, the gemspec is `APISpeci
fi
cation` and
it does not have `Gem::Speci
fi
caiton#extensions`.
[Activation request
[APISpeci
fi
cation name: json version: 2.6.3 platform: ruby dependencies: [] set uri: https://index.rubygems.org/info/]
for [Dependency request json (= 2.6.3) requested by nil]]
[Activation request
[LocalSpeci
fi
cation name: json version: 2.6.3 platform: ruby dependencies: [] source: /Users/hsbt/path/to/pkg/json-2.6.3.gem]
for [Dependency request json (= 2.6.3) requested by nil]]
• When you run `gem i pkg/foo-x.y.z.gem`, gemspec is
`LocalSpeci
fi
cation`, not `APISpeci
fi
cation`. This gemspec contains all
the contents of foo.gemspec in the repository.
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
How resolve this issue?
• I added additional condition for `build_extensions`.
• RubyGems skipped the build if the same name and version of default
gems exists system-wide.
• I'm sorry to add another condition about default gems.
def build_extensions # :nodoc:
return if extensions.empty?
return if default_gem?
+ # we need to fresh build when same name and version of default gems
+ return if self.class.
fi
nd_by_full_name(full_name)&.default_gem?
return if File.exist? gem_build_complete_path
return if !File.writable?(base_dir)
return if !File.exist?(File.join(base_dir, "extensions"))
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
RubyGems is too complex and complicated
• gemspec has a complex tree of inherited relationships:
• The install/build logic are located all over the place
Gem::BasicSpeci
fi
cation
Gem::StubSpeci
fi
cation < Gem::BasicSpeci
fi
cation
Gem::Speci
fi
cation < Gem::BasicSpeci
fi
cation
Gem::Resolver::Speci
fi
cation
Gem::Resolver::APISpeci
fi
cation < Gem::Resolver::Speci
fi
cation
Gem::Resolver::LocalSpeci
fi
cation < Gem::Resolver::SpecSpeci
fi
cation
Gem::Resolver::GitSpeci
fi
cation < Gem::Resolver::SpecSpeci
fi
cation
Gem::Resolver::LockSpeci
fi
cation < Gem::Resolver::Speci
fi
cation
Gem::Resolver::IndexSpeci
fi
cation < Gem::Resolver::Speci
fi
cation
Gem::Resolver::VendorSpeci
fi
cation < Gem::Resolver::SpecSpeci
fi
cation
...
and extended speci
fi
cation by Bundler
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Warnings of
`bundle exec`
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
I got the report from k0kubun
k0kubun: I'm not sure why I got this warnings in spite of I already
compile erb with rake-compiler.
hsbt: You can resolve it with bumping version like `3.0.1.pre` because
it's default gems and latest version.
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Why did it show warning?
• The rake-compiler build C extension properly.
• `.bundle` or `.so` files exist under `lib` and `tmp` directory.
def missing_extensions?
return false if extensions.empty?
return false if default_gem?
return false if File.exist? gem_build_complete_path
true
end
This case skipped all of guard
conditions and show warning
message
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
What's gem.build_complete?
• RubyGems has the following value as `Gem::Specification#extension_dir`.
>> Gem::Speci
fi
cation.
fi
nd_by_name("json").extension_dir
=> "/Users/hsbt/.local/share/gem/extensions/arm64-darwin-22/3.3.0+0-static/json-2.6.3"
• Place a file `gem.build_complete` in the above directory when the build is complete.
• RubyGems checks whether the file exists or not to determine whether the build
is complete or not.
• However, the C extension files built by `rake-compiler` are not considered to be built
by RubyGems because they do not take the above specification.
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
The first try for resolving this issue
• I fixed it by adding new conditions to this `missing_extensions?`.
def missing_extensions?
(snip)
return false if (full_require_paths - [extension_dir]).any? do |path|
File.exist?(File.join(path, "#{name}.#{RbCon
fi
g::CONFIG['DLEXT']}")) ||
!Dir.glob(File.join(path, name, "*.#{RbCon
fi
g::CONFIG['DLEXT']}")).empty?
end
(snip)
• We have to search for the names in directories other than extension_dir (erb.so or erb/
erb.bundle ).
• There is no way for RubyGems to know what rake-compiler is doing, so we need to
search heuristic.
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
But...
• Review comment from Deivid who are one of primary maintainers
• This method is called when a gem is required. It's very
expensive to search all the full_require_paths in gemspec each
time.
• We already extend many of logic like this.
$ wc -l *
68 kernel_gem.rb
165 kernel_require.rb
49 kernel_warn.rb
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Final solution for this
• I changed to use `rubygems_ext.rb` in Bundler. This file can extend RubyGems only when run with
Bundler.
• When `gemspec` method is presented in the Gemfile, `source.root` is defined. We can handle some
conditions under the only `bundle exec`
alias_method :rg_missing_extensions?, :missing_extensions?
def missing_extensions?
if source.respond_to?(:root)
return false if raw_require_paths.any? do |path|
ext_dir = File.join(full_gem_path, path)
File.exist?(File.join(ext_dir, "#{name}.#{RbCon
fi
g::CONFIG["DLEXT"]}")) ||
!Dir.glob(File.join(ext_dir, name, "*.#{RbCon
fi
g::CONFIG["DLEXT"]}")).empty?
end
end
rg_missing_extensions?
end
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
`bundle update --conservative`
is not working as expected
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
What's --conservative option?
• What happens when you run `bundle update --conservative rails`
• Only gems in the rails dependency tree and Gemfile will be updated
• `gem install/update --conservative rails` behaves a bit differently
• Only install or update gems in the rails dependency tree
$ gem i rails
Successfully installed rails-7.0.4.3
1 gem installed
~
$ gem i rails --conservative
~
$
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Unexpected behavior of conservative option
• When we run `bundle update --conservative
rails` with following Gemfile
• It updated `timeout` version.
• I want only `activerecord`, `actionmailer`
that are directly depends with `rails`.
• Why are `rake` and other dependencies not
updated, but only the above gems are?
• Is it a bug or something?
$ bundle up --conservative rails
Fetching gem metadata from https://rubygems.org/..........
Resolving dependencies...
Using rake 13.0.5
(snip)
Using crass 1.0.6
Using timeout 0.3.2 (was 0.3.1)
Using bundler 2.4.12
(snip)
Using net-imap 0.3.4
Using activesupport 7.0.4.3 (was 7.0.4.2)
Using rails-html-sanitizer 1.5.0
Using websocket-driver 0.7.5
Using mail 2.8.1
Using activemodel 7.0.4.3 (was 7.0.4.2)
Using rails-dom-testing 2.0.3
Using globalid 1.1.0
Using activerecord 7.0.4.3 (was 7.0.4.2)
Using actionview 7.0.4.3 (was 7.0.4.2)
Using activejob 7.0.4.3 (was 7.0.4.2)
Using actionpack 7.0.4.3 (was 7.0.4.2)
Using actioncable 7.0.4.3 (was 7.0.4.2)
Using activestorage 7.0.4.3 (was 7.0.4.2)
Using railties 7.0.4.3 (was 7.0.4.2)
Using actionmailer 7.0.4.3 (was 7.0.4.2)
Using actiontext 7.0.4.3 (was 7.0.4.2)
Using importmap-rails 1.1.5
Using actionmailbox 7.0.4.3 (was 7.0.4.2)
Using rails 7.0.4.3 (was 7.0.4.2)
Bundle updated!
source "https://rubygems.org"
gem "rails", "7.0.4.3"
gem "importmap-rails"
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
It's expected behavior of Bundler
• Resolution conflicts occur when a dependent gem under rails, such as `railties`, is version-locked by
referencing another gem. `PubGrub::SolveFailure` exception occurs and this gem is sent to the retry list.
• For example, importmap-rails depends on `railtie`. `importmap-rails was sent into retry list.
• `railtie` and `activesupport` are used often as they are rails plugins, so they are almost always included
def solve_versions(root:, logger:)
solver = PubGrub::VersionSolver.new(:source => self, :root => root, :logger => logger)
result = solver.solve
result.map {|package, version| version.to_specs(package) }.
fl
atten.uniq
rescue PubGrub::SolveFailure => e
incompatibility = e.incompatibility
names_to_unlock, names_to_allow_prereleases_for, extended_explanation =
fi
nd_names_to_relax(incompatibility)
names_to_relax = names_to_unlock + names_to_allow_prereleases_for
if names_to_relax.any?
if names_to_unlock.any?
Bundler.ui.debug "Found con
fl
icts with locked dependencies. Will retry with #{names_to_unlock.join(", ")} unlocked...", true
@base.unlock_names(names_to_unlock)
end
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
It's enemy for Rails upgrade Engineer
Bundler could not
fi
nd compatible versions for gem "activesupport":
In Gem
fi
le:
inherited_resources (= 1.6.0) was resolved to 1.6.0, which depends on
has_scope (~> 0.6.0.rc) was resolved to 0.6.0, which depends on
activesupport (>= 3.2, < 5)
rails (= 4.2.0) was resolved to 4.2.0, which depends on
activesupport (= 4.2.0)
Bundler could not
fi
nd compatible versions for gem "railties":
In Gem
fi
le:
inherited_resources (= 1.6.0) was resolved to 1.6.0, which depends on
railties (>= 3.2, < 5)
rails (= 4.2.0) was resolved to 4.2.0, which depends on
railties (= 4.2.0)
inherited_resources (= 1.6.0) was resolved to 1.6.0, which depends on
responders was resolved to 1.1.2, which depends on
railties (>= 3.2, < 4.2)
This behavior is derivation of the following events frequently after
running `bundle update` at Bundler 2.3 or before.
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
What's changed in Bundler 2.4?
• If a resolution conflict occurs with
PubGrub from Bundler 2.4, the logic is
to give up immediately and ignore the
end of the dependency tree. It only
update target gems.
• `activerecord`, `railties`, etc. are
updated for this reason.
• rake and others are unchanged.
https://nex3.medium.com/pubgrub-2fb6470504f
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Tree swing cartoon
• Running "bundle update --nanika
rails" will update only rails and
the gems directly under it.
• This is difficult because
Bundler does not keep the
dependency hierarchy as
data
$ bundle up --nanika rails
Fetching gem metadata from https://rubygems.org/..........
Resolving dependencies...
Using rake 13.0.5
(snip)
Using crass 1.0.6
Using timeout 0.3.1
Using bundler 2.4.12
(snip)
Using net-imap 0.3.4
Using activesupport 7.0.4.3 (was 7.0.4.2)
Using rails-html-sanitizer 1.5.0
Using websocket-driver 0.7.5
Using mail 2.8.1
Using activemodel 7.0.4.3 (was 7.0.4.2)
Using rails-dom-testing 2.0.3
Using globalid 1.1.0
Using activerecord 7.0.4.3 (was 7.0.4.2)
Using actionview 7.0.4.3 (was 7.0.4.2)
Using activejob 7.0.4.3 (was 7.0.4.2)
Using actionpack 7.0.4.3 (was 7.0.4.2)
Using actioncable 7.0.4.3 (was 7.0.4.2)
Using activestorage 7.0.4.3 (was 7.0.4.2)
Using railties 7.0.4.3 (was 7.0.4.2)
Using actionmailer 7.0.4.3 (was 7.0.4.2)
Using actiontext 7.0.4.3 (was 7.0.4.2)
Using importmap-rails 1.1.5
Using actionmailbox 7.0.4.3 (was 7.0.4.2)
Using rails 7.0.4.3 (was 7.0.4.2)
Bundle updated!
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Proposals for the future
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Duplicates and redundant of
code and commands
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
What's I worked?
• I started to unify toolchains in rubygems repository
• Rake task(rubocop, test/spec, release...)
• The migration of Rubocop Rules(almost done)
• I want to unify commands and their code-base
• Merge to either `gem` and `bundle`
• Share the same Resolver Engine that is PubGrub
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
A difficult way for them
Update Install
Commands
Bundler.definition
Extended classes
of RubyGems
Resolver
Resolver Engine
PubGrub
Update
Commands
Install
Gem::Specification
Request::Set
Etc...
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Rubygems/Bundler
is too slow
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Refactor and re-organizing code about core extension
• Refactor require and gem methods on RubyGems. It's too complex
with historical reason.
• We avoid to scan all gemspecs in your system. In this fact,
RubyGems and Bundler is too slow with your largely rails
monolith.
• Ideally, it should be fast without caching tools like `bootsnap`.
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Impromovement about Resolver and its engine
• Resolver improvements in RubyGems and Bundler
• PubGrub is fast enough
• Complexity of passing data to PubGrub/Molinillo and receiving results from
PubGrub/Molinillo
• There appears to be duplicate data and repeated runs.
• I'm wondering if it's unnecessary to simply use `bundle update rails` to
run `rails` dependencies 3 times...?
• I still don't understand it well enough, so I'll work on it!
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Conclusion
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Conclusion
• I talked about some issues and recent fixes. What should be
RubyGems and Bundler by maintainer's view.
• I will do my best to make the experience even better!
• Thanks to ANDPAD, I am able to spend more time focusing
• Also Thanks to attend my talk.
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Appendix
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Example of mixing C extensions
in multiple Ruby versions
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
Ignoring .... の Warning は何か
• The following message is displayed when RubyGems does not
determine that the C extension is already installed
Ignoring erb-4.0.2 because its extensions are not built. Try: gem pristine erb --version 4.0.2
• This message often appears when using chruby or setting your own
GEM_HOME.
• If the three conditions of `missing_extension?` (especially
gem.build_complete) are not met, the extension is not considered to be built.
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
とりあえず解決するには?
• Run `gem pristine --extension
• Run reinstallation with the gem files already downloaded
• Note that this command will run all the C extension gems you
have installed (even different versions).
• You must have about 50-100 C extension gems at your disposal...?
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
流石に使いにくいのでちょっとした改善をいれた
• Added `--only-missing` option to RubyGems 3.5 (Ruby 3.3 or later)
• This option rebuilds only C extensions with `missing_extensions?
elsif options[:extensions_set] &&
options[:extensions] && options[:args].empty?
Gem::Speci
fi
cation.select do |spec|
spec.extensions && !spec.extensions.empty?
end
elsif options[:only_missing_extensions]
Gem::Speci
fi
cation.select do |spec|
spec.missing_extensions?
end
else
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
C 拡張の gem における Warning 以上の問題点
• If you are using multiple Ruby versions and have a common
GEM_HOME, you may have problems above Warning.
• gemspec and lib are not separated by Ruby version.
• Therefore, reuqire of C extensions built/installed with different
Ruby versions will cause SEGV.
• C extension directories (extension_dir) are separated
• Should we use extension_dir instead of lib to require C extensions?
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
更に一歩進んだ提案
• In theory, all Ruby versions can share Gem files
• Pure Ruby libraries can be shared by nature
• GEM_HOME is also a common philosophy.
• extension_dir is originally in full_require_paths, so it can be required naively,
and there are no accidents because it is separated by Ruby version.
• This can be achieved by not putting C extensions under lib.
• When you change Ruby version, you can't say "Oh.... I need to bundle install
again..." when changing Ruby versions. This is very eco-friendly and productive.
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
lib の下から C 拡張をすべて消すスクリプト
require "rbcon
fi
g"
require "pathname"
gems = Gem::Speci
fi
cation.select { |spec|
spec.platform == RUBY_ENGINE && !spec.extensions.empty?
}.compact.uniq.map { |spec|
[spec.name, spec.version]
}
gems.each do |n, v|
s = Gem::Speci
fi
cation.
fi
nd_all_by_full_name("#{n}-#{v}").
fi
rst
(s.full_require_paths - [s.extension_dir]).each do |path|
Dir.glob(File.join(path, "**/*")).each do |
fi
le|
if Pathname(
fi
le).extname == ".#{RbCon
fi
g::CONFIG["DLEXT"]}"
puts "Deleting #{
fi
le}"
File.delete(
fi
le)
end
end
end
end
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
歴史的な経緯もあって難航中
• RubyGems 3.4 now does make clean after building C extensions
• Some gems required or passed to ffi C extensions that were
built in the build directory and not in extension_dir or lib...
• Fixed it all.
• Bundler also seems to have code that expects to be under lib...
Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止
今後に向けて
• In the meantime, I created a pull-req that can be turned off at the
configuration level.
• https://github.com/rubygems/rubygems/pull/6463
• Someone please try it.
• Putting `install_extension_in_lib: false` in gemrc will not install C
extensions under lib. Eco.

More Related Content

Similar to How resolve Gem dependencies in your code?

State management for ios development
State management for ios developmentState management for ios development
State management for ios developmentDaisuke Yamashita
 
OSS Tools: Creating a Reverse Engineering Plug-in for r2frida
OSS Tools: Creating a Reverse Engineering Plug-in for r2fridaOSS Tools: Creating a Reverse Engineering Plug-in for r2frida
OSS Tools: Creating a Reverse Engineering Plug-in for r2fridaNowSecure
 
Service oriented cloud computing
Service oriented cloud computingService oriented cloud computing
Service oriented cloud computingMandar Pathrikar
 
FARO and LFM Software, a Winning Combination for Project Execution in the Ind...
FARO and LFM Software, a Winning Combination for Project Execution in the Ind...FARO and LFM Software, a Winning Combination for Project Execution in the Ind...
FARO and LFM Software, a Winning Combination for Project Execution in the Ind...Melissa Tiffany
 
Hado“OPS” or Had “oops”
Hado“OPS” or Had “oops”Hado“OPS” or Had “oops”
Hado“OPS” or Had “oops”Rocket Fuel Inc.
 
Building a Stock Prediction system with Machine Learning using Geode, SpringX...
Building a Stock Prediction system with Machine Learning using Geode, SpringX...Building a Stock Prediction system with Machine Learning using Geode, SpringX...
Building a Stock Prediction system with Machine Learning using Geode, SpringX...William Markito Oliveira
 
Android Penetration Testing - Day 3
Android Penetration Testing - Day 3Android Penetration Testing - Day 3
Android Penetration Testing - Day 3Mohammed Adam
 
CODE BLUE 2014 : Persisted: The active use and exploitation of Microsoft's Ap...
CODE BLUE 2014 : Persisted: The active use and exploitation of Microsoft's Ap...CODE BLUE 2014 : Persisted: The active use and exploitation of Microsoft's Ap...
CODE BLUE 2014 : Persisted: The active use and exploitation of Microsoft's Ap...CODE BLUE
 
Your Code Isn’t Static. Your Processes Shouldn’t be Either.
Your Code Isn’t Static. Your Processes Shouldn’t be Either.Your Code Isn’t Static. Your Processes Shouldn’t be Either.
Your Code Isn’t Static. Your Processes Shouldn’t be Either.DevOps.com
 
Embedded Development Systems-WearberryTec-Linked
Embedded Development Systems-WearberryTec-LinkedEmbedded Development Systems-WearberryTec-Linked
Embedded Development Systems-WearberryTec-LinkedAnil Kumar
 
Implementing a highly scalable stock prediction system with R, Geode, SpringX...
Implementing a highly scalable stock prediction system with R, Geode, SpringX...Implementing a highly scalable stock prediction system with R, Geode, SpringX...
Implementing a highly scalable stock prediction system with R, Geode, SpringX...William Markito Oliveira
 
Bloombase Spitfire StoreSafe QLogic 10GbE Ethernet Adapter Interoperability
Bloombase Spitfire StoreSafe QLogic 10GbE Ethernet Adapter InteroperabilityBloombase Spitfire StoreSafe QLogic 10GbE Ethernet Adapter Interoperability
Bloombase Spitfire StoreSafe QLogic 10GbE Ethernet Adapter InteroperabilityBloombase
 
Android P Security Updates: What You Need to Know
Android P Security Updates: What You Need to KnowAndroid P Security Updates: What You Need to Know
Android P Security Updates: What You Need to KnowNowSecure
 
Network Visibility For Openstack Operations
Network Visibility For Openstack OperationsNetwork Visibility For Openstack Operations
Network Visibility For Openstack OperationsDebojyoti Dutta
 
eFolder Webinar, Seven Great Reasons to Upgrade Legacy BDRs Now
eFolder Webinar, Seven Great Reasons to Upgrade Legacy BDRs NoweFolder Webinar, Seven Great Reasons to Upgrade Legacy BDRs Now
eFolder Webinar, Seven Great Reasons to Upgrade Legacy BDRs NowDropbox
 
Android's security architecture
Android's security architectureAndroid's security architecture
Android's security architectureOfer Rivlin, CISSP
 

Similar to How resolve Gem dependencies in your code? (20)

State management for ios development
State management for ios developmentState management for ios development
State management for ios development
 
OSS Tools: Creating a Reverse Engineering Plug-in for r2frida
OSS Tools: Creating a Reverse Engineering Plug-in for r2fridaOSS Tools: Creating a Reverse Engineering Plug-in for r2frida
OSS Tools: Creating a Reverse Engineering Plug-in for r2frida
 
Service oriented cloud computing
Service oriented cloud computingService oriented cloud computing
Service oriented cloud computing
 
Ruby with cucmber
Ruby with cucmberRuby with cucmber
Ruby with cucmber
 
FARO and LFM Software, a Winning Combination for Project Execution in the Ind...
FARO and LFM Software, a Winning Combination for Project Execution in the Ind...FARO and LFM Software, a Winning Combination for Project Execution in the Ind...
FARO and LFM Software, a Winning Combination for Project Execution in the Ind...
 
Hado“OPS” or Had “oops”
Hado“OPS” or Had “oops”Hado“OPS” or Had “oops”
Hado“OPS” or Had “oops”
 
Building a Stock Prediction system with Machine Learning using Geode, SpringX...
Building a Stock Prediction system with Machine Learning using Geode, SpringX...Building a Stock Prediction system with Machine Learning using Geode, SpringX...
Building a Stock Prediction system with Machine Learning using Geode, SpringX...
 
Android Penetration Testing - Day 3
Android Penetration Testing - Day 3Android Penetration Testing - Day 3
Android Penetration Testing - Day 3
 
CODE BLUE 2014 : Persisted: The active use and exploitation of Microsoft's Ap...
CODE BLUE 2014 : Persisted: The active use and exploitation of Microsoft's Ap...CODE BLUE 2014 : Persisted: The active use and exploitation of Microsoft's Ap...
CODE BLUE 2014 : Persisted: The active use and exploitation of Microsoft's Ap...
 
Your Code Isn’t Static. Your Processes Shouldn’t be Either.
Your Code Isn’t Static. Your Processes Shouldn’t be Either.Your Code Isn’t Static. Your Processes Shouldn’t be Either.
Your Code Isn’t Static. Your Processes Shouldn’t be Either.
 
20100616 Deployit For N How
20100616 Deployit For N How20100616 Deployit For N How
20100616 Deployit For N How
 
Embedded Development Systems-WearberryTec-Linked
Embedded Development Systems-WearberryTec-LinkedEmbedded Development Systems-WearberryTec-Linked
Embedded Development Systems-WearberryTec-Linked
 
Implementing a highly scalable stock prediction system with R, Geode, SpringX...
Implementing a highly scalable stock prediction system with R, Geode, SpringX...Implementing a highly scalable stock prediction system with R, Geode, SpringX...
Implementing a highly scalable stock prediction system with R, Geode, SpringX...
 
potatotips_77.pdf
potatotips_77.pdfpotatotips_77.pdf
potatotips_77.pdf
 
Bloombase Spitfire StoreSafe QLogic 10GbE Ethernet Adapter Interoperability
Bloombase Spitfire StoreSafe QLogic 10GbE Ethernet Adapter InteroperabilityBloombase Spitfire StoreSafe QLogic 10GbE Ethernet Adapter Interoperability
Bloombase Spitfire StoreSafe QLogic 10GbE Ethernet Adapter Interoperability
 
Android P Security Updates: What You Need to Know
Android P Security Updates: What You Need to KnowAndroid P Security Updates: What You Need to Know
Android P Security Updates: What You Need to Know
 
Network Visibility For Openstack Operations
Network Visibility For Openstack OperationsNetwork Visibility For Openstack Operations
Network Visibility For Openstack Operations
 
A Snapshot of DevOps
A Snapshot of DevOpsA Snapshot of DevOps
A Snapshot of DevOps
 
eFolder Webinar, Seven Great Reasons to Upgrade Legacy BDRs Now
eFolder Webinar, Seven Great Reasons to Upgrade Legacy BDRs NoweFolder Webinar, Seven Great Reasons to Upgrade Legacy BDRs Now
eFolder Webinar, Seven Great Reasons to Upgrade Legacy BDRs Now
 
Android's security architecture
Android's security architectureAndroid's security architecture
Android's security architecture
 

More from Hiroshi SHIBATA

Ruby コミッターと歩む Ruby を用いたプロダクト開発
Ruby コミッターと歩む Ruby を用いたプロダクト開発Ruby コミッターと歩む Ruby を用いたプロダクト開発
Ruby コミッターと歩む Ruby を用いたプロダクト開発Hiroshi SHIBATA
 
Why ANDPAD commit Ruby and RubyKaigi?
Why ANDPAD commit Ruby and RubyKaigi?Why ANDPAD commit Ruby and RubyKaigi?
Why ANDPAD commit Ruby and RubyKaigi?Hiroshi SHIBATA
 
RailsGirls から始める エンジニアリングはじめの一歩
RailsGirls から始める エンジニアリングはじめの一歩RailsGirls から始める エンジニアリングはじめの一歩
RailsGirls から始める エンジニアリングはじめの一歩Hiroshi SHIBATA
 
How to develop the Standard Libraries of Ruby?
How to develop the Standard Libraries of Ruby?How to develop the Standard Libraries of Ruby?
How to develop the Standard Libraries of Ruby?Hiroshi SHIBATA
 
The details of CI/CD environment for Ruby
The details of CI/CD environment for RubyThe details of CI/CD environment for Ruby
The details of CI/CD environment for RubyHiroshi SHIBATA
 
Dependency Resolution with Standard Libraries
Dependency Resolution with Standard LibrariesDependency Resolution with Standard Libraries
Dependency Resolution with Standard LibrariesHiroshi SHIBATA
 
Roadmap for RubyGems 4 and Bundler 3
Roadmap for RubyGems 4 and Bundler 3Roadmap for RubyGems 4 and Bundler 3
Roadmap for RubyGems 4 and Bundler 3Hiroshi SHIBATA
 
The Future of library dependency management of Ruby
 The Future of library dependency management of Ruby The Future of library dependency management of Ruby
The Future of library dependency management of RubyHiroshi SHIBATA
 
Ruby Security the Hard Way
Ruby Security the Hard WayRuby Security the Hard Way
Ruby Security the Hard WayHiroshi SHIBATA
 
OSS Security the hard way
OSS Security the hard wayOSS Security the hard way
OSS Security the hard wayHiroshi SHIBATA
 
The Future of library dependency manageement of Ruby
The Future of library dependency manageement of RubyThe Future of library dependency manageement of Ruby
The Future of library dependency manageement of RubyHiroshi SHIBATA
 
The Future of Dependency Management for Ruby
The Future of Dependency Management for RubyThe Future of Dependency Management for Ruby
The Future of Dependency Management for RubyHiroshi SHIBATA
 
The Future of Bundled Bundler
The Future of Bundled BundlerThe Future of Bundled Bundler
The Future of Bundled BundlerHiroshi SHIBATA
 
Productive Organization with Ruby
Productive Organization with RubyProductive Organization with Ruby
Productive Organization with RubyHiroshi SHIBATA
 
How to distribute Ruby to the world
How to distribute Ruby to the worldHow to distribute Ruby to the world
How to distribute Ruby to the worldHiroshi SHIBATA
 

More from Hiroshi SHIBATA (20)

Ruby コミッターと歩む Ruby を用いたプロダクト開発
Ruby コミッターと歩む Ruby を用いたプロダクト開発Ruby コミッターと歩む Ruby を用いたプロダクト開発
Ruby コミッターと歩む Ruby を用いたプロダクト開発
 
Why ANDPAD commit Ruby and RubyKaigi?
Why ANDPAD commit Ruby and RubyKaigi?Why ANDPAD commit Ruby and RubyKaigi?
Why ANDPAD commit Ruby and RubyKaigi?
 
RailsGirls から始める エンジニアリングはじめの一歩
RailsGirls から始める エンジニアリングはじめの一歩RailsGirls から始める エンジニアリングはじめの一歩
RailsGirls から始める エンジニアリングはじめの一歩
 
How to develop the Standard Libraries of Ruby?
How to develop the Standard Libraries of Ruby?How to develop the Standard Libraries of Ruby?
How to develop the Standard Libraries of Ruby?
 
The details of CI/CD environment for Ruby
The details of CI/CD environment for RubyThe details of CI/CD environment for Ruby
The details of CI/CD environment for Ruby
 
Dependency Resolution with Standard Libraries
Dependency Resolution with Standard LibrariesDependency Resolution with Standard Libraries
Dependency Resolution with Standard Libraries
 
Roadmap for RubyGems 4 and Bundler 3
Roadmap for RubyGems 4 and Bundler 3Roadmap for RubyGems 4 and Bundler 3
Roadmap for RubyGems 4 and Bundler 3
 
The Future of library dependency management of Ruby
 The Future of library dependency management of Ruby The Future of library dependency management of Ruby
The Future of library dependency management of Ruby
 
Ruby Security the Hard Way
Ruby Security the Hard WayRuby Security the Hard Way
Ruby Security the Hard Way
 
OSS Security the hard way
OSS Security the hard wayOSS Security the hard way
OSS Security the hard way
 
The Future of library dependency manageement of Ruby
The Future of library dependency manageement of RubyThe Future of library dependency manageement of Ruby
The Future of library dependency manageement of Ruby
 
The Future of Dependency Management for Ruby
The Future of Dependency Management for RubyThe Future of Dependency Management for Ruby
The Future of Dependency Management for Ruby
 
The Future of Bundled Bundler
The Future of Bundled BundlerThe Future of Bundled Bundler
The Future of Bundled Bundler
 
What's new in RubyGems3
What's new in RubyGems3What's new in RubyGems3
What's new in RubyGems3
 
Productive Organization with Ruby
Productive Organization with RubyProductive Organization with Ruby
Productive Organization with Ruby
 
Gems on Ruby
Gems on RubyGems on Ruby
Gems on Ruby
 
Gems on Ruby
Gems on RubyGems on Ruby
Gems on Ruby
 
RubyGems 3 & 4
RubyGems 3 & 4RubyGems 3 & 4
RubyGems 3 & 4
 
RubyGems 3 & 4
RubyGems 3 & 4RubyGems 3 & 4
RubyGems 3 & 4
 
How to distribute Ruby to the world
How to distribute Ruby to the worldHow to distribute Ruby to the world
How to distribute Ruby to the world
 

Recently uploaded

The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?XfilesPro
 

Recently uploaded (20)

The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?
 

How resolve Gem dependencies in your code?

  • 1. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 How resolve Gem dependencies in your code? Hiroshi SHIBATA 2023/05/12 RubyKaigi 2023
  • 2. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Self Introduction Hiroshi SHIBATA https://hsbt.org @hsbt Ruby core team ANDPAD Fellow
  • 3. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 ANDPAD のご紹介
  • 4. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 ANDPAD のご紹介 Construction service in Japan have many many of problems in the future. It’s time to provide DX experiences to them. 図解入門業界研究 最新建設業界の動向とカラクリがよ ~ くわかる本[第4版]
  • 5. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 What's Dependency Resolution with RubyGems/Bundler?
  • 6. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Knowledge & Definition
  • 7. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 What's package manager? • User interface • Provide user interface to install package • Dependency Resolution • Resolve dependencies of package and provide list of name and version of package • Version locking (NEW!) • Provide environment to lock specified versions of package
  • 8. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Terminology • Gem • A package/library for the Ruby programming language • Gem::Specification • Class for defining metadata including name, version, platform, etc. • gemspec • File describing the Gem::Specification in RubyGems/Bundler • This file is written by you for releasing gem • This file is created at gem install time by RubyGems
  • 9. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Terminology • Resolution • Ensuring that the dependency constraint are satisfied the combinatorial constraints of multiple libraries. • Resolver Engine • Performs dependency resolution with library name and version combinations and provides a list of libraries if resolved. RubyGems uses Mollinilo, Bundler uses PubGrub • Resolver • Provides the Resolver Engine with the necessary data abstraction and library dependency resolution • Provides list of libraries including their names and versions to be installed.
  • 10. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 The current issues of RubyGems and Bundler
  • 11. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Architecture of RubyGems/Bundler Update Install Commands Bundler.definition Extended classes of RubyGems Resolver Resolver Engine PubGrub Update Commands Install Resolver Resolver Engine Molinillo Gem::Specification Request::Set Etc... RubyGems Bundler
  • 12. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Performance issues • Both RubyGems and Bundler are slow • Ruby startup time is also slow with RubyGems • RubyGems extends `require`, `gem` and `warn` • Users uses a trick that is `-- disable-gems` def require(path) # :doc: return gem_original_require(path) unless Gem.discover_gems_on_require begin RUBYGEMS_ACTIVATION_MONITOR.enter path = path.to_path if path.respond_to? :to_path if spec = Gem. fi nd_unresolved_default_spec(path) # Ensure -I beats a default gem resolved_path = begin rp = nil (snip)
  • 13. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Infinitely `bundle update` $ bundle update Fetching gem metadata from https://rubygems.org/............ Resolving dependencies................................................................................................................................. ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ......................................................................^C
  • 14. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Case Studies
  • 15. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 `gem install *.gem` does not work as expected
  • 16. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 We are not sure why `gem install` is not working We can't install the same version of default gems with local install (`gem install pkg/foo.gem`) when default gems is the latest version.
  • 17. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Deep dive into `gem install` command def install(options, &block) # :yields: request, installer (snip) sorted_requests.each do |req| if req.installed? req.spec.spec.build_extensions if @always_install.none? {|spec| spec == req.spec.spec } yield req, nil if block_given? next end end `install_command.rb` > `install_gem` > `Gem::RequestSet#install` Compared to the case where I just ran `gem install foo` and succeeded, it looks like this `req.spec.spec.build_extensions` is skipped.
  • 18. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 How works build_extensions def build_extensions # :nodoc: return if extensions.empty? return if default_gem? return if File.exist? gem_build_complete_path return if !File.writable?(base_dir) return if !File.exist?(File.join(base_dir, "extensions")) (snip) ui = Gem::SilentUI.new Gem::DefaultUserInteraction.use_ui ui do builder = Gem::Ext::Builder.new self builder.build_extensions end ensure ui&.close Gem::Speci fi cation.unresolved_deps.replace unresolved_deps end This case skipped all of guard conditions and raise build error
  • 19. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Success/Failure cases of gem install • When you run `gem install foo`, the gemspec is `APISpeci fi cation` and it does not have `Gem::Speci fi caiton#extensions`. [Activation request [APISpeci fi cation name: json version: 2.6.3 platform: ruby dependencies: [] set uri: https://index.rubygems.org/info/] for [Dependency request json (= 2.6.3) requested by nil]] [Activation request [LocalSpeci fi cation name: json version: 2.6.3 platform: ruby dependencies: [] source: /Users/hsbt/path/to/pkg/json-2.6.3.gem] for [Dependency request json (= 2.6.3) requested by nil]] • When you run `gem i pkg/foo-x.y.z.gem`, gemspec is `LocalSpeci fi cation`, not `APISpeci fi cation`. This gemspec contains all the contents of foo.gemspec in the repository.
  • 20. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 How resolve this issue? • I added additional condition for `build_extensions`. • RubyGems skipped the build if the same name and version of default gems exists system-wide. • I'm sorry to add another condition about default gems. def build_extensions # :nodoc: return if extensions.empty? return if default_gem? + # we need to fresh build when same name and version of default gems + return if self.class. fi nd_by_full_name(full_name)&.default_gem? return if File.exist? gem_build_complete_path return if !File.writable?(base_dir) return if !File.exist?(File.join(base_dir, "extensions"))
  • 21. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 RubyGems is too complex and complicated • gemspec has a complex tree of inherited relationships: • The install/build logic are located all over the place Gem::BasicSpeci fi cation Gem::StubSpeci fi cation < Gem::BasicSpeci fi cation Gem::Speci fi cation < Gem::BasicSpeci fi cation Gem::Resolver::Speci fi cation Gem::Resolver::APISpeci fi cation < Gem::Resolver::Speci fi cation Gem::Resolver::LocalSpeci fi cation < Gem::Resolver::SpecSpeci fi cation Gem::Resolver::GitSpeci fi cation < Gem::Resolver::SpecSpeci fi cation Gem::Resolver::LockSpeci fi cation < Gem::Resolver::Speci fi cation Gem::Resolver::IndexSpeci fi cation < Gem::Resolver::Speci fi cation Gem::Resolver::VendorSpeci fi cation < Gem::Resolver::SpecSpeci fi cation ... and extended speci fi cation by Bundler
  • 22. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Warnings of `bundle exec`
  • 23. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 I got the report from k0kubun k0kubun: I'm not sure why I got this warnings in spite of I already compile erb with rake-compiler. hsbt: You can resolve it with bumping version like `3.0.1.pre` because it's default gems and latest version.
  • 24. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Why did it show warning? • The rake-compiler build C extension properly. • `.bundle` or `.so` files exist under `lib` and `tmp` directory. def missing_extensions? return false if extensions.empty? return false if default_gem? return false if File.exist? gem_build_complete_path true end This case skipped all of guard conditions and show warning message
  • 25. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 What's gem.build_complete? • RubyGems has the following value as `Gem::Specification#extension_dir`. >> Gem::Speci fi cation. fi nd_by_name("json").extension_dir => "/Users/hsbt/.local/share/gem/extensions/arm64-darwin-22/3.3.0+0-static/json-2.6.3" • Place a file `gem.build_complete` in the above directory when the build is complete. • RubyGems checks whether the file exists or not to determine whether the build is complete or not. • However, the C extension files built by `rake-compiler` are not considered to be built by RubyGems because they do not take the above specification.
  • 26. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 The first try for resolving this issue • I fixed it by adding new conditions to this `missing_extensions?`. def missing_extensions? (snip) return false if (full_require_paths - [extension_dir]).any? do |path| File.exist?(File.join(path, "#{name}.#{RbCon fi g::CONFIG['DLEXT']}")) || !Dir.glob(File.join(path, name, "*.#{RbCon fi g::CONFIG['DLEXT']}")).empty? end (snip) • We have to search for the names in directories other than extension_dir (erb.so or erb/ erb.bundle ). • There is no way for RubyGems to know what rake-compiler is doing, so we need to search heuristic.
  • 27. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 But... • Review comment from Deivid who are one of primary maintainers • This method is called when a gem is required. It's very expensive to search all the full_require_paths in gemspec each time. • We already extend many of logic like this. $ wc -l * 68 kernel_gem.rb 165 kernel_require.rb 49 kernel_warn.rb
  • 28. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Final solution for this • I changed to use `rubygems_ext.rb` in Bundler. This file can extend RubyGems only when run with Bundler. • When `gemspec` method is presented in the Gemfile, `source.root` is defined. We can handle some conditions under the only `bundle exec` alias_method :rg_missing_extensions?, :missing_extensions? def missing_extensions? if source.respond_to?(:root) return false if raw_require_paths.any? do |path| ext_dir = File.join(full_gem_path, path) File.exist?(File.join(ext_dir, "#{name}.#{RbCon fi g::CONFIG["DLEXT"]}")) || !Dir.glob(File.join(ext_dir, name, "*.#{RbCon fi g::CONFIG["DLEXT"]}")).empty? end end rg_missing_extensions? end
  • 29. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 `bundle update --conservative` is not working as expected
  • 30. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 What's --conservative option? • What happens when you run `bundle update --conservative rails` • Only gems in the rails dependency tree and Gemfile will be updated • `gem install/update --conservative rails` behaves a bit differently • Only install or update gems in the rails dependency tree $ gem i rails Successfully installed rails-7.0.4.3 1 gem installed ~ $ gem i rails --conservative ~ $
  • 31. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Unexpected behavior of conservative option • When we run `bundle update --conservative rails` with following Gemfile • It updated `timeout` version. • I want only `activerecord`, `actionmailer` that are directly depends with `rails`. • Why are `rake` and other dependencies not updated, but only the above gems are? • Is it a bug or something? $ bundle up --conservative rails Fetching gem metadata from https://rubygems.org/.......... Resolving dependencies... Using rake 13.0.5 (snip) Using crass 1.0.6 Using timeout 0.3.2 (was 0.3.1) Using bundler 2.4.12 (snip) Using net-imap 0.3.4 Using activesupport 7.0.4.3 (was 7.0.4.2) Using rails-html-sanitizer 1.5.0 Using websocket-driver 0.7.5 Using mail 2.8.1 Using activemodel 7.0.4.3 (was 7.0.4.2) Using rails-dom-testing 2.0.3 Using globalid 1.1.0 Using activerecord 7.0.4.3 (was 7.0.4.2) Using actionview 7.0.4.3 (was 7.0.4.2) Using activejob 7.0.4.3 (was 7.0.4.2) Using actionpack 7.0.4.3 (was 7.0.4.2) Using actioncable 7.0.4.3 (was 7.0.4.2) Using activestorage 7.0.4.3 (was 7.0.4.2) Using railties 7.0.4.3 (was 7.0.4.2) Using actionmailer 7.0.4.3 (was 7.0.4.2) Using actiontext 7.0.4.3 (was 7.0.4.2) Using importmap-rails 1.1.5 Using actionmailbox 7.0.4.3 (was 7.0.4.2) Using rails 7.0.4.3 (was 7.0.4.2) Bundle updated! source "https://rubygems.org" gem "rails", "7.0.4.3" gem "importmap-rails"
  • 32. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 It's expected behavior of Bundler • Resolution conflicts occur when a dependent gem under rails, such as `railties`, is version-locked by referencing another gem. `PubGrub::SolveFailure` exception occurs and this gem is sent to the retry list. • For example, importmap-rails depends on `railtie`. `importmap-rails was sent into retry list. • `railtie` and `activesupport` are used often as they are rails plugins, so they are almost always included def solve_versions(root:, logger:) solver = PubGrub::VersionSolver.new(:source => self, :root => root, :logger => logger) result = solver.solve result.map {|package, version| version.to_specs(package) }. fl atten.uniq rescue PubGrub::SolveFailure => e incompatibility = e.incompatibility names_to_unlock, names_to_allow_prereleases_for, extended_explanation = fi nd_names_to_relax(incompatibility) names_to_relax = names_to_unlock + names_to_allow_prereleases_for if names_to_relax.any? if names_to_unlock.any? Bundler.ui.debug "Found con fl icts with locked dependencies. Will retry with #{names_to_unlock.join(", ")} unlocked...", true @base.unlock_names(names_to_unlock) end
  • 33. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 It's enemy for Rails upgrade Engineer Bundler could not fi nd compatible versions for gem "activesupport": In Gem fi le: inherited_resources (= 1.6.0) was resolved to 1.6.0, which depends on has_scope (~> 0.6.0.rc) was resolved to 0.6.0, which depends on activesupport (>= 3.2, < 5) rails (= 4.2.0) was resolved to 4.2.0, which depends on activesupport (= 4.2.0) Bundler could not fi nd compatible versions for gem "railties": In Gem fi le: inherited_resources (= 1.6.0) was resolved to 1.6.0, which depends on railties (>= 3.2, < 5) rails (= 4.2.0) was resolved to 4.2.0, which depends on railties (= 4.2.0) inherited_resources (= 1.6.0) was resolved to 1.6.0, which depends on responders was resolved to 1.1.2, which depends on railties (>= 3.2, < 4.2) This behavior is derivation of the following events frequently after running `bundle update` at Bundler 2.3 or before.
  • 34. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 What's changed in Bundler 2.4? • If a resolution conflict occurs with PubGrub from Bundler 2.4, the logic is to give up immediately and ignore the end of the dependency tree. It only update target gems. • `activerecord`, `railties`, etc. are updated for this reason. • rake and others are unchanged. https://nex3.medium.com/pubgrub-2fb6470504f
  • 35. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Tree swing cartoon • Running "bundle update --nanika rails" will update only rails and the gems directly under it. • This is difficult because Bundler does not keep the dependency hierarchy as data $ bundle up --nanika rails Fetching gem metadata from https://rubygems.org/.......... Resolving dependencies... Using rake 13.0.5 (snip) Using crass 1.0.6 Using timeout 0.3.1 Using bundler 2.4.12 (snip) Using net-imap 0.3.4 Using activesupport 7.0.4.3 (was 7.0.4.2) Using rails-html-sanitizer 1.5.0 Using websocket-driver 0.7.5 Using mail 2.8.1 Using activemodel 7.0.4.3 (was 7.0.4.2) Using rails-dom-testing 2.0.3 Using globalid 1.1.0 Using activerecord 7.0.4.3 (was 7.0.4.2) Using actionview 7.0.4.3 (was 7.0.4.2) Using activejob 7.0.4.3 (was 7.0.4.2) Using actionpack 7.0.4.3 (was 7.0.4.2) Using actioncable 7.0.4.3 (was 7.0.4.2) Using activestorage 7.0.4.3 (was 7.0.4.2) Using railties 7.0.4.3 (was 7.0.4.2) Using actionmailer 7.0.4.3 (was 7.0.4.2) Using actiontext 7.0.4.3 (was 7.0.4.2) Using importmap-rails 1.1.5 Using actionmailbox 7.0.4.3 (was 7.0.4.2) Using rails 7.0.4.3 (was 7.0.4.2) Bundle updated!
  • 36. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Proposals for the future
  • 37. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Duplicates and redundant of code and commands
  • 38. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 What's I worked? • I started to unify toolchains in rubygems repository • Rake task(rubocop, test/spec, release...) • The migration of Rubocop Rules(almost done) • I want to unify commands and their code-base • Merge to either `gem` and `bundle` • Share the same Resolver Engine that is PubGrub
  • 39. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 A difficult way for them Update Install Commands Bundler.definition Extended classes of RubyGems Resolver Resolver Engine PubGrub Update Commands Install Gem::Specification Request::Set Etc...
  • 40. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Rubygems/Bundler is too slow
  • 41. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Refactor and re-organizing code about core extension • Refactor require and gem methods on RubyGems. It's too complex with historical reason. • We avoid to scan all gemspecs in your system. In this fact, RubyGems and Bundler is too slow with your largely rails monolith. • Ideally, it should be fast without caching tools like `bootsnap`.
  • 42. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Impromovement about Resolver and its engine • Resolver improvements in RubyGems and Bundler • PubGrub is fast enough • Complexity of passing data to PubGrub/Molinillo and receiving results from PubGrub/Molinillo • There appears to be duplicate data and repeated runs. • I'm wondering if it's unnecessary to simply use `bundle update rails` to run `rails` dependencies 3 times...? • I still don't understand it well enough, so I'll work on it!
  • 43. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Conclusion
  • 44. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Conclusion • I talked about some issues and recent fixes. What should be RubyGems and Bundler by maintainer's view. • I will do my best to make the experience even better! • Thanks to ANDPAD, I am able to spend more time focusing • Also Thanks to attend my talk.
  • 45. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Appendix
  • 46. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Example of mixing C extensions in multiple Ruby versions
  • 47. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 Ignoring .... の Warning は何か • The following message is displayed when RubyGems does not determine that the C extension is already installed Ignoring erb-4.0.2 because its extensions are not built. Try: gem pristine erb --version 4.0.2 • This message often appears when using chruby or setting your own GEM_HOME. • If the three conditions of `missing_extension?` (especially gem.build_complete) are not met, the extension is not considered to be built.
  • 48. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 とりあえず解決するには? • Run `gem pristine --extension • Run reinstallation with the gem files already downloaded • Note that this command will run all the C extension gems you have installed (even different versions). • You must have about 50-100 C extension gems at your disposal...?
  • 49. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 流石に使いにくいのでちょっとした改善をいれた • Added `--only-missing` option to RubyGems 3.5 (Ruby 3.3 or later) • This option rebuilds only C extensions with `missing_extensions? elsif options[:extensions_set] && options[:extensions] && options[:args].empty? Gem::Speci fi cation.select do |spec| spec.extensions && !spec.extensions.empty? end elsif options[:only_missing_extensions] Gem::Speci fi cation.select do |spec| spec.missing_extensions? end else
  • 50. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 C 拡張の gem における Warning 以上の問題点 • If you are using multiple Ruby versions and have a common GEM_HOME, you may have problems above Warning. • gemspec and lib are not separated by Ruby version. • Therefore, reuqire of C extensions built/installed with different Ruby versions will cause SEGV. • C extension directories (extension_dir) are separated • Should we use extension_dir instead of lib to require C extensions?
  • 51. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 更に一歩進んだ提案 • In theory, all Ruby versions can share Gem files • Pure Ruby libraries can be shared by nature • GEM_HOME is also a common philosophy. • extension_dir is originally in full_require_paths, so it can be required naively, and there are no accidents because it is separated by Ruby version. • This can be achieved by not putting C extensions under lib. • When you change Ruby version, you can't say "Oh.... I need to bundle install again..." when changing Ruby versions. This is very eco-friendly and productive.
  • 52. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 lib の下から C 拡張をすべて消すスクリプト require "rbcon fi g" require "pathname" gems = Gem::Speci fi cation.select { |spec| spec.platform == RUBY_ENGINE && !spec.extensions.empty? }.compact.uniq.map { |spec| [spec.name, spec.version] } gems.each do |n, v| s = Gem::Speci fi cation. fi nd_all_by_full_name("#{n}-#{v}"). fi rst (s.full_require_paths - [s.extension_dir]).each do |path| Dir.glob(File.join(path, "**/*")).each do | fi le| if Pathname( fi le).extname == ".#{RbCon fi g::CONFIG["DLEXT"]}" puts "Deleting #{ fi le}" File.delete( fi le) end end end end
  • 53. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 歴史的な経緯もあって難航中 • RubyGems 3.4 now does make clean after building C extensions • Some gems required or passed to ffi C extensions that were built in the build directory and not in extension_dir or lib... • Fixed it all. • Bundler also seems to have code that expects to be under lib...
  • 54. Copyright © 2020 Present ANDPAD Inc. This information is confidential and was prepared by ANDPAD Inc. for the use of our client. It is not to be relied on by and 3rd party. Proprietary & Confidential 無断転載・無断複製の禁止 今後に向けて • In the meantime, I created a pull-req that can be turned off at the configuration level. • https://github.com/rubygems/rubygems/pull/6463 • Someone please try it. • Putting `install_extension_in_lib: false` in gemrc will not install C extensions under lib. Eco.