Add content addressable gems support - #9773
Draft
jenshenny wants to merge 10 commits into
Draft
Conversation
jenshenny
force-pushed
the
feature-branch-ca-changes-rubygems
branch
2 times, most recently
from
August 10, 2026 18:27
4a5def3 to
d849a56
Compare
Allow `gem build --ruby-abi X.Y` to build a gem that only supports a single Ruby ABI (a skinny gem) with a content addressable file name of the form <name>-<version>-<sha8>.gem, where the suffix is derived from the SHA-256 digest of the gem contents. The gem is built in memory and validated against the requested Ruby ABI. If required_ruby_version is unset it is derived from the ABI; the passed-in spec is only updated once the build succeeds. Co-authored-by: Jenny Shen <jenny.shen@shopify.com>
Co-authored-by: Jenny Shen <jenny.shen@shopify.com>
- Parse compact-index suffix as content address when hex + platform:= requirement present; carry content_address through resolver. - Prefer content-addressed gems in resolver when platform specificity ties. - Download and install SHA-named gem archives; fetch SHA-named gemspecs for development dependencies. - Preserve distinct resolver candidates by content_address in ==/hash. - Update BasicSpecification.content_address? calls to Gem::ContentAddress.match? (PR #172 refactor). Assisted-By: devx/fff388fa-6f3f-4c7a-8385-6e602f16830e
Assisted-By: devx/5f8c508e-3e50-4812-b2c3-84379e7c3fce
Assisted-By: devx/ce8ef461-c04c-4d00-8751-1b2488fe8a4b
Assisted-By: devx/ce8ef461-c04c-4d00-8751-1b2488fe8a4b
Assisted-By: devx/ce8ef461-c04c-4d00-8751-1b2488fe8a4b
Co-authored-by: Harriet Oughton <harriet.oughton@shopify.com>
Assisted-By: devx/be89c912-a11a-418c-92be-1893963a909c
OughtPuts
force-pushed
the
feature-branch-ca-changes-rubygems
branch
from
August 19, 2026 15:56
aad98a3 to
0caed62
Compare
Assisted-By: devx/3250d709-a0a0-4417-8f2f-83669ac9e685
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#9654
TL;DR
Adds RubyGems and Bundler client support for content-addressable ("skinny") binary gems: one artifact per Ruby ABI, named with a SHA-256 prefix.
The branch covers build, discovery, install, display, yank, lockfiles, caching, and
bundle install --local. Existing source and platform gems are unchanged.Why
"Fat" binary gems contain every supported Ruby ABI and keep growing. Skinny binaries are smaller, but builds for the same gem, version, and platform need distinct filenames. A content-derived suffix gives each artifact a unique identity.
A content address must be 8–64 lowercase hexadecimal characters. RubyGems only treats it as one when the gem also has a non-Ruby platform and constrained
required_ruby_version, avoiding false matches with ordinary filenames.What changes
gem build--ruby-abi X.Yvalidates the ABI, platform, andrequired_ruby_version; defaults the requirement to~> X.Y.0; builds in memory; writesname-version-<sha>.gem. Without the option, behaviour is unchanged.gem push--platformand--ruby-abiselectors. Given multiple SHA-named files, RubyGems reads their specifications and pushes the single matching artifact. No match or multiple matches raise instead of guessing; passing one exact filename remains unchanged.gem installgem installplatform:=metadata separately. Distinct hashes remain distinct candidates. A compatible skinny gem is preferred; resolution falls back to a traditional platform gem, then a source gem. Downloads the SHA-named archive and development gemspec.gem list -r,gem search -r, andgem info -rshow the real platform and Ruby ABI, not the hash. Versions/platforms are separated; ABIs for the same version/platform are grouped.gem yank--ruby-abi; sends gem name, version, platform, and ABI so the server can select one skinny variant. Existing yank behaviour remains unchanged without it.bundle installGemfile.lock, parses both on the next run, and installs the SHA-named artifact fromvendor/cachewithbundle install --local. Remote and local paths produce the same installed directory; checksums remain keyed by the platform lock name.Formats
Build:
gem build nokogiri.gemspec --ruby-abi 3.4 # => nokogiri-1.18.9-78be552b.gemCompact index:
Remote query output:
Lockfile:
Cache and install paths:
Targeted yank:
Each part was reviewed independently before being assembled for the feature branch.
Tophatting
gem push name-*.gem --platform <platform> --ruby-abi <ABI>; confirm it selects the matching file. Confirm ambiguous and non-matching selectors fail rather than guessing.gem installandbundle installselect the compatible skinny gem and fall back on an incompatible Ruby.vendor/cache, remove the installed copy, and confirmbundle install --localrecreates the same directory without contacting the server.--platformand--ruby-abi.