class TrustedPublisher

Includes
::Gem::UserInteraction; ::Gem::GemcutterUtilities

Registers the reviewed release workflow with RubyGems.org using its owner API.

Definitions

SCOPE = :configure_trusted_publishers

The RubyGems API scope for managing trusted publishers.

TYPE = "OIDC::TrustedPublisher::GitHubAction"

The provider type accepted by the RubyGems trusted publisher API.

def self.load(root, **options)

Load the gem identity and reviewed publisher settings from the current project.

Signature

parameter root String

The repository root, which must also be the working directory.

parameter options Hash

Authentication options passed to Bake::Gem::GitHub::TrustedPublisher#initialize.

returns TrustedPublisher

The configured RubyGems client.

Implementation

def self.load(root, **options)
	project = Project.new(root)
	name = Helper.new(root).gemspec.name
	
	new(name, project.trusted_publisher, **options)
end

def initialize(name, settings, key: nil, otp: nil)

Configure an existing gem's expected GitHub Actions publisher.

Signature

parameter name String

The gem name.

parameter settings Hash

Repository owner/name, workflow filename, and environment.

parameter key Symbol | Nil

An explicitly selected key in RubyGems credentials.

parameter otp String | Nil

An optional MFA code; RubyGems can prompt when required.

Implementation

def initialize(name, settings, key: nil, otp: nil)
	@path = "api/v1/gems/#{URI.encode_www_form_component(name)}/trusted_publishers"
	@settings = settings.transform_keys(&:to_s)
	@options = {key: key, otp: otp}
	@host = "https://rubygems.org"
	@api_key = nil
end

attr_reader :options

Signature

attribute Hash

Options used by RubyGems authentication and MFA support.

def status

Read the matching publisher without changing publisher configuration.

Signature

returns Hash

Whether the publisher is configured and its existing API record, if any.

raises RuntimeError

If RubyGems cannot list the gem's publishers.

Implementation

def status
	sign_in(scope: SCOPE) unless api_key
	publishers = request(:get, expected: "200")
	raise "Invalid RubyGems trusted publishers response." unless publishers.is_a?(Array)
	publisher = publishers.find{|record| matching?(record)}
	
	return {configured: !publisher.nil?, publisher: publisher}
end

def register

Register a missing publisher, preserving all existing publisher registrations.

Signature

returns Hash

Whether registration was created and the matching API record.

raises RuntimeError

If RubyGems rejects registration or returns different settings.

Implementation

def register
	current = status
	return {created: false, publisher: current.fetch(:publisher)} if current.fetch(:configured)
	
	publisher = request(:post, expected: "201", payload: {trusted_publisher_type: TYPE, trusted_publisher: @settings})
	raise "RubyGems returned unexpected trusted publisher settings." unless matching?(publisher)
	
	return {created: true, publisher: publisher}
end

def api_key

Use the session key or an explicitly supplied credential, leaving the default push key alone.

Signature

returns String | Nil

The API key used for this session.

Implementation

def api_key
	@api_key || ENV["GEM_HOST_API_KEY"] || (options[:key] && verify_api_key(options[:key]))
end

def set_api_key(host, key)

Keep newly issued credentials in memory rather than changing the user's credentials file.

Signature

parameter host String

The authenticated RubyGems host.

parameter key String

The newly issued API key.

Implementation

def set_api_key(host, key)
	@api_key = key
end