Skip to content

Preserve the locked Bundler checksum when the gem isn't cached#9658

Open
rwstauner wants to merge 1 commit into
ruby:masterfrom
Shopify:rwstauner/bundler-checksum-keep
Open

Preserve the locked Bundler checksum when the gem isn't cached#9658
rwstauner wants to merge 1 commit into
ruby:masterfrom
Shopify:rwstauner/bundler-checksum-keep

Conversation

@rwstauner

@rwstauner rwstauner commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

bundler_checksum recomputed the Bundler self-checksum from the locally cached gem on every lockfile write and emitted nothing when that gem was absent. As a result an existing bundler (x.y.z) sha256=... entry was silently dropped whenever the lockfile was rewritten on a machine that never downloaded the Bundler gem (e.g. a fresh checkout or CI), making the entry flicker in and out depending on the environment.

Fall back to the checksum already locked in the lockfile (parsed into the metadata source's checksum store and merged during source convergence) when a fresh one can't be computed, so the entry stays consistent across environments. A cached gem whose digest disagrees with the locked value still raises ChecksumMismatchError.

Guard that fallback so it only applies when the BUNDLED WITH version isn't changing (locked_gems.bundler_version == bundler_version_to_lock). When the locked Bundler version is being bumped and we can't compute a fresh checksum (the gem isn't cached), drop the entry instead of keeping it. Otherwise we'd lock a bundler (<old version>) sha256=... checksum that no longer matches the new BUNDLED WITH version, e.g. after bundle lock --update --bundler rewrites the section without switching the running Bundler.

The .dev and SKIP_BUNDLER_CHECKSUM opt-outs are unchanged: they remain hard 'do not record' signals used by Bundler/RubyGems' own development and release tasks.

What was the end-user or developer problem that led to this PR?

In the same project, some people would get the bundler checksum added to the lock file and on other people's computers it would end up getting removed.
People tired of seeing it added locally commit it, then people who don't get it locally remove it.

What is your fix for the problem, implemented in this PR?

If we don't have the cache for a new checksum, just leave the old one in place.

Make sure the following tasks are checked

@Edouard-chin Edouard-chin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. This make sense to me but I think we need to introduce a new guard and remove the checksum in the event where the BUNDLE_WITH section is modified and we can't compute a checksum due to the bundler gem missing. Otherwise we may end up with a BUNDLE_WITH version that no longer matches the checksum of the computed previous version

I believe we can tell whether the bundled with section matches with the runtime by doing sth like

definition.locked_gems.bundler_version == definition.bundler_version_to_lock

@semaperepelitsa

Copy link
Copy Markdown
Contributor

Running gem install bundler fixed it for me - but would be good to fix the root cause.

`bundler_checksum` recomputed the Bundler self-checksum from the locally
cached gem on every lockfile write and emitted nothing when that gem was
absent. As a result an existing `bundler (x.y.z) sha256=...` entry was
silently dropped whenever the lockfile was rewritten on a machine that
never downloaded the Bundler gem (e.g. a fresh checkout or CI), making the
entry flicker in and out depending on the environment.

Fall back to the checksum already locked in the lockfile (parsed into the
metadata source's checksum store and merged during source convergence) when
a fresh one can't be computed, so the entry stays consistent across
environments. A cached gem whose digest disagrees with the locked value
still raises ChecksumMismatchError.

Guard that fallback so it only applies when the `BUNDLED WITH` version isn't
changing (`locked_gems.bundler_version == bundler_version_to_lock`). When the
locked Bundler version is being bumped and we can't compute a fresh checksum
(the gem isn't cached), drop the entry instead of keeping it. Otherwise we'd
lock a `bundler (<old version>) sha256=...` checksum that no longer matches
the new `BUNDLED WITH` version, e.g. after `bundle lock --update --bundler`
rewrites the section without switching the running Bundler.

The `.dev` and SKIP_BUNDLER_CHECKSUM opt-outs are unchanged: they remain
hard 'do not record' signals used by Bundler/RubyGems' own development and
release tasks.
@rwstauner rwstauner force-pushed the rwstauner/bundler-checksum-keep branch from 949c8d6 to bdfd8d4 Compare July 6, 2026 22:07
@rwstauner rwstauner requested a review from Edouard-chin July 6, 2026 22:07
@rwstauner

Copy link
Copy Markdown
Contributor Author

Good call, @Edouard-chin, I added a handler for that scenario.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants