Skip to content

Inject required_rubygems_version >= 4.1.0.a into CA gems at build - #193

Merged
jenshenny merged 1 commit into
feature-branch-ca-changes-rubygemsfrom
ca-inject-rubygems-version-constraint
Sep 2, 2026
Merged

Inject required_rubygems_version >= 4.1.0.a into CA gems at build#193
jenshenny merged 1 commit into
feature-branch-ca-changes-rubygemsfrom
ca-inject-rubygems-version-constraint

Conversation

@jenshenny

@jenshenny jenshenny commented Sep 1, 2026

Copy link
Copy Markdown

Skinny gems built with --ruby-abi did not carry a required_rubygems_version constraint, so older RubyGems clients (4.0.x) could install them through the local path (gem install ./file.gem, vendor/cache, bundle install --local) with no warning. The content address was silently discarded and a gem scoped to one Ruby ABI would activate on an incompatible Ruby sharing that GEM_HOME.

Gem::Package.build now derives the required_rubygems_version for the built gem from the gemspec's own requirement:

  • unset requirements become >= 4.1.0.a
  • requirements that already satisfy that floor are left untouched
  • weaker requirements are rewritten to the floor plus any declared upper bounds and exclusions, with a warning since the built gem's metadata will differ from the gemspec
  • requirements that cap below the floor (e.g. < 4.0, ~> 3.5) raise at build time, since combined with the floor no RubyGems version could ever install the resulting gem

As with required_ruby_version, the derived value is propagated back to the original spec only after a successful build.

@jenshenny
jenshenny force-pushed the ca-inject-rubygems-version-constraint branch 3 times, most recently from 137b0c2 to ea51bda Compare September 2, 2026 01:45
@jenshenny

Copy link
Copy Markdown
Author
===== unset requirement (clean inject, no warning)
  Successfully built RubyGem
  Name: content_addressable_test
  Version: 0.1.1
  File: content_addressable_test-0.1.1-bfe80d24.gem

===== weak lower bound >= 3.0 (warning, raised to floor)
WARNING:  required_rubygems_version was changed from ">= 3.0" to ">= 4.1.0.beta1" for this build because content addressable gems can only be installed by RubyGems >= 4.1.0.beta1.
  Successfully built RubyGem
  Name: content_addressable_test
  Version: 0.1.1
  File: content_addressable_test-0.1.1-bfe80d24.gem

===== upper bound < 5.0 (warning, bound preserved)
WARNING:  required_rubygems_version was changed from "< 5.0" to ">= 4.1.0.beta1, < 5.0" for this build because content addressable gems can only be installed by RubyGems >= 4.1.0.beta1.
  Successfully built RubyGem
  Name: content_addressable_test
  Version: 0.1.1
  File: content_addressable_test-0.1.1-25c72c06.gem

===== already >= 4.2 (untouched, no warning)
  Successfully built RubyGem
  Name: content_addressable_test
  Version: 0.1.1
  File: content_addressable_test-0.1.1-96992460.gem

===== conflict: < 4.0
ERROR:  While executing gem ... (ArgumentError)
    Cannot build gem for Ruby ABI 4.0 because required_rubygems_version is set to < 4.0, which excludes RubyGems >= 4.1.0.beta1 required to install content addressable gems. Please remove or loosen the conflicting constraint.
	/Users/jennyshen/src/github.com/Shopify/rubygems/lib/rubygems/package.rb:756:in 'Gem::Package#normalized_required_rubygems_version'
	/Users/jennyshen/src/github.com/Shopify/rubygems/lib/rubygems/package.rb:402:in 'Gem::Package#build_content_addressable_file'

===== conflict: ~> 3.5
ERROR:  While executing gem ... (ArgumentError)
    Cannot build gem for Ruby ABI 4.0 because required_rubygems_version is set to ~> 3.5, which excludes RubyGems >= 4.1.0.beta1 required to install content addressable gems. Please remove or loosen the conflicting constraint.

===== conflict: = 3.5.9
ERROR:  While executing gem ... (ArgumentError)
    Cannot build gem for Ruby ABI 4.0 because required_rubygems_version is set to = 3.5.9, which excludes RubyGems >= 4.1.0.beta1 required to install content addressable gems. Please remove or loosen the conflicting constraint.

===== conflict: <= 4.1.0.beta0
ERROR:  While executing gem ... (ArgumentError)
    Cannot build gem for Ruby ABI 4.0 because required_rubygems_version is set to <= 4.1.0.beta0, which excludes RubyGems >= 4.1.0.beta1 required to install content addressable gems. Please remove or loosen the conflicting constraint.

===== ruby-abi mismatch with required_ruby_version
ERROR:  While executing gem ... (ArgumentError)
    Cannot build gem for Ruby ABI 4.0 because required_ruby_version is set to ~> 3.4.0. Please set required_ruby_version to "~> 4.0.0".

===== no platform set (default ruby platform)
ERROR:  While executing gem ... (ArgumentError)
    Cannot build a gem scoped to a single Ruby ABI as no platform or a Ruby platform has been set
      raise ArgumentError, "Cannot build a gem scoped to a single Ruby ABI as no platform or a Ruby platform has been set"

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Pessimistic constraints are mishandled around prerelease upper bounds, potentially broadening or making requirements unsatisfiable.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds a RubyGems version floor to Ruby ABI-scoped content-addressable gems.

Changes:

  • Normalizes and propagates required_rubygems_version.
  • Rejects incompatible constraints and warns about rewrites.
  • Adds package and command-level tests.
File summaries
File Description
lib/rubygems/package.rb Implements requirement normalization and validation.
test/rubygems/test_gem_package.rb Tests metadata derivation and constraints.
test/rubygems/test_gem_commands_build_command.rb Tests command-level conflict rejection.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 2
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread lib/rubygems/package.rb Outdated
Comment thread lib/rubygems/package.rb Outdated
@jenshenny
jenshenny force-pushed the ca-inject-rubygems-version-constraint branch from ea51bda to c26c555 Compare September 2, 2026 02:21
@jenshenny
jenshenny requested a balanced review from Copilot September 2, 2026 02:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Valid prerelease constraints are incorrectly rejected as conflicting with the declared minimum.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread lib/rubygems/package.rb Outdated
Comment thread test/rubygems/test_gem_package.rb Outdated
@jenshenny
jenshenny force-pushed the ca-inject-rubygems-version-constraint branch 2 times, most recently from c5cff18 to 35c6975 Compare September 2, 2026 03:41
@jenshenny
jenshenny requested a balanced review from Copilot September 2, 2026 03:42
@jenshenny
jenshenny force-pushed the ca-inject-rubygems-version-constraint branch from 35c6975 to 5aba3e6 Compare September 2, 2026 03:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Compound constraints capped at the version floor can produce an uninstallable gem instead of failing the build.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread lib/rubygems/package.rb Outdated
@jenshenny
jenshenny force-pushed the ca-inject-rubygems-version-constraint branch 2 times, most recently from c67ec4f to 9d0b03f Compare September 2, 2026 04:04
@jenshenny jenshenny changed the title Inject required_rubygems_version >= 4.1.0.beta1 into CA gems at build Inject required_rubygems_version >= 4.1.0.a into CA gems at build Sep 2, 2026
@jenshenny
jenshenny force-pushed the ca-inject-rubygems-version-constraint branch 2 times, most recently from b0c2841 to 11503fc Compare September 2, 2026 04:13
Skinny gems built with --ruby-abi did not carry a required_rubygems_version
constraint, so older RubyGems clients (4.0.x) could install them through
the local path (gem install ./file.gem, vendor/cache, bundle install --local)
with no warning. The content address was silently discarded and a gem scoped
to one Ruby ABI would activate on an incompatible Ruby sharing that GEM_HOME.

The remote path was safe only by accident: the version token parsed to
platform=unknown which failed Gem::Platform.match_spec?. Now the protection
is the one the RFC describes -- older clients reject the gem because their
RubyGems version doesn't satisfy >= 4.1.0.a.

Published artifacts are immutable, so any skinny gem released without this
constraint stays visible to old clients permanently.

Gem::Package.build now derives the required_rubygems_version for the built
gem from the gemspec's own requirement:

- unset requirements become >= 4.1.0.a
- requirements that already satisfy that floor are left untouched
- weaker requirements are rewritten to the floor plus any declared upper
  bounds and exclusions, with a warning since the built gem's metadata
  will differ from the gemspec
- requirements that cap below the floor (e.g. < 4.0, ~> 3.5) raise at
  build time, since combined with the floor no RubyGems version could
  ever install the resulting gem

As with required_ruby_version, the derived value is propagated back to the
original spec only after a successful build.

Assisted-By: devx/01a05e2e-d421-7e27-b54e-abee85203da5
@jenshenny
jenshenny force-pushed the ca-inject-rubygems-version-constraint branch from 11503fc to a1abcc9 Compare September 2, 2026 04:20
@jenshenny
jenshenny requested a balanced review from Copilot September 2, 2026 04:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

The implementation matches the described behavior and includes comprehensive coverage of success and failure paths.

Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@jenshenny
jenshenny marked this pull request as ready for review September 2, 2026 04:24
@jenshenny
jenshenny merged commit 5f8c2b5 into feature-branch-ca-changes-rubygems Sep 2, 2026
104 checks passed
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.

2 participants