Skip to content

[Content Addressable] Support content addressable gem builds / gem naming in PackageTask - #9897

Draft
OughtPuts wants to merge 2 commits into
ruby:masterfrom
Shopify:ho/add-ruby-abi-to-package-task
Draft

OughtPuts wants to merge 2 commits into
ruby:masterfrom
Shopify:ho/add-ruby-abi-to-package-task

Conversation

@OughtPuts

@OughtPuts OughtPuts commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

#9900

NB Blocked behind: #9906 which changes the arguments for Gem::Package.build.

TLDR

Adds support to Gem::PackageTask for building single-ABI, content-addressable gems.

Description

This PR:

  1. Adds an optional ruby_abi attribute to Gem::PackageTask.

  2. Passes ruby_abi to Gem::Package.build, allowing it to produce a content-addressable gem for that
    Ruby ABI.

  3. Uses a predictable .gem-built stamp file as the Rake build target when ruby_abi is present. This
    is necessary because the content-addressable gem filename contains a hash that is not known until the
    gem has been built.

  4. Writes the path of the generated content-addressable gem into the stamp file. When ruby_abi is not
    provided, Gem::PackageTask retains its existing behaviour and uses the traditional gem path as its
    build target.

Testing

Tests in test_gem_package_task.rb verify that:

  • ruby_abi is passed to Gem::Package.build;
  • the content-addressable filename returned by Gem::Package.build is moved into the package directory;
  • the stamp file is created and contains the path of the generated gem; and
  • the existing packaging behaviour remains unchanged when no Ruby ABI is provided.

Top Hat

This has been top-hatted as part of the complete flow. See the cibuildgem CA support PR for more information.

@OughtPuts
OughtPuts force-pushed the ho/add-ruby-abi-to-package-task branch from 2dfe44b to 6b81423 Compare September 18, 2026 12:14
Comment thread lib/rubygems/package_task.rb Outdated
Comment thread lib/rubygems/package_task.rb

@girachawda girachawda left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM! I can't actually give you the ✅ but tophat passed and the code makes sense. Edouard's comments above make sense ^

@OughtPuts
OughtPuts marked this pull request as draft September 21, 2026 11:02
@OughtPuts

Copy link
Copy Markdown
Contributor Author

Putting this in draft temporarily until we are aligned on any changes needed to the --ruby_abi build flag.

@OughtPuts

Copy link
Copy Markdown
Contributor Author

--content-addressable changes added here and upstream but still in draft awaiting the upstream parts to merge.

@jenshenny

Copy link
Copy Markdown
Contributor

This PR is looking good to me 👍

@jenshenny

jenshenny commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Updated PR description:

TLDR

Adds Gem::PackageTask#content_addressable. When true, the gem task builds a content addressable gem for the single Ruby ABI identified by gem_spec.required_ruby_version.

Includes commits from #9906, please look at the last commit.

Description

Gem::PackageTask uses the gem's file path as its Rake target: file "pkg/foo-1.0.0-x86_64-linux.gem" => files. A content addressable gem's file name contains the hash of its contents, so it isn't known until the gem has been built and can't be a Rake target. This PR:

  1. Adds content_addressable (default false) and passes it through to Gem::Package.build. The Ruby ABI comes from gem_spec.required_ruby_version via Gem::ContentAddress.ruby_abi_for, so the spec must already be in the ~> X.Y.0 form that content addressable gems require; nothing is inferred from a separate ruby_abi setting.

  2. Uses a stamp file as the Rake target in content addressable mode: pkg/<full_name>-<ruby abi>.gem-built, containing the path of the built gem. On the next run the stamp is removed if the gem it points to no longer exists, so the gem is rebuilt; otherwise Rake's normal staleness check applies.

  3. Suffixes the staging directory with the Ruby ABI (package_dir_path → pkg/<full_name>-<ruby abi>). A build that produces a multi ABI gem and several single ABI gems for the same full_name (rake-compiler#257) would otherwise share pkg/<full_name>/ between all of them. This lets every gem land directly in pkg/.

When content_addressable is false nothing changes: the target is the gem path, the staging directory is pkg/<full_name>, and Gem::Package.build is called with content_addressable = false.

Testing

A one-file gem packaged with Gem::PackageTask directly:

# Rakefile
require "rubygems/package_task"

spec = Gem::Specification.new do |s|
  s.name = "hello"
  s.version = "1.0.0"
  s.summary = "hello"
  s.authors = ["x"]
  s.files = ["lib/hello.rb"]
  s.platform = "arm64-darwin"
  s.required_ruby_version = "~> 4.0.0"
end

Gem::PackageTask.new(spec) do |pkg|
  pkg.content_addressable = true
end
$ rake gem
  Successfully built RubyGem
  File: hello-1.0.0-fa8b73c3.gem
  Platform: arm64-darwin
  Ruby ABI: 4.0

$ ls -p pkg
hello-1.0.0-arm64-darwin-4.0/           # staging dir, suffixed with the ABI
hello-1.0.0-arm64-darwin-4.0.gem-built  # stamp, the Rake target
hello-1.0.0-fa8b73c3.gem                # the gem

$ cat pkg/hello-1.0.0-arm64-darwin-4.0.gem-built
pkg/hello-1.0.0-fa8b73c3.gem

@jenshenny
jenshenny force-pushed the ho/add-ruby-abi-to-package-task branch 10 times, most recently from 8c0d3cc to 1899306 Compare September 29, 2026 20:26

@kou kou 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.

+1

@jenshenny
jenshenny force-pushed the ho/add-ruby-abi-to-package-task branch from 1899306 to 32715dd Compare September 30, 2026 02:26
Adds Gem::PackageTask#content_addressable. When true, the gem task builds
a content addressable gem for the single Ruby ABI identified by
gem_spec.required_ruby_version, passing content_addressable through to
Gem::Package.build.

A content addressable gem's file name contains a hash of its contents, so
it isn't known until the gem is built and can't be a Rake target. In this
mode the task uses a stamp file (pkg/<full_name>-<ruby abi>.gem-built) as
its Rake target, writes the built gem's path into it, and rebuilds when
the referenced gem no longer exists. The staging directory is suffixed
with the Ruby ABI (pkg/<full_name>-<ruby abi>) so per-ABI builds of the
same full_name don't share a directory.

When content_addressable is false, behaviour is unchanged.
@jenshenny
jenshenny force-pushed the ho/add-ruby-abi-to-package-task branch from 32715dd to c138e1f Compare September 30, 2026 02:45

This branch has not been deployed

No deployments
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.

5 participants