SlideShare a Scribd company logo
1 of 50
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 @hsbt
2023/09/21 Euruko 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 無断転載・無断複製の禁止
Hiroshi SHIBATA
https://hsbt.org
@hsbt
Ruby core team
RubyGems/Bundler team
Technical fellow at ANDPAD
Self introduction
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 無断転載・無断複製の禁止
Introduction of 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 無断転載・無断複製の禁止
I'm from Japan where is Ruby birth place
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 無断転載・無断複製の禁止
RubyKaigi 2023
RubyKaigi 2023 is Ruby conference in Japan
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 無断転載・無断複製の禁止
RubyKaigi 2024
RubyKaigi 2024 will be coming Okinawa island in Japan at May, 2024.
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 無断転載・無断複製の禁止
What are
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 無断転載・無断複製の禁止
What's package manager?
• User interface
• Provide commands like install/update/search 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 無断転載・無断複製の禁止
What’s rubygems?
RubyGems is a package manager of the Ruby language.
• rubygems/rubygems.org:
• The Ruby community's gem host.
• rubygems.org is maintain by infrastructure team of rubygems. It is
different team from rubygems cli team.
• rubygems/rubygems:
• Command line tool for rubygems.org
• Now, rubygems maintained rubygems team. I'm member of this team.
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 無断転載・無断複製の禁止
What’s Bundler?
# frozen_string_literal: true
source "https://rubygems.org"
gemspec
gem "rake", ">= 11.1”
• Bundler is also package manager of Ruby language
• Bundler focused version locking feature
• Bundler extends a lot of RubyGems resources like gemspec.
• Bundler works with Gemfile like:
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 無断転載・無断複製の禁止
Inside of Ruby libraries and
gem dependencies.
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 無断転載・無断複製の禁止
gemspec in your code
• You can see gemspec with `Gem.loaded_specs` like this:
• `Gem::Speci
fi
cation#dependencies` is important parts of your application.
>> Gem.loaded_specs["rack"]
=>
Gem::Speci
fi
cation.new do |s|
s.name = "rack"
s.version = Gem::Version.new("2.2.8")
s.installed_by_version = Gem::Version.new("3.4.10")
s.authors = ["Leah Neukirchen"]
s.date = Time.utc(2023, 7, 31)
s.dependencies = [Gem::Dependency.new("minitest", Gem::Requirement.new(["~> 5.0"]), :development),
Gem::Dependency.new("minitest-sprint", Gem::Requirement.new([">= 0"]), :development),
Gem::Dependency.new("minitest-global_expectations", Gem::Requirement.new([">= 0"]), :development),
Gem::Dependency.new("rake", Gem::Requirement.new([">= 0"]), :development)]
s.description = "Rack provides a minimal, modular and adaptable interface for developingnweb
applications in Ruby. By wrapping HTTP requests and responses innthe simplest way possible, it uni
fi
es
and distills the API for webnservers, web frameworks, and software in between (the so-
callednmiddleware) into a single method call.n"
(...snip...)
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 無断転載・無断複製の禁止
What's Default gems
• The Ruby core team released "Default gems" to the rubygems.org.
• You can install standard libraries of Ruby via RubyGems.
• Default gems are openssl, psych, json, etc… You can see all of
default gems at https://stdgems.org/
• Rubygems have a detection method for default gems.
>> require 'rss'
=> true
>> Gem.loaded_specs["rss"].default_gem?
=> false
>> require 'openssl'
=> true
>> Gem.loaded_specs["openssl"].default_gem?
=> true
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 Bundled gems
• We bundled *.gem and unpacked
fi
les to tarball package for Bundled
gems with `gems/bundled_gems` in ruby/ruby repository like this:
• `make install` installed Bundled gem your box.
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 with RubyGems
• RubyGems extends `require`,
`gem` and `warn`.
• Because Ruby startup time
is slow with RubyGems.
• Bundler resolve this slow
down.
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 無断転載・無断複製の禁止
Performance issues
• Bundler also extends RubyGems classes/methods. It's enabled when we used Bundler.
• `Gem::Specification#extension_dir` needs to handle git resource of Gemfile like this:
# for gem “rails”, git: “https://github.com/rails/rails"
alias_method :rg_extension_dir, :extension_dir
def extension_dir
# following instance variable is already used in original method
# and that is the reason to prefix it with bundler_ and add rubocop exception
@bundler_extension_dir ||= if source.respond_to?(:extension_dir_name)
unique_extension_dir = [source.extension_dir_name,
File.basename(full_gem_path)].uniq.join("-")
File.expand_path(File.join(extensions_dir, unique_extension_dir))
else
rg_extension_dir
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 無断転載・無断複製の禁止
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 無断転載・無断複製の禁止
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 無断転載・無断複製の禁止
Basic case of Gemfile
and 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 無断転載・無断複製の禁止
Basic case of Gemfile and Bundler
• How Bundler lock gem versions?
• I'll introduce how resolve these paths with examples.
# Gem
fi
le
# frozen_string_literal: true
source "https://rubygems.org"
gem "rss"
# Gem
fi
le.lock
GEM
remote: https://rubygems.org/
specs:
rexml (3.2.5)
rss (0.2.9)
rexml
PLATFORMS
arm64-darwin-23
DEPENDENCIES
rss
BUNDLED WITH
2.5.0.dev
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 Bundler.setup
def setup(*groups)
@definition.ensure_equivalent_gemfile_and_lockfile if
Bundler.frozen_bundle?
# Has to happen first
clean_load_path
specs = @definition.specs_for(groups)
SharedHelpers.set_bundle_environment
Bundler.rubygems.replace_entrypoints(specs)
# Activate the specs
load_paths = specs.map do |spec|
check_for_activated_spec!(spec)
Bundler.rubygems.mark_loaded(spec)
spec.load_paths.reject {|path| $LOAD_PATH.include?(path) }
end.reverse.flatten
Bundler.rubygems.add_to_load_path(load_paths)
setup_manpath
lock(:preserve_unknown_sections => true)
self
end
• `Bundler.setup` and
`Bundler.require` is most
important parts of Bundler
• These methods
defined at `runtime.rb`.
• `bundle exec` call
`Bundler.setup` and
`Kernel.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 無断転載・無断複製の禁止
Reset your environment with Bundler
@definition.ensure_equivalent_gemfile_and_lockfile if Bundler.frozen_bundle?
# Has to happen first
clean_load_path
• At first, Bundler update your lockfile and install new versions if it's
needed. After that, Reject gem paths that are not `require` yet.
def clean_load_path
loaded_gem_paths = Bundler.rubygems.loaded_gem_paths
$LOAD_PATH.reject! do |p|
resolved_path = resolve_path(p)
next if $LOADED_FEATURES.any? {|lf| lf.start_with?(resolved_path) }
loaded_gem_paths.delete(p)
end
$LOAD_PATH.uniq!
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 無断転載・無断複製の禁止
• `Bundler.definition` and `Bundler::Resolver` is core parts for this.
• Bundler.definition create instance of `Bundler::Resolver` and call
resolution methods inside `specs_for`.
• `specs` is instance of Bundler::SpecSet.
• Bundler inject `bundler` as dependency into Gemfile.
How select dependencies by Bundler.definition
specs = @definition.specs_for(groups)
SharedHelpers.set_bundle_environment
Bundler.rubygems.replace_entrypoints(specs)
>> specs.map(&:name)
=> ["bundler", "rexml", "rss"]
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 無断転載・無断複製の禁止
Basic scenario of Bundler resolution
• `Bundler.rubygems.replace_entrypoints` inject gemspecs of default
gems into dependencies of Gemfile.
specs = Declared in Gemfile: rails, nokogiri, sidekiq, etc...
default_spec = Default gems: csv, psych, json, etc...
+
Bundler.rubygems.default_stubs.each do |stub|
default_spec = stub.to_spec
default_spec_name = default_spec.name
next if specs_by_name.key?(default_spec_name)
specs << default_spec
specs_by_name[default_spec_name] = default_spec
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 無断転載・無断複製の禁止
Update your LOAD_PATH with scratch
~/.rbenv/versions/master/lib/ruby/gems/3.3.0+0/gems/rss-0.2.9/lib
~/.rbenv/versions/master/lib/ruby/gems/3.3.0+0/gems/rexml-3.2.5/lib
~/.rbenv/versions/master/lib/ruby/gems/3.3.0+0/gems/bundler-2.5.0.dev/lib
# Activate the specs
load_paths = specs.map do |spec|
check_for_activated_spec!(spec)
Bundler.rubygems.mark_loaded(spec)
spec.load_paths.reject {|path| $LOAD_PATH.include?(path) }
end.reverse.flatten
Bundler.rubygems.add_to_load_path(load_paths)
setup_manpath
lock(:preserve_unknown_sections => true)
self
• These logic is easy to understand. We generate paths generated by resolved gemspec.
`Gem::Specification#load_paths` returns load paths from gemspec.
• `load_paths` returns like this:
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 library
dependency 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 無断転載・無断複製の禁止
How works PubGrub
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 無断転載・無断複製の禁止
What's PubGrub?
• PubGrub is next generation resolution engine
developed by Natalie Weizenbaum a.k.a @nex3.
• PubGrub is for Dart language. But we
have Ruby implementation that is
`pub_grub`.
• If resolution conflict occurs with PubGrub,
PubGrub give up immediately to resolving loop.
This makes faster resolution with complex
Gemfile.
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 無断転載・無断複製の禁止
Easy scenario of PubGrub
source = PubGrub::StaticPackageSource.new do |s|
s.add 'foo', '2.0.0', deps: { 'bar' => '1.0.0' }
s.add 'foo', '1.0.0'
s.add 'bar', '1.0.0', deps: { 'foo' => '1.0.0' }
s.root deps: { 'bar' => '>= 1.0.0' }
end
solver = PubGrub::VersionSolver.new(source: source)
result = solver.solve
p result
#=> {#<PubGrub::Package :root>=>0, "bar"=>#<Gem::Version "1.0.0">,
"foo"=>#<Gem::Version "1.0.0">}
• This is basic scenario of dependency resolution.
• We can see Resolution with PubGrub::VersionSolver and package source definition
provided by 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 無断転載・無断複製の禁止
Easy scenario of PubGrub
I want
bar-1.0.0 or
higher
bar-1.0.0 foo-1.0.0
foo-2.0.0
• We want to use `bar >= 1.0.0`. bar-1.0.0 wants foo-1.0.0.
• We can get resolution result that is `bar-1.0.0` and `foo-1.0.0`.
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 無断転載・無断複製の禁止
Conflict scenario of PubGrub
source = PubGrub::StaticPackageSource.new do |s|
s.add 'foo', '2.0.0', deps: { 'bar' => '1.0.0' }
s.add 'foo', '1.0.0'
s.add 'bar', '1.0.0', deps: { 'foo' => '1.0.0' }
s.root deps: { 'foo' => '>= 2.0.0' }
end
solver = PubGrub::VersionSolver.new(source: source)
result = solver.solve
p result
#=> pub_grub/version_solver.rb:233:in `resolve_conflict': Could not find compatible
versions (PubGrub::SolveFailure)
• This is conflict scenario of dependency resolution.
• If PubGrub couldn't resolve their versions, it raises `SolveFailure`.
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 無断転載・無断複製の禁止
Easy scenario of PubGrub
I want
foo-2.0.0 or
higher
bar-1.0.0
foo-1.0.0
foo-2.0.0
• We want to use `foo >= 2.0.0`.
• But foo-2.0.0 wants bar-1.0.0, and bar-1.0.0 wants foo-1.0.0.
This is not
foo-2.0.0
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 bit of complex scenario of PubGrub
source = PubGrub::StaticPackageSource.new do |s|
s.add 'foo', '3.0.0', deps: { 'bar' => '> 1.0.0' }
s.add 'foo', '2.0.0', deps: { 'bar' => '1.0.0' }
s.add 'foo', '1.0.0'
s.add 'bar', '1.0.0', deps: { 'foo' => '1.0.0' }
s.add 'bar', '2.0.0'
s.add 'buzz', '1.0.0', deps: { 'foo' => '> 1.0.0' }
s.root deps: { 'buzz' => '1.0.0' }
end
solver = PubGrub::VersionSolver.new(source: source)
result = solver.solve
p result
#=> {#<PubGrub::Package :root>=>0, "buzz"=>#<Gem::Version "1.0.0">, "foo"=>#<Gem::Version
"3.0.0">, "bar"=>#<Gem::Version "2.0.0">}
• This is additional scenario for PubGrub. We have three versions of foo, two versions of bar, and buzz.
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 bit of complex scenario of PubGrub
I want
buzz-1.0.0
buzz-1.0.0 foo-1.0.0
foo-2.0.0
foo-3.0.0
bar-1.0.0
bar-2.0.0
This is not foo
> 1.0.0 for buzz
We want to use buzz-1.0.0, buzz-1.0.0
wants foo > 1.0.0. PubGrub resolve it
with foo-2.0.0 or foo-3.0.0, But foo-2.0.0
conflicts with bar-1.0.0.
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 bit of complex scenario of PubGrub
I want
buzz-1.0.0
buzz-1.0.0 foo-1.0.0
foo-2.0.0
foo-3.0.0
bar-1.0.0
bar-2.0.0
We finally get buzz-1.0.0,
foo-3.0.0 and bar-2.0.0
as resolution result.
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 happened with
`bundle update 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 無断転載・無断複製の禁止
Infinitely case of `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 無断転載・無断複製の禁止
Why rails loops infinite with bundle update?
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 happend called with setup_solver in Bundler?
• `bundle update` will create instance of `Resolver` for resolution.
• Resolver invoke `setup_solver` and `solve_versions`. `setup_solver` prepared all versions
of gemspec(called all_specs) and dependency tree and logger for `solve_versions`
>> @all_specs.keys
=> ["rails", "importmap-rails", "Rubyu0000", "RubyGemsu0000"]
>> @all_specs["rails"].map{|s| [s.name, s.version.to_s]}
=>
[["rails", "0.8.0"],
["rails", "0.8.5"],
...
["rails", "7.0.7.2"],
["rails", "7.0.8"]]
source "https://rubygems.org"
gem "rails"
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 無断転載・無断複製の禁止
How use PubGrub in Bundler?
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
• But real case happens resolution conflicts 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.
• Bundler will resolve dependencies defined at Gemfile and all_specs of
gem by PubGrub like sample case.
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 無断転載・無断複製の禁止
Real case of PubGrub resolution
I want
rails-7.0.8
and
importmap-
rails-1.2.1
rails-0.8.0
activerecord-...
rails-7.0.8
・
・
・
importmap-rails-0.1.0
・
・
・
importmap-rails-1.2.1
activemailer-...
activesupport-...
actionview-...
railties-...
actionpack-...
mini_mime-...
mail-...
minitest-...
tzinfo-...
thor-...
rake-...
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 無断転載・無断複製の禁止
Bundler handles conflict result of PubGrub
• 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
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?
(snip)
root, logger = setup_solver
Bundler.ui.debug "Retrying resolution...", true
retry
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 無断転載・無断複製の禁止
Bundler will propagate conflict result into next resolution
OK, I skip
importmap-
rails-1.2.1 and
its
dependencies.
rails-0.8.0
activerecord-...
rails-7.0.8
・
・
・
importmap-rails-0.1.0
・
・
・
importmap-rails-1.2.1
activemailer-...
activesupport-...
actionview-...
railties-...
actionpack-...
mini_mime-...
mail-...
minitest-...
tzinfo-...
thor-...
rake-...
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 無断転載・無断複製の禁止
Result of resolution with rails and importmap-rails
yay, I got the full
list of gems with
rails-7.0.8 and
importmap-
rails-1.2.1
activerecord-...
rails-7.0.8
importmap-rails-1.2.1
activemailer-...
actionview-...
GEM
remote: https://rubygems.org/
specs:
actioncable (7.0.8)
actionpack (= 7.0.8)
activesupport (= 7.0.8)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (7.0.8)
actionpack (= 7.0.8)
activejob (= 7.0.8)
activerecord (= 7.0.8)
activestorage (= 7.0.8)
activesupport (= 7.0.8)
mail (>= 2.7.1)
net-imap
net-pop
net-smtp
actionmailer (7.0.8)
actionpack (= 7.0.8)
actionview (= 7.0.8)
activejob (= 7.0.8)
activesupport (= 7.0.8)
mail (~> 2.5, >= 2.5.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 無断転載・無断複製の禁止
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 無断転載・無断複製の禁止
Resolve 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 無断転載・無断複製の禁止
Migration RubyGems and Bundler in the future
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 無断転載・無断複製の禁止
Conclusion
• I talked about...
• Knowledge RubyGems, Bundler and Package Manager.
• How works Bundler modify LOAD_PATH of Ruby
• How works PubGrub and Bundler
< Ruby is a programmer's best friend

More Related Content

Similar to How resolve Gem dependencies in your code?

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
 
Convert the notification feature to the notification microservice
Convert the notification feature to the notification microserviceConvert the notification feature to the notification microservice
Convert the notification feature to the notification microserviceDaisuke Yamashita
 
Business Success with Core Web Vitals
Business Success with Core Web VitalsBusiness Success with Core Web Vitals
Business Success with Core Web VitalsIzzi Smith
 
20190206 AWS Black Belt Online Seminar Amazon SageMaker Basic Session
20190206 AWS Black Belt Online Seminar Amazon SageMaker Basic Session20190206 AWS Black Belt Online Seminar Amazon SageMaker Basic Session
20190206 AWS Black Belt Online Seminar Amazon SageMaker Basic SessionAmazon Web Services Japan
 
State management for ios development
State management for ios developmentState management for ios development
State management for ios developmentDaisuke Yamashita
 
GDPR Compliance: Transparent Handing of Personally Identifiable Information i...
GDPR Compliance: Transparent Handing of Personally Identifiable Information i...GDPR Compliance: Transparent Handing of Personally Identifiable Information i...
GDPR Compliance: Transparent Handing of Personally Identifiable Information i...confluent
 
"Logo Maker’s micro guts — micro frontend at Fiverr", Yuriy Dadichin
"Logo Maker’s micro guts — micro frontend at Fiverr", Yuriy Dadichin"Logo Maker’s micro guts — micro frontend at Fiverr", Yuriy Dadichin
"Logo Maker’s micro guts — micro frontend at Fiverr", Yuriy DadichinFwdays
 
Building Secure Services using Containers
Building Secure Services using ContainersBuilding Secure Services using Containers
Building Secure Services using ContainersAmazon Web Services
 
Supercharge your Code to get optimal Database Performance
Supercharge your Code to get optimal Database PerformanceSupercharge your Code to get optimal Database Performance
Supercharge your Code to get optimal Database Performancegvenzl
 
Linux Foundation Live Webinar: Applying Governance to CI/CD
Linux Foundation Live Webinar: Applying Governance to CI/CDLinux Foundation Live Webinar: Applying Governance to CI/CD
Linux Foundation Live Webinar: Applying Governance to CI/CDTiffany Jachja
 
Not a Kubernetes fan? The state of PaaS in 2024
Not a Kubernetes fan? The state of PaaS in 2024Not a Kubernetes fan? The state of PaaS in 2024
Not a Kubernetes fan? The state of PaaS in 2024Anthony Dahanne
 
Android's security architecture
Android's security architectureAndroid's security architecture
Android's security architectureOfer Rivlin, CISSP
 
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
 
Android Penetration Testing - Day 3
Android Penetration Testing - Day 3Android Penetration Testing - Day 3
Android Penetration Testing - Day 3Mohammed Adam
 
Building Microservices with the Twelve Factor App Pattern on AWS
Building Microservices with the Twelve Factor App Pattern on AWSBuilding Microservices with the Twelve Factor App Pattern on AWS
Building Microservices with the Twelve Factor App Pattern on AWSAmazon Web Services
 
Supercharge GuardDuty with Partners: Threat Detection and Response at Scale (...
Supercharge GuardDuty with Partners: Threat Detection and Response at Scale (...Supercharge GuardDuty with Partners: Threat Detection and Response at Scale (...
Supercharge GuardDuty with Partners: Threat Detection and Response at Scale (...Amazon Web Services
 
NodeWay in my project & sails.js
NodeWay in my project & sails.jsNodeWay in my project & sails.js
NodeWay in my project & sails.jsDmytro Ovcharenko
 
Crea la tua prima serverless ledger-based app con QLDB e NodeJS
Crea la tua prima serverless ledger-based app con QLDB e NodeJSCrea la tua prima serverless ledger-based app con QLDB e NodeJS
Crea la tua prima serverless ledger-based app con QLDB e NodeJSAmazon Web Services
 

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

Ruby with cucmber
Ruby with cucmberRuby with cucmber
Ruby with cucmber
 
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...
 
Convert the notification feature to the notification microservice
Convert the notification feature to the notification microserviceConvert the notification feature to the notification microservice
Convert the notification feature to the notification microservice
 
Business Success with Core Web Vitals
Business Success with Core Web VitalsBusiness Success with Core Web Vitals
Business Success with Core Web Vitals
 
20190206 AWS Black Belt Online Seminar Amazon SageMaker Basic Session
20190206 AWS Black Belt Online Seminar Amazon SageMaker Basic Session20190206 AWS Black Belt Online Seminar Amazon SageMaker Basic Session
20190206 AWS Black Belt Online Seminar Amazon SageMaker Basic Session
 
State management for ios development
State management for ios developmentState management for ios development
State management for ios development
 
GDPR Compliance: Transparent Handing of Personally Identifiable Information i...
GDPR Compliance: Transparent Handing of Personally Identifiable Information i...GDPR Compliance: Transparent Handing of Personally Identifiable Information i...
GDPR Compliance: Transparent Handing of Personally Identifiable Information i...
 
"Logo Maker’s micro guts — micro frontend at Fiverr", Yuriy Dadichin
"Logo Maker’s micro guts — micro frontend at Fiverr", Yuriy Dadichin"Logo Maker’s micro guts — micro frontend at Fiverr", Yuriy Dadichin
"Logo Maker’s micro guts — micro frontend at Fiverr", Yuriy Dadichin
 
Building Secure Services using Containers
Building Secure Services using ContainersBuilding Secure Services using Containers
Building Secure Services using Containers
 
Supercharge your Code to get optimal Database Performance
Supercharge your Code to get optimal Database PerformanceSupercharge your Code to get optimal Database Performance
Supercharge your Code to get optimal Database Performance
 
Linux Foundation Live Webinar: Applying Governance to CI/CD
Linux Foundation Live Webinar: Applying Governance to CI/CDLinux Foundation Live Webinar: Applying Governance to CI/CD
Linux Foundation Live Webinar: Applying Governance to CI/CD
 
Not a Kubernetes fan? The state of PaaS in 2024
Not a Kubernetes fan? The state of PaaS in 2024Not a Kubernetes fan? The state of PaaS in 2024
Not a Kubernetes fan? The state of PaaS in 2024
 
Android's security architecture
Android's security architectureAndroid's security architecture
Android's security architecture
 
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
 
Android Penetration Testing - Day 3
Android Penetration Testing - Day 3Android Penetration Testing - Day 3
Android Penetration Testing - Day 3
 
Building Microservices with the Twelve Factor App Pattern on AWS
Building Microservices with the Twelve Factor App Pattern on AWSBuilding Microservices with the Twelve Factor App Pattern on AWS
Building Microservices with the Twelve Factor App Pattern on AWS
 
Supercharge GuardDuty with Partners: Threat Detection and Response at Scale (...
Supercharge GuardDuty with Partners: Threat Detection and Response at Scale (...Supercharge GuardDuty with Partners: Threat Detection and Response at Scale (...
Supercharge GuardDuty with Partners: Threat Detection and Response at Scale (...
 
A Snapshot of DevOps
A Snapshot of DevOpsA Snapshot of DevOps
A Snapshot of DevOps
 
NodeWay in my project & sails.js
NodeWay in my project & sails.jsNodeWay in my project & sails.js
NodeWay in my project & sails.js
 
Crea la tua prima serverless ledger-based app con QLDB e NodeJS
Crea la tua prima serverless ledger-based app con QLDB e NodeJSCrea la tua prima serverless ledger-based app con QLDB e NodeJS
Crea la tua prima serverless ledger-based app con QLDB e NodeJS
 

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

Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
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
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 

Recently uploaded (20)

Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 

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 @hsbt 2023/09/21 Euruko 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 無断転載・無断複製の禁止 Hiroshi SHIBATA https://hsbt.org @hsbt Ruby core team RubyGems/Bundler team Technical fellow at ANDPAD Self introduction
  • 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 無断転載・無断複製の禁止 Introduction of 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 無断転載・無断複製の禁止 I'm from Japan where is Ruby birth place
  • 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 無断転載・無断複製の禁止 RubyKaigi 2023 RubyKaigi 2023 is Ruby conference in Japan
  • 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 無断転載・無断複製の禁止 RubyKaigi 2024 RubyKaigi 2024 will be coming Okinawa island in Japan at May, 2024.
  • 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 Dependency Resolution with RubyGems/Bundler?
  • 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 無断転載・無断複製の禁止 What are RubyGems and Bundler?
  • 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 無断転載・無断複製の禁止 What's package manager? • User interface • Provide commands like install/update/search 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
  • 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 無断転載・無断複製の禁止 What’s rubygems? RubyGems is a package manager of the Ruby language. • rubygems/rubygems.org: • The Ruby community's gem host. • rubygems.org is maintain by infrastructure team of rubygems. It is different team from rubygems cli team. • rubygems/rubygems: • Command line tool for rubygems.org • Now, rubygems maintained rubygems team. I'm member of this team.
  • 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 無断転載・無断複製の禁止 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
  • 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 無断転載・無断複製の禁止 What’s Bundler? # frozen_string_literal: true source "https://rubygems.org" gemspec gem "rake", ">= 11.1” • Bundler is also package manager of Ruby language • Bundler focused version locking feature • Bundler extends a lot of RubyGems resources like gemspec. • Bundler works with Gemfile like:
  • 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 無断転載・無断複製の禁止 Inside of Ruby libraries and gem dependencies.
  • 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 無断転載・無断複製の禁止 gemspec in your code • You can see gemspec with `Gem.loaded_specs` like this: • `Gem::Speci fi cation#dependencies` is important parts of your application. >> Gem.loaded_specs["rack"] => Gem::Speci fi cation.new do |s| s.name = "rack" s.version = Gem::Version.new("2.2.8") s.installed_by_version = Gem::Version.new("3.4.10") s.authors = ["Leah Neukirchen"] s.date = Time.utc(2023, 7, 31) s.dependencies = [Gem::Dependency.new("minitest", Gem::Requirement.new(["~> 5.0"]), :development), Gem::Dependency.new("minitest-sprint", Gem::Requirement.new([">= 0"]), :development), Gem::Dependency.new("minitest-global_expectations", Gem::Requirement.new([">= 0"]), :development), Gem::Dependency.new("rake", Gem::Requirement.new([">= 0"]), :development)] s.description = "Rack provides a minimal, modular and adaptable interface for developingnweb applications in Ruby. By wrapping HTTP requests and responses innthe simplest way possible, it uni fi es and distills the API for webnservers, web frameworks, and software in between (the so- callednmiddleware) into a single method call.n" (...snip...) end
  • 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 無断転載・無断複製の禁止 What's Default gems • The Ruby core team released "Default gems" to the rubygems.org. • You can install standard libraries of Ruby via RubyGems. • Default gems are openssl, psych, json, etc… You can see all of default gems at https://stdgems.org/ • Rubygems have a detection method for default gems. >> require 'rss' => true >> Gem.loaded_specs["rss"].default_gem? => false >> require 'openssl' => true >> Gem.loaded_specs["openssl"].default_gem? => true
  • 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 無断転載・無断複製の禁止 What's Bundled gems • We bundled *.gem and unpacked fi les to tarball package for Bundled gems with `gems/bundled_gems` in ruby/ruby repository like this: • `make install` installed Bundled gem your box.
  • 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 無断転載・無断複製の禁止 Performance issues with RubyGems • RubyGems extends `require`, `gem` and `warn`. • Because Ruby startup time is slow with RubyGems. • Bundler resolve this slow down. 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)
  • 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 無断転載・無断複製の禁止 Performance issues • Bundler also extends RubyGems classes/methods. It's enabled when we used Bundler. • `Gem::Specification#extension_dir` needs to handle git resource of Gemfile like this: # for gem “rails”, git: “https://github.com/rails/rails" alias_method :rg_extension_dir, :extension_dir def extension_dir # following instance variable is already used in original method # and that is the reason to prefix it with bundler_ and add rubocop exception @bundler_extension_dir ||= if source.respond_to?(:extension_dir_name) unique_extension_dir = [source.extension_dir_name, File.basename(full_gem_path)].uniq.join("-") File.expand_path(File.join(extensions_dir, unique_extension_dir)) else rg_extension_dir end end
  • 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 無断転載・無断複製の禁止 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
  • 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 無断転載・無断複製の禁止 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.
  • 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 無断転載・無断複製の禁止 Basic case of Gemfile and bundle exec
  • 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 無断転載・無断複製の禁止 Basic case of Gemfile and Bundler • How Bundler lock gem versions? • I'll introduce how resolve these paths with examples. # Gem fi le # frozen_string_literal: true source "https://rubygems.org" gem "rss" # Gem fi le.lock GEM remote: https://rubygems.org/ specs: rexml (3.2.5) rss (0.2.9) rexml PLATFORMS arm64-darwin-23 DEPENDENCIES rss BUNDLED WITH 2.5.0.dev
  • 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 無断転載・無断複製の禁止 What's Bundler.setup def setup(*groups) @definition.ensure_equivalent_gemfile_and_lockfile if Bundler.frozen_bundle? # Has to happen first clean_load_path specs = @definition.specs_for(groups) SharedHelpers.set_bundle_environment Bundler.rubygems.replace_entrypoints(specs) # Activate the specs load_paths = specs.map do |spec| check_for_activated_spec!(spec) Bundler.rubygems.mark_loaded(spec) spec.load_paths.reject {|path| $LOAD_PATH.include?(path) } end.reverse.flatten Bundler.rubygems.add_to_load_path(load_paths) setup_manpath lock(:preserve_unknown_sections => true) self end • `Bundler.setup` and `Bundler.require` is most important parts of Bundler • These methods defined at `runtime.rb`. • `bundle exec` call `Bundler.setup` and `Kernel.exec`.
  • 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 無断転載・無断複製の禁止 Reset your environment with Bundler @definition.ensure_equivalent_gemfile_and_lockfile if Bundler.frozen_bundle? # Has to happen first clean_load_path • At first, Bundler update your lockfile and install new versions if it's needed. After that, Reject gem paths that are not `require` yet. def clean_load_path loaded_gem_paths = Bundler.rubygems.loaded_gem_paths $LOAD_PATH.reject! do |p| resolved_path = resolve_path(p) next if $LOADED_FEATURES.any? {|lf| lf.start_with?(resolved_path) } loaded_gem_paths.delete(p) end $LOAD_PATH.uniq! end
  • 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 無断転載・無断複製の禁止 • `Bundler.definition` and `Bundler::Resolver` is core parts for this. • Bundler.definition create instance of `Bundler::Resolver` and call resolution methods inside `specs_for`. • `specs` is instance of Bundler::SpecSet. • Bundler inject `bundler` as dependency into Gemfile. How select dependencies by Bundler.definition specs = @definition.specs_for(groups) SharedHelpers.set_bundle_environment Bundler.rubygems.replace_entrypoints(specs) >> specs.map(&:name) => ["bundler", "rexml", "rss"]
  • 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 無断転載・無断複製の禁止 Basic scenario of Bundler resolution • `Bundler.rubygems.replace_entrypoints` inject gemspecs of default gems into dependencies of Gemfile. specs = Declared in Gemfile: rails, nokogiri, sidekiq, etc... default_spec = Default gems: csv, psych, json, etc... + Bundler.rubygems.default_stubs.each do |stub| default_spec = stub.to_spec default_spec_name = default_spec.name next if specs_by_name.key?(default_spec_name) specs << default_spec specs_by_name[default_spec_name] = default_spec end
  • 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 無断転載・無断複製の禁止 Update your LOAD_PATH with scratch ~/.rbenv/versions/master/lib/ruby/gems/3.3.0+0/gems/rss-0.2.9/lib ~/.rbenv/versions/master/lib/ruby/gems/3.3.0+0/gems/rexml-3.2.5/lib ~/.rbenv/versions/master/lib/ruby/gems/3.3.0+0/gems/bundler-2.5.0.dev/lib # Activate the specs load_paths = specs.map do |spec| check_for_activated_spec!(spec) Bundler.rubygems.mark_loaded(spec) spec.load_paths.reject {|path| $LOAD_PATH.include?(path) } end.reverse.flatten Bundler.rubygems.add_to_load_path(load_paths) setup_manpath lock(:preserve_unknown_sections => true) self • These logic is easy to understand. We generate paths generated by resolved gemspec. `Gem::Specification#load_paths` returns load paths from gemspec. • `load_paths` returns like this:
  • 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 無断転載・無断複製の禁止 How resolve library dependency by Bundler?
  • 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 無断転載・無断複製の禁止 How works PubGrub and Bundler
  • 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 PubGrub? • PubGrub is next generation resolution engine developed by Natalie Weizenbaum a.k.a @nex3. • PubGrub is for Dart language. But we have Ruby implementation that is `pub_grub`. • If resolution conflict occurs with PubGrub, PubGrub give up immediately to resolving loop. This makes faster resolution with complex Gemfile. https://nex3.medium.com/pubgrub-2fb6470504f
  • 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 無断転載・無断複製の禁止 Easy scenario of PubGrub source = PubGrub::StaticPackageSource.new do |s| s.add 'foo', '2.0.0', deps: { 'bar' => '1.0.0' } s.add 'foo', '1.0.0' s.add 'bar', '1.0.0', deps: { 'foo' => '1.0.0' } s.root deps: { 'bar' => '>= 1.0.0' } end solver = PubGrub::VersionSolver.new(source: source) result = solver.solve p result #=> {#<PubGrub::Package :root>=>0, "bar"=>#<Gem::Version "1.0.0">, "foo"=>#<Gem::Version "1.0.0">} • This is basic scenario of dependency resolution. • We can see Resolution with PubGrub::VersionSolver and package source definition provided by PubGrub.
  • 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 無断転載・無断複製の禁止 Easy scenario of PubGrub I want bar-1.0.0 or higher bar-1.0.0 foo-1.0.0 foo-2.0.0 • We want to use `bar >= 1.0.0`. bar-1.0.0 wants foo-1.0.0. • We can get resolution result that is `bar-1.0.0` and `foo-1.0.0`.
  • 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 無断転載・無断複製の禁止 Conflict scenario of PubGrub source = PubGrub::StaticPackageSource.new do |s| s.add 'foo', '2.0.0', deps: { 'bar' => '1.0.0' } s.add 'foo', '1.0.0' s.add 'bar', '1.0.0', deps: { 'foo' => '1.0.0' } s.root deps: { 'foo' => '>= 2.0.0' } end solver = PubGrub::VersionSolver.new(source: source) result = solver.solve p result #=> pub_grub/version_solver.rb:233:in `resolve_conflict': Could not find compatible versions (PubGrub::SolveFailure) • This is conflict scenario of dependency resolution. • If PubGrub couldn't resolve their versions, it raises `SolveFailure`.
  • 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 無断転載・無断複製の禁止 Easy scenario of PubGrub I want foo-2.0.0 or higher bar-1.0.0 foo-1.0.0 foo-2.0.0 • We want to use `foo >= 2.0.0`. • But foo-2.0.0 wants bar-1.0.0, and bar-1.0.0 wants foo-1.0.0. This is not foo-2.0.0
  • 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 無断転載・無断複製の禁止 A bit of complex scenario of PubGrub source = PubGrub::StaticPackageSource.new do |s| s.add 'foo', '3.0.0', deps: { 'bar' => '> 1.0.0' } s.add 'foo', '2.0.0', deps: { 'bar' => '1.0.0' } s.add 'foo', '1.0.0' s.add 'bar', '1.0.0', deps: { 'foo' => '1.0.0' } s.add 'bar', '2.0.0' s.add 'buzz', '1.0.0', deps: { 'foo' => '> 1.0.0' } s.root deps: { 'buzz' => '1.0.0' } end solver = PubGrub::VersionSolver.new(source: source) result = solver.solve p result #=> {#<PubGrub::Package :root>=>0, "buzz"=>#<Gem::Version "1.0.0">, "foo"=>#<Gem::Version "3.0.0">, "bar"=>#<Gem::Version "2.0.0">} • This is additional scenario for PubGrub. We have three versions of foo, two versions of bar, and buzz.
  • 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 無断転載・無断複製の禁止 A bit of complex scenario of PubGrub I want buzz-1.0.0 buzz-1.0.0 foo-1.0.0 foo-2.0.0 foo-3.0.0 bar-1.0.0 bar-2.0.0 This is not foo > 1.0.0 for buzz We want to use buzz-1.0.0, buzz-1.0.0 wants foo > 1.0.0. PubGrub resolve it with foo-2.0.0 or foo-3.0.0, But foo-2.0.0 conflicts with bar-1.0.0.
  • 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 無断転載・無断複製の禁止 A bit of complex scenario of PubGrub I want buzz-1.0.0 buzz-1.0.0 foo-1.0.0 foo-2.0.0 foo-3.0.0 bar-1.0.0 bar-2.0.0 We finally get buzz-1.0.0, foo-3.0.0 and bar-2.0.0 as resolution result.
  • 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 happened with `bundle update rails`
  • 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 無断転載・無断複製の禁止 Infinitely case of `bundle update` $ bundle update Fetching gem metadata from https://rubygems.org/............ Resolving dependencies................................................................................................................................. ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ....................................................................................................................................................... ......................................................................^C
  • 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 無断転載・無断複製の禁止 Why rails loops infinite with bundle update? 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.
  • 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 無断転載・無断複製の禁止 What's happend called with setup_solver in Bundler? • `bundle update` will create instance of `Resolver` for resolution. • Resolver invoke `setup_solver` and `solve_versions`. `setup_solver` prepared all versions of gemspec(called all_specs) and dependency tree and logger for `solve_versions` >> @all_specs.keys => ["rails", "importmap-rails", "Rubyu0000", "RubyGemsu0000"] >> @all_specs["rails"].map{|s| [s.name, s.version.to_s]} => [["rails", "0.8.0"], ["rails", "0.8.5"], ... ["rails", "7.0.7.2"], ["rails", "7.0.8"]] source "https://rubygems.org" gem "rails" gem "importmap-rails"
  • 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 無断転載・無断複製の禁止 How use PubGrub in Bundler? 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 • But real case happens resolution conflicts 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. • Bundler will resolve dependencies defined at Gemfile and all_specs of gem by PubGrub like sample case.
  • 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 無断転載・無断複製の禁止 Real case of PubGrub resolution I want rails-7.0.8 and importmap- rails-1.2.1 rails-0.8.0 activerecord-... rails-7.0.8 ・ ・ ・ importmap-rails-0.1.0 ・ ・ ・ importmap-rails-1.2.1 activemailer-... activesupport-... actionview-... railties-... actionpack-... mini_mime-... mail-... minitest-... tzinfo-... thor-... rake-...
  • 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 無断転載・無断複製の禁止 Bundler handles conflict result of PubGrub • 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 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? (snip) root, logger = setup_solver Bundler.ui.debug "Retrying resolution...", true retry end
  • 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 無断転載・無断複製の禁止 Bundler will propagate conflict result into next resolution OK, I skip importmap- rails-1.2.1 and its dependencies. rails-0.8.0 activerecord-... rails-7.0.8 ・ ・ ・ importmap-rails-0.1.0 ・ ・ ・ importmap-rails-1.2.1 activemailer-... activesupport-... actionview-... railties-... actionpack-... mini_mime-... mail-... minitest-... tzinfo-... thor-... rake-...
  • 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 無断転載・無断複製の禁止 Result of resolution with rails and importmap-rails yay, I got the full list of gems with rails-7.0.8 and importmap- rails-1.2.1 activerecord-... rails-7.0.8 importmap-rails-1.2.1 activemailer-... actionview-... GEM remote: https://rubygems.org/ specs: actioncable (7.0.8) actionpack (= 7.0.8) activesupport (= 7.0.8) nio4r (~> 2.0) websocket-driver (>= 0.6.1) actionmailbox (7.0.8) actionpack (= 7.0.8) activejob (= 7.0.8) activerecord (= 7.0.8) activestorage (= 7.0.8) activesupport (= 7.0.8) mail (>= 2.7.1) net-imap net-pop net-smtp actionmailer (7.0.8) actionpack (= 7.0.8) actionview (= 7.0.8) activejob (= 7.0.8) activesupport (= 7.0.8) mail (~> 2.5, >= 2.5.4) ・ ・ ・
  • 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 無断転載・無断複製の禁止 Proposals for the future
  • 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 無断転載・無断複製の禁止 Resolve duplicates and redundant of code and commands
  • 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 無断転載・無断複製の禁止 Migration RubyGems and Bundler in the future Update Install Commands Bundler.definition Extended classes of RubyGems Resolver Resolver Engine PubGrub Update Commands Install Gem::Specification Request::Set Etc...
  • 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 無断転載・無断複製の禁止 Conclusion • I talked about... • Knowledge RubyGems, Bundler and Package Manager. • How works Bundler modify LOAD_PATH of Ruby • How works PubGrub and Bundler < Ruby is a programmer's best friend