From 848f878ad96c6b81c075feff42a60ca7de02026e Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Thu, 21 Dec 2023 13:45:47 -0700 Subject: [PATCH] don't evaluate the default lockfile at all in certain cases (#20) if an alternate lockfile is active, and while that's active for some reason the default lockfile is not evaluatable, just don't evaluate it (but without having to know outside of ruby which one will be active) --- README.md | 27 +++++++++++++++++++++++++++ lib/bundler/multilock.rb | 3 ++- spec/bundler/multilock_spec.rb | 19 +++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) 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)