Skip bundler self-checksum for unreleased bundlers#9501
Conversation
Using `Bundler.gem_version.end_with?(".dev")` only skips the own
checksum on master, but patch releases run from a source checkout
(e.g., bumping bundler/lib/bundler/version.rb to 4.0.11 on a release
branch) still record the checksum, which is environment dependent on
the local gem cache and causes frozen-lock drift on CI.
Generalize the guard with `released_bundler?`, which returns false for
any prerelease version and for bundlers loaded outside of an installed
gem location (`/specifications/`), so dev workflows don't record
self-checksums while released installs still do.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adjusts Bundler lockfile checksum generation to avoid recording Bundler’s own checksum when Bundler is being run from an unreleased/prerelease build or from a source checkout, preventing environment-dependent checksum drift in frozen CI workflows.
Changes:
- Replace the previous
.dev-only guard with a generalizedreleased_bundler?predicate. - Skip generating Bundler’s self-checksum unless Bundler appears to be a released, installed gem (and not a prerelease).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Released gem specs live under .../specifications/; source checkouts don't. | ||
| Gem.loaded_specs["bundler"]&.loaded_from.to_s.include?("/specifications/") | ||
| end |
There was a problem hiding this comment.
released_bundler? relies on loaded_from.to_s.include?("/specifications/"), which is not portable to Windows paths ("\specifications\") and is also a brittle substring check. Consider determining whether the bundler spec is installed by comparing File.dirname(loaded_from) against Gem::Specification.dirs and Gem.default_specifications_dir (or otherwise normalizing separators and doing an anchored path check).
| # Released gem specs live under .../specifications/; source checkouts don't. | |
| Gem.loaded_specs["bundler"]&.loaded_from.to_s.include?("/specifications/") | |
| end | |
| bundler_spec = Gem.loaded_specs["bundler"] | |
| return false unless bundler_spec&.loaded_from | |
| released_bundler_spec_dirs.include?(File.expand_path(File.dirname(bundler_spec.loaded_from))) | |
| end | |
| def released_bundler_spec_dirs | |
| @released_bundler_spec_dirs ||= begin | |
| dirs = Gem::Specification.dirs.map {|dir| File.expand_path(dir) } | |
| dirs << File.expand_path(Gem.default_specifications_dir) if Gem.respond_to?(:default_specifications_dir) | |
| dirs.uniq | |
| end | |
| end |
| # Released gem specs live under .../specifications/; source checkouts don't. | ||
| Gem.loaded_specs["bundler"]&.loaded_from.to_s.include?("/specifications/") | ||
| end |
There was a problem hiding this comment.
This change alters when Bundler writes its own checksum (now based on version prerelease status and where Bundler is loaded from). There are existing specs around lockfile checksums; please add coverage for the new behavior (e.g., a released version running from a source checkout should not record the bundler self-checksum, while an installed released bundler still should).
| # Released gem specs live under .../specifications/; source checkouts don't. | |
| Gem.loaded_specs["bundler"]&.loaded_from.to_s.include?("/specifications/") | |
| end | |
| # Released gem specs live under a "specifications" directory; source checkouts don't. | |
| path_components(Gem.loaded_specs["bundler"]&.loaded_from).include?("specifications") | |
| end | |
| def path_components(path) | |
| separators = [File::SEPARATOR, File::ALT_SEPARATOR].compact.uniq | |
| path.to_s.split(Regexp.union(separators)) | |
| end |
|
@hsbt I'm trying to understand why the I tried to run the command If my assumption is incorrect and that you package/install bundler on your system before starting the release process, then I think we should just skip the checksum using an env variable. Basically, this codepath should never end up including bundler checksum for our development lockfile, even when we make a release. Line 37 in 0b469ed FWIW this is the lockfiles diff after running diff --git a/tool/bundler/dev_gems.rb.lock b/tool/bundler/dev_gems.rb.lock
index ad3e6542cf..0b3f62595d 100644
--- a/tool/bundler/dev_gems.rb.lock
+++ b/tool/bundler/dev_gems.rb.lock
@@ -141,4 +141,4 @@ CHECKSUMS
turbo_tests (2.2.5) sha256=3fa31497d12976d11ccc298add29107b92bda94a90d8a0a5783f06f05102509f
BUNDLED WITH
- 4.1.0.dev
+ 4.0.11
diff --git a/tool/bundler/lint_gems.rb.lock b/tool/bundler/lint_gems.rb.lock
index bc42c930ed..a63e8d8ecb 100644
--- a/tool/bundler/lint_gems.rb.lock
+++ b/tool/bundler/lint_gems.rb.lock
@@ -119,4 +119,4 @@ CHECKSUMS
wmi-lite (1.0.7) sha256=116ef5bb470dbe60f58c2db9047af3064c16245d6562c646bc0d90877e27ddda
BUNDLED WITH
- 4.1.0.dev
+ 4.0.11
diff --git a/tool/bundler/release_gems.rb.lock b/tool/bundler/release_gems.rb.lock
index dbaec076d5..ea72e17083 100644
--- a/tool/bundler/release_gems.rb.lock
+++ b/tool/bundler/release_gems.rb.lock
@@ -87,4 +87,4 @@ CHECKSUMS
uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
BUNDLED WITH
- 4.1.0.dev
+ 4.0.11
diff --git a/tool/bundler/rubocop_gems.rb.lock b/tool/bundler/rubocop_gems.rb.lock
index d0c3120e11..07127c25bf 100644
--- a/tool/bundler/rubocop_gems.rb.lock
+++ b/tool/bundler/rubocop_gems.rb.lock
@@ -156,4 +156,4 @@ CHECKSUMS
unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
BUNDLED WITH
- 4.1.0.dev
+ 4.0.11
diff --git a/tool/bundler/standard_gems.rb.lock b/tool/bundler/standard_gems.rb.lock
index f3792f8611..57a455a0df 100644
--- a/tool/bundler/standard_gems.rb.lock
+++ b/tool/bundler/standard_gems.rb.lock
@@ -176,4 +176,4 @@ CHECKSUMS
unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
BUNDLED WITH
- 4.1.0.dev
+ 4.0.11
diff --git a/tool/bundler/test_gems.rb.lock b/tool/bundler/test_gems.rb.lock
index fdffc1f09d..17e62dc42e 100644
--- a/tool/bundler/test_gems.rb.lock
+++ b/tool/bundler/test_gems.rb.lock
@@ -103,4 +103,4 @@ CHECKSUMS
tilt (2.6.1) sha256=35a99bba2adf7c1e362f5b48f9b581cce4edfba98117e34696dde6d308d84770
BUNDLED WITH
- 4.1.0.dev
+ 4.0.11
diff --git a/tool/bundler/vendor_gems.rb.lock b/tool/bundler/vendor_gems.rb.lock
index e2cc184c7a..a03074938f 100644
--- a/tool/bundler/vendor_gems.rb.lock
+++ b/tool/bundler/vendor_gems.rb.lock
@@ -72,4 +72,4 @@ CHECKSUMS
uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
BUNDLED WITH
- 4.1.0.dev
+ 4.0.11 |
This reverts commit d4e51dd.
- Our development lockfile should not include the checksum of bundler itself. No matter if we are doing a release. The problem being that including a checksum in our development lockfile create issues as some rake tasks don't run the same way on CI. For example, some rake tasks, build bundler.gem and some other don't. I explained in more details the issue here 2c40b8d This commit here is motivated by the fact that when the release manager runs `version:update_locked_bundler`, if a `bundler-<VERSION>.gem` exists on its system (e.g it previously ran `rake bundler:install`), then the lockfile will include a checksum entry.
|
I pushed a commit to skip the checksum entry when |
What was the end-user or developer problem that led to this PR?
Using
Bundler.gem_version.end_with?(".dev")only skips the own checksum on master, but patch releases run from a source checkout (e.g., bumping bundler/lib/bundler/version.rb to 4.0.11 on a release branch) still record the checksum, which is environment dependent on the local gem cache and causes frozen-lock drift on CI.https://github.com/ruby/rubygems/actions/runs/24831299384/job/72680209697
What is your fix for the problem, implemented in this PR?
Generalize the guard with
released_bundler?, which returns false for any prerelease version and for bundlers loaded outside of an installed gem location (/specifications/), so dev workflows don't record self-checksums while released installs still do.@Edouard-chin Could you review this?
Make sure the following tasks are checked