Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds automatic Sigstore attestation support to gem push (targeting rubygems.org), generating an attestation bundle via sigstore-cli when no --attestation is provided and falling back to a non-attested push if attestation fails.
Changes:
- Updated
Gem::Commands::PushCommandto push with multipart attestations by default (rubygems.org-only), and retry without attestations on errors. - Added
attest!implementation usinggem exec sigstore-cli:0.2.2 sign ... --bundle .... - Refactored push command tests to validate multipart attestation requests via a shared helper and added tests for auto-attestation and fallback behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| lib/rubygems/commands/push_command.rb | Implements auto-attestation flow, multipart request building, and fallback-to-non-attested push logic. |
| test/rubygems/test_gem_commands_push_command.rb | Adds/updates tests for multipart attestation requests, auto-attestation behavior, and fallback behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -92,23 +92,64 @@ def send_gem(name) | |||
| private | |||
|
|
|||
| def send_push_request(name, args) | |||
There was a problem hiding this comment.
The early return for RUBY_ENGINE == "jruby" || !attestation_supported_host? skips all attestation, including when the user explicitly passes --attestation. That changes existing behavior and also contradicts the PR description (“When --attestation option provided, gem push only uses that.”). Consider only disabling auto attestation here (i.e., still call send_push_request_with_attestation when options[:attestations].any?), and gate the attest! path separately for JRuby/unsupported hosts.
| def send_push_request(name, args) | |
| def send_push_request(name, args) | |
| if options[:attestations].any? | |
| begin | |
| return send_push_request_with_attestation(name, args) | |
| rescue StandardError => e | |
| alert_warning "Failed to push with attestation, retrying without attestation.\n#{e.full_message}" | |
| return send_push_request_without_attestation(name, args) | |
| end | |
| end |
| begin | ||
| send_push_request_with_attestation(name, args) | ||
| rescue StandardError => e | ||
| alert_warning "Failed to push with attestation, retrying without attestation.\n#{e.full_message}" |
There was a problem hiding this comment.
alert_warning includes e.full_message, which typically contains a full backtrace and can be extremely verbose/noisy (and may leak local paths). Consider logging only e.message by default and printing the full backtrace only under Gem.configuration.really_verbose (or similar), while still retrying without attestation.
| alert_warning "Failed to push with attestation, retrying without attestation.\n#{e.full_message}" | |
| message = "Failed to push with attestation, retrying without attestation." | |
| if Gem.configuration.really_verbose | |
| message = "#{message}\n#{e.full_message}" | |
| else | |
| message = "#{message}\n#{e.message}" | |
| end | |
| alert_warning message |
| def attestation_supported_host? | ||
| (@host || Gem.host) == "https://rubygems.org" | ||
| end |
There was a problem hiding this comment.
attestation_supported_host? uses exact string equality against "https://rubygems.org". If the host is configured as https://rubygems.org/ (trailing slash) or otherwise equivalent, auto-attestation will be incorrectly disabled. Consider normalizing/parsing the URI (scheme + host) or comparing against Gem::DEFAULT_HOST after normalization.
9f87b0f to
da9e8e4
Compare
|
I'm not sure making Attestations the default path going forward would be a net positive in its current form. I don't have the stats in front of me, but I believe the vast majority of gem pushes to rubygems.org are still from local dev machines, so the vast majority of |
Co-authored-by: hsbt <12301+hsbt@users.noreply.github.com>
Co-authored-by: hsbt <12301+hsbt@users.noreply.github.com>
Co-authored-by: hsbt <12301+hsbt@users.noreply.github.com>
da9e8e4 to
fcd4d81
Compare
@colby-swandale Oh, I didn't know that. This change eliminates the need for monkey patching. That's the fist my motivation. The long term goal, I would like to consider a system that would enable attestation even when pushing from local, but I don't have any ideas yet. |
|
This change would be great ! I have this use case on cibuildgem . I can't use the standard With this change, the gem pushed will be fully attested 🥳 |
What was the end-user or developer problem that led to this PR?
We should expand to use attestation of rubygems. The current toolchain only enabled attestation by https://github.com/rubygems/release-gem or
--attestationoption with local sigstore json file.What is your fix for the problem, implemented in this PR?
Integrate rubygems-attestation-patch.rb to
gem pushcommand. After that,gem pushcommand perfome:--attestationoption provided,gem pushonly uses that.gem pushperform without atttestationTODO: After merging this, we should avoid to load
rubygems-attestation-patch.rbatrubygems/release-gemwith RubyGems>= 4.1.Make sure the following tasks are checked