Prepare RubyGems 4.0.11 and Bundler 4.0.11#9496
Conversation
Lock the checksum of Bundler itself in the lockfile (cherry picked from commit 44f4b15)
Ensure the release CI doesn't break due to the Bundler checksum feature (cherry picked from commit 9baf3e0)
Agent-Logs-Url: https://github.com/ruby/rubygems/sessions/a9efe3b4-99c9-4af2-9954-a65a2859edfc Co-authored-by: hsbt <12301+hsbt@users.noreply.github.com> (cherry picked from commit 3d4e90a)
…el_tests' Agent-Logs-Url: https://github.com/ruby/rubygems/sessions/dd120552-e56f-4a0e-9143-ec483aa07bfc Co-authored-by: hsbt <12301+hsbt@users.noreply.github.com> (cherry picked from commit 56a9827)
… gem Agent-Logs-Url: https://github.com/ruby/rubygems/sessions/61efd9ab-67d3-4ce2-b81d-4b6e8ef07f99 Co-authored-by: hsbt <12301+hsbt@users.noreply.github.com> (cherry picked from commit bf73b51)
Agent-Logs-Url: https://github.com/ruby/rubygems/sessions/9cf2fa2e-02a9-4dde-a833-8ad11974e1eb Co-authored-by: hsbt <12301+hsbt@users.noreply.github.com> (cherry picked from commit 5ac4c84)
…version helpers Agent-Logs-Url: https://github.com/ruby/rubygems/sessions/4028db0e-e050-48af-9704-4219653a4753 Co-authored-by: hsbt <12301+hsbt@users.noreply.github.com> (cherry picked from commit 951ef62)
Change "and lock the mutex" to "and to lock the mutex" for correct parallel infinitive structure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> (cherry picked from commit 94f9267)
Fix the bundler version not being updated in dev/test lockfile (cherry picked from commit 4758fb5)
fix formatting for BUNDLE_PREFER_PATCH variable in man page (cherry picked from commit a3d2d2c)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> (cherry picked from commit 97d05b3)
Package registries are active supply chain attack targets. Recent high-profile incidents include the Axios NPM compromise (https://socket.dev/blog/axios-npm-package-compromised) and the LiteLLM PyPI compromise (https://docs.litellm.ai/blog/security-update-march-2026). RubyGems supports an MFA-required opt-in via gemspec metadata: spec.metadata["rubygems_mfa_required"] = "true" but most gems haven't enabled it. A big reason is discoverability. Nothing in the `bundle gem` flow mentions the option, so authors would need to already know it exists to find it. Reference: https://guides.rubygems.org/mfa-requirement-opt-in/ This commit adds a commented-out `spec.metadata["rubygems_mfa_required"] = "true"` line, along with a short explanatory comment and a reference link, to the gemspec template used by `bundle gem`. Default behavior is unchanged because the line is commented out, but every new gem author now sees the MFA opt-in right where they configure their gemspec. Opting in is then a matter of deleting the leading `# `. (cherry picked from commit 2fd3496)
Fix installing gems with native extensions + transitive dependencies (cherry picked from commit 49c0aff)
There was a problem hiding this comment.
Pull request overview
Prepares the RubyGems and Bundler 4.0.11 release by bumping versions, updating release notes, and adjusting Bundler behavior/tests/docs around lockfile checksums, dependency handling, and templates.
Changes:
- Bump RubyGems and Bundler versions to 4.0.11 and update changelogs/manpages.
- Extend lockfile checksum handling (including Bundler itself) and update associated specs/fixtures.
- Add/update tests and templates (MFA metadata hint, transitive native-extension install case, indirect dependency confusion warning spec).
Reviewed changes
Copilot reviewed 57 out of 57 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| test/rubygems/test_gem_stub_specification.rb | Fix stub gemspec fixture filenames to match gem names and avoid collisions. |
| test/rubygems/test_gem_commands_push_command.rb | Fix expected push response string to match created gem name/version. |
| lib/rubygems/commands/specification_command.rb | Clarify gem spec argument naming and error message wording. |
| lib/rubygems.rb | Bump RubyGems version to 4.0.11. |
| bundler/spec/support/checksums.rb | Extend checksum helper to support Bundler checksum and alternate gem file folders. |
| bundler/spec/runtime/setup_spec.rb | Disable lockfile checksums in a runtime spec to keep expectations stable. |
| bundler/spec/install/gems/resolving_spec.rb | Fix lockfile fixture dependency name to match test intent. |
| bundler/spec/install/gemfile/git_spec.rb | Fix heredoc indentation and a test description typo. |
| bundler/spec/commands/update_spec.rb | Update lockfile expectations and add Bundler checksum coverage in update specs. |
| bundler/spec/commands/newgem_spec.rb | Add spec asserting MFA metadata hint is present in generated gemspec. |
| bundler/spec/commands/lock_spec.rb | Update lock command spec expectations to use checksum helpers. |
| bundler/spec/commands/install_spec.rb | Add regression spec for transitive dependency needed at native extension build time. |
| bundler/spec/bundler/installer/spec_installation_spec.rb | Update unit specs for new dependency-install readiness behavior. |
| bundler/spec/bundler/definition_spec.rb | Add spec coverage for indirect dependency confusion warning behavior. |
| bundler/lib/bundler/version.rb | Bump Bundler version to 4.0.11. |
| bundler/lib/bundler/templates/newgem/newgem.gemspec.tt | Add commented-out rubygems_mfa_required metadata hint to template. |
| bundler/lib/bundler/source/rubygems.rb | Minor comment grammar fix. |
| bundler/lib/bundler/source/metadata.rb | Add a checksum store for the metadata source (Bundler-as-a-spec). |
| bundler/lib/bundler/man/gemfile.5 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-version.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-update.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-show.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-remove.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-pristine.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-plugin.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-platform.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-outdated.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-open.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-lock.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-list.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-licenses.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-issue.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-install.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-init.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-info.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-help.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-gem.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-fund.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-exec.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-env.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-doctor.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-console.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-config.1.ronn | Fix formatting for BUNDLE_PREFER_PATCH env var in docs source. |
| bundler/lib/bundler/man/bundle-config.1 | Regenerate manpage formatting for BUNDLE_PREFER_PATCH. |
| bundler/lib/bundler/man/bundle-clean.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-check.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-cache.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-binstubs.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/man/bundle-add.1 | Refresh generated manpage header date. |
| bundler/lib/bundler/lockfile_parser.rb | Allow parsing/storing Bundler checksum via a metadata source. |
| bundler/lib/bundler/lockfile_generator.rb | Include Bundler checksum in generated lockfile checksums section. |
| bundler/lib/bundler/installer/parallel_installer.rb | Ensure native-extension install readiness considers transitive deps. |
| bundler/lib/bundler/definition.rb | Merge metadata-source checksum store from lockfile into current sources. |
| bundler/CHANGELOG.md | Add Bundler 4.0.11 release notes. |
| Rakefile | Adjust task to update locked Bundler version in dev/test fixtures. |
| CHANGELOG.md | Add RubyGems 4.0.11 release notes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| Dir.glob("{tool/bundler/*_gems.rb,bundler/spec/realworld/fixtures/*/Gemfile}").each do |file| | ||
| Spec::Rubygems.dev_bundle("update", "--bundler", version, gemfile: file) | ||
| Spec::Rubygems.dev_bundle("lock", "--bundler", "--bundler", version, gemfile: file) |
There was a problem hiding this comment.
rake version:update_locked_bundler currently runs bundle lock with --bundler passed twice and the version passed as a separate positional argument. bundle lock expects --bundler either without an argument or as --bundler=<version>, and typically needs --update to actually rewrite the lockfile. As written, this invocation is likely to no-op or error; adjust it to the intended argument structure (e.g., include --update and pass the version via --bundler=<version> if needed).
| Spec::Rubygems.dev_bundle("lock", "--bundler", "--bundler", version, gemfile: file) | |
| Spec::Rubygems.dev_bundle("lock", "--update", "--bundler=#{version}", gemfile: file) |
| describe "#precompute_source_requirements_for_indirect_dependencies?" do | ||
| before do | ||
| allow(Bundler::SharedHelpers).to receive(:find_gemfile) { Pathname.new("Gemfile") } | ||
| end | ||
|
|
||
| let(:sources) { Bundler::SourceList.new } | ||
| subject { Bundler::Definition.new(nil, [], sources, []) } | ||
|
|
||
| before do | ||
| allow(sources).to receive(:non_global_rubygems_sources).and_return(non_global_rubygems_sources) | ||
| end | ||
|
|
||
| context "when all the scoped sources implement a dependency API" do | ||
| let(:non_global_rubygems_sources) do | ||
| [ | ||
| double("non-global-source-0", "dependency_api_available?":true, to_s:"a"), | ||
| double("non-global-source-1", "dependency_api_available?":true, to_s:"b"), | ||
| ] | ||
| end | ||
|
|
||
| it "returns true without warning" do | ||
| expect(subject).not_to receive(:non_dependency_api_warning) | ||
|
|
||
| expect(subject.send(:precompute_source_requirements_for_indirect_dependencies?)).to be_truthy | ||
| end | ||
| end | ||
|
|
||
| context "when some scoped sources do not implement a dependency API" do | ||
| let(:non_global_rubygems_sources) do | ||
| [ | ||
| double("non-global-source-0", "dependency_api_available?":true, to_s:"a"), | ||
| double("non-global-source-1", "dependency_api_available?":false, to_s:"b"), | ||
| double("non-global-source-2", "dependency_api_available?":false, to_s:"c"), | ||
| ] | ||
| end | ||
|
|
||
| it "returns false and warns about the non-API sources" do | ||
| expect(Bundler.ui).to receive(:warn).with(<<-W.strip) | ||
| Your Gemfile contains scoped sources that don't implement a dependency API, namely: | ||
|
|
||
| * b | ||
| * c | ||
|
|
||
| Using the above gem servers may result in installing unexpected gems. To resolve this warning, make sure you use gem servers that implement dependency APIs, such as gemstash or geminabox gem servers. | ||
| W | ||
|
|
||
| expect(subject.send(:precompute_source_requirements_for_indirect_dependencies?)).to be_falsy | ||
| end |
There was a problem hiding this comment.
These new examples expect #precompute_source_requirements_for_indirect_dependencies? to emit a warning listing non-Dependency-API sources, but the current implementation in bundler/lib/bundler/definition.rb only returns a boolean (all?(&:dependency_api_available?)) and never calls Bundler.ui.warn. Either implement the warning behavior in Bundler::Definition (and make this method return false after warning when needed), or adjust the spec to match the actual behavior.
gem spec#9476