diff --git a/README.md b/README.md index 6dc1f01..72e9070 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,33 @@ BUNDLE_LOCKFILE=rails-7.0 bundle exec rspec You can also dynamically select it in your Gemfile, and pass `current: true` to (exactly one!) `lockfile` method. +In some cases, you may want to essentially disable bundler-multilock's +syncing behavior, while still allowing the Gemfile to select the active +lockfile. For example, if you have gems in the default lockfile that cannot +be installed under a certain Ruby version, but still want to be able to CI +against that Ruby version, you may set it up like this: + +```ruby +lockfile active: RUBY_VERSION >= "2.7" do + gem "debug", "~> 1.9" +end + +lockfile "ruby-2.6", active: RUBY_VERSION < "2.7" do + gem "debug", "~> 1.8.0" +end +``` + +However, you cannot run a regular `bundle install` while running Ruby 2.6 in +this situation, since simply evaluating the default lockfile's block, even +for checking that the lockfiles are valid, will raise an exception that debug +1.9.0 require Ruby 2.7. You could set `BUNDLE_LOCKFILE=ruby-2.6` to have +bundler-multilock only consider the one lockfile, but then your CI may need +additional logic to _not_ set it for other Ruby versions. Instead, you can +set `BUNDLE_LOCKFILE=active`, which will not override the Gemfile's selection +of which lockfile is active, but still behave as if `BUNDLE_LOCKFILE` is set, +bypassing any other syncing logic and not evaluating the default lockfile in +our example. + ## Comparison to Appraisal [Appraisal](https://github.com/thoughtbot/appraisal) is a gem that might serve diff --git a/lib/bundler/multilock.rb b/lib/bundler/multilock.rb index c3a5ce5..f356c69 100644 --- a/lib/bundler/multilock.rb +++ b/lib/bundler/multilock.rb @@ -60,7 +60,8 @@ def add_lockfile(lockfile = nil, raise ArgumentError, "Lockfile #{lockfile} is already defined" end - env_lockfile = ENV["BUNDLE_LOCKFILE"]&.then { |l| expand_lockfile(l) } + env_lockfile = lockfile if active && ENV["BUNDLE_LOCKFILE"] == "active" + env_lockfile ||= ENV["BUNDLE_LOCKFILE"]&.then { |l| expand_lockfile(l) } active = env_lockfile == lockfile if env_lockfile if active && (old_active = lockfile_definitions.find { |definition| definition[:active] }) diff --git a/spec/bundler/multilock_spec.rb b/spec/bundler/multilock_spec.rb index ee1061f..32966ed 100644 --- a/spec/bundler/multilock_spec.rb +++ b/spec/bundler/multilock_spec.rb @@ -736,6 +736,25 @@ end end + it "does not evaluate the default lockfile at all if an alternate is active, " \ + "without specifying that lockfile explicitly" do + with_gemfile(<<~RUBY) do + gem "inst-jobs", "3.1.13" + + lockfile active: ENV["ALTERNATE"] != "1" do + raise "evaluated!" if ENV["ALTERNATE"] == "1" + end + + lockfile "alt", active: ENV["ALTERNATE"] == "1" do + gem "activerecord-pg-extensions" + end + RUBY + invoke_bundler("install") + + invoke_bundler("install", env: { "ALTERNATE" => "1", "BUNDLE_LOCKFILE" => "active" }) + end + end + private def create_local_gem(name, content = "", subdirectory: true)