bake-gem-github 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f7557669b8ec839c193fbf060816c360413ba4be3cd8e223f294acb8e29baed
4
- data.tar.gz: c4806b56446c74082b785e6f19ac8a36cfbe1cd79a07ba05eda3bcd223ceaeb8
3
+ metadata.gz: 6806efc908e7db5189295eb013a2d29bc3f82a20b9749eafc9464baa898a251a
4
+ data.tar.gz: 19143737be1d10805c3204064234880fe49b2b33ba107cb55676c522a83fd5e1
5
5
  SHA512:
6
- metadata.gz: 522b233facca2afd17c28320ee34de988053bc33832a595c4e54ad34a308997813d54afaf43aa8a6c6b785b0a882b0f953aa5fecd7c4d004c0d4a21180d8f9b7
7
- data.tar.gz: 7d4dbe694f2209d5a369c2e8100101a824b1cc0839023dd4a58976b9022154428c6e7e87ab8185b70f17e7913746f07bf4abdeabd4145c510ade5c3b8ba44ee3
6
+ metadata.gz: 7ec509f5bc2921c554352950a9c469dcbe8dccc8f64bfd0e71fcfdb237855c68c1d0a232fcbea6e816204cb37868d952a11b8b0bf97d1ca3e6c0b9e7cfb22f8d
7
+ data.tar.gz: 8bfb262d1cfcb69db13aa8075fb354d1dbf70826c03a04747bd7cba1e80b4c04a18d16ff147c150727c78a2c88deb4ff8a8a63498a024bfcff31d62adddbb572
@@ -4,9 +4,29 @@
4
4
  # Copyright, 2026, by Samuel Williams.
5
5
 
6
6
  # Inspect external settings before applying the generated policy.
7
+ # @parameter publisher [Boolean] Authenticate to RubyGems and check the expected publisher registration.
8
+ # @parameter key [Symbol] An explicitly selected RubyGems API key name.
9
+ # @parameter otp [String] An optional RubyGems MFA code.
7
10
  # @returns [Hash] Desired and observed settings for review.
8
- def plan
9
- context.lookup("gem:github:doctor").call
11
+ def plan(publisher: false, key: nil, otp: nil)
12
+ result = context.lookup("gem:github:doctor").call
13
+ if publisher
14
+ require "bake/gem/github/trusted_publisher"
15
+
16
+ result[:trusted_publisher_status] = Bake::Gem::GitHub::TrustedPublisher.load(context.root, key: key, otp: otp).status
17
+ end
18
+
19
+ return result
20
+ end
21
+
22
+ # Register the configured release workflow as a trusted publisher for an existing gem on RubyGems.org.
23
+ # @parameter key [Symbol] An explicitly selected RubyGems API key name.
24
+ # @parameter otp [String] An optional RubyGems MFA code.
25
+ # @returns [Hash] Whether the publisher was created and its API record.
26
+ def publisher(key: nil, otp: nil)
27
+ require "bake/gem/github/trusted_publisher"
28
+
29
+ Bake::Gem::GitHub::TrustedPublisher.load(context.root, key: key, otp: otp).register
10
30
  end
11
31
 
12
32
  # Apply the four managed rulesets and configured environment reviewers using the current gh administrator credentials.
data/bake/gem/github.rb CHANGED
@@ -9,10 +9,9 @@
9
9
  # @parameter branch [String] Default branch name; discovered through GitHub when omitted.
10
10
  # @parameter approvals [Integer] Number of approving reviews.
11
11
  # @parameter reviewers [Array(String)] Publishing environment reviewers: user logins or organization/team names. Omit to leave environment settings unmanaged.
12
- # @parameter signing [Boolean] Require certificate signing; when omitted, enable it if `release.cert` exists.
13
12
  # @parameter ruby [String] Ruby version for release workflows.
14
13
  # @returns [Array(String)] Generated paths relative to the repository root.
15
- def setup(checks:, repository: nil, branch: nil, approvals: 2, reviewers: nil, signing: nil, ruby: "3.4")
14
+ def setup(checks:, repository: nil, branch: nil, approvals: 2, reviewers: nil, ruby: "3.4")
16
15
  require "bake/gem/github/setup"
17
16
  require "bake/gem/shell"
18
17
 
@@ -31,7 +30,6 @@ def setup(checks:, repository: nil, branch: nil, approvals: 2, reviewers: nil, s
31
30
  reviewers: reviewers,
32
31
  ruby: ruby,
33
32
  }
34
- options[:signing] = signing unless signing.nil?
35
33
 
36
34
  Bake::Gem::GitHub::Setup.new(context.root).generate(**options)
37
35
  end
@@ -48,13 +48,29 @@ The rules require two approvals by default, allow explicit administrator bypass,
48
48
 
49
49
  ## Configure publishing credentials
50
50
 
51
- Create a `rubygems` GitHub environment restricted to the default branch. On RubyGems, an owner must configure a Trusted Publisher with the values printed by `gem:github:setup:plan`: the owner/repository, workflow filename **`release-publish.yaml`**, and environment **`rubygems`**. See [RubyGems Trusted Publishing](https://guides.rubygems.org/trusted-publishing/) for the account setup.
51
+ Create a `rubygems` GitHub environment restricted to the default branch. For an existing gem on RubyGems.org, run this task from the repository root as a gem owner:
52
52
 
53
- Ownership, MFA, and signing bootstrap are manual setup steps. The plan reports expected RubyGems values; it does not verify ownership or publisher trust. Trusted Publishing supplies the publishing credential for each run, so a long-lived RubyGems API key is unnecessary.
53
+ ``` bash
54
+ bundle exec bake gem:github:setup:publisher
55
+ ```
56
+
57
+ The task reads the gem name from its gemspec and the owner/repository and environment from `config/release.yaml`. It registers the **`release-publish.yaml`** workflow with the configured environment (**`rubygems`** by default). An exact existing match is reused, so reruns do not create duplicate registrations. Other publishers are preserved; the task does not remove or replace them.
54
58
 
55
- When `release.cert` exists, setup enables certificate signing. Commit the public certificate and install its matching private key as `GEM_SIGNING_KEY`, either in the `rubygems` environment or as an organization secret available to the repository. The publisher checks certificate validity, key matching, and package signatures. Use `signing=false` during setup to disable certificate signing.
59
+ Without an explicitly supplied API key, the task prompts for RubyGems credentials and any required MFA verification. It requests a key with only the `configure_trusted_publishers` scope, expiring after 15 minutes, and keeps it in memory. It does not read or overwrite your default saved push key. To use an existing key with this scope, supply `GEM_HOST_API_KEY` or select a named RubyGems credential with `key=publisher`. Registration and the optional plan check also accept `otp=123456` or `GEM_HOST_OTP_CODE` when needed.
56
60
 
57
- Ensure another maintainer can administer the repository and recover its RubyGems account and signing key.
61
+ To check registration without creating a publisher:
62
+
63
+ ``` bash
64
+ bundle exec bake gem:github:setup:plan publisher=true
65
+ ```
66
+
67
+ This adds `trusted_publisher_status` to the plan, including `configured` and the matching registration. The default plan only reports expected RubyGems values and does not authenticate to RubyGems. Authentication, ownership, and API failures stop the task rather than being reported as a missing registration.
68
+
69
+ For a gem that has never been published, configure a pending publisher manually. Account ownership, MFA enrollment, and the GitHub environment remain manual setup steps. See [RubyGems Trusted Publishing](https://guides.rubygems.org/trusted-publishing/) for account setup. Trusted Publishing supplies the publishing credential for each release, so a long-lived RubyGems API key is unnecessary.
70
+
71
+ Publishing builds gems without RubyGems certificate signatures. Sigstore and GitHub provenance attestations bind the package to its source and release workflow; no separate certificate or private signing key is required.
72
+
73
+ Ensure another maintainer can administer the repository and recover its RubyGems account.
58
74
 
59
75
  ## Authorize publishing
60
76
 
@@ -117,6 +133,8 @@ git diff
117
133
 
118
134
  This updates managed files in the working tree and returns their changed paths. Review the diff and selectively retain repository customizations before committing. The task does not stage, commit, or change remote settings. Repeated updates produce no further changes unless customizations differ from the templates. Apply changed rulesets after the corresponding workflows are running.
119
135
 
136
+ Updating removes the obsolete `signing` configuration and `GEM_SIGNING_KEY` workflow reference. The publisher ignores legacy certificate-signing settings and always builds unsigned packages. Remove `cert_chain`, `signing_key`, and unused public certificates from your gem project when migrating. Attestation verification and RubyGems Trusted Publishing remain required.
137
+
120
138
  To enable rebase merging on an existing installation, regenerate and merge `release-validate.yaml` so it runs `gem:github:release:validate`, which requires single-commit release PRs. Then review `gem:github:setup:plan` and run `gem:github:setup:apply` to allow rebase merging in the managed rules. Enable rebase merging in repository settings as well. Upgrading the gem alone does not update workflows or live rules.
121
139
 
122
140
  Regenerate existing workflows to adopt publishing on `push` instead of `pull_request_target`. The workflow filename and `rubygems` environment remain the same, so the RubyGems Trusted Publisher configuration does not change. No exception to GitHub's `pull_request_target` execution policy is needed. The resolve task continues to accept PR numbers from older workflows while you migrate.
@@ -36,7 +36,7 @@ Merging into the configured default branch triggers `release-publish.yaml` throu
36
36
 
37
37
  Each release must land as the tip of its own push, as it does when merging a PR through GitHub. Later pushes do not change a pending release's source: inspection and publishing remain pinned to the original commit, and reruns use the same event. Do not combine a release and later changes into one direct push. If you automate merging, use a GitHub App or personal access token; pushes made using a workflow's `GITHUB_TOKEN` do not trigger another workflow.
38
38
 
39
- Only validated releases enter the publishing queue and request approval from the `rubygems` environment when required. Ordinary pushes cannot replace them in that queue. The publishing job retains the existing signing, attestation, and artifact recovery checks.
39
+ Only validated releases enter the publishing queue and request approval from the `rubygems` environment when required. Ordinary pushes cannot replace them in that queue. The publishing job retains attestation and artifact recovery checks.
40
40
 
41
41
  ## Resume interrupted preparation
42
42
 
@@ -6,7 +6,7 @@ Use this when checking a completed release or confirming which source commit pro
6
6
 
7
7
  ## What publishing verifies
8
8
 
9
- After squash, rebase, or merge, the publishing workflow verifies GitHub's merged PR record and ancestry, then checks out the exact resulting commit. Each release PR contains one commit, so the resulting commit's **first parent** is the default branch immediately before the release landed. Later development on the default branch is allowed. Publishing regenerates against that first parent, builds in a clean worktree, optionally certificate-signs, and creates two attestations over the final bytes:
9
+ After squash, rebase, or merge, the publishing workflow verifies GitHub's merged PR record and ancestry, then checks out the exact resulting commit. Each release PR contains one commit, so the resulting commit's **first parent** is the default branch immediately before the release landed. Later development on the default branch is allowed. Publishing regenerates against that first parent, builds an unsigned gem in a clean worktree, and creates two attestations over the final bytes:
10
10
 
11
11
  - A Sigstore bundle submitted explicitly with `gem push --attestation` using RubyGems 4.0.21.
12
12
  - GitHub's native SLSA provenance covering both the gem and `release.json`. This signed receipt binds the gem digest to the exact release commit, even when the workflow's own default-branch revision is newer.
@@ -181,12 +181,18 @@ module Bake
181
181
  existing_rules: api("rulesets?per_page=100"),
182
182
  environments: api("environments"),
183
183
  environment_changes: environment_changes,
184
- trusted_publisher: {
185
- repository_owner: @repository.split("/").first,
186
- repository_name: @repository.split("/").last,
187
- workflow_filename: "release-publish.yaml",
188
- environment: @config.fetch("environment"),
189
- }
184
+ trusted_publisher: trusted_publisher,
185
+ }
186
+ end
187
+
188
+ # Describe the RubyGems publisher for the reviewed release workflow.
189
+ # @returns [Hash] Repository, workflow filename, and environment settings.
190
+ def trusted_publisher
191
+ {
192
+ repository_owner: @repository.split("/").first,
193
+ repository_name: @repository.split("/").last,
194
+ workflow_filename: "release-publish.yaml",
195
+ environment: @config.fetch("environment"),
190
196
  }
191
197
  end
192
198
 
@@ -8,7 +8,6 @@ require_relative "backup"
8
8
  require_relative "registry"
9
9
  require "bake/releases"
10
10
  require "digest"
11
- require "openssl"
12
11
 
13
12
  module Bake
14
13
  module Gem
@@ -28,7 +27,7 @@ module Bake
28
27
 
29
28
  # Build or restore this workflow run's artifact, after validating the actual merged commit.
30
29
  # @parameter number [String | Integer] The merged release PR number.
31
- # @returns [Hash] The release receipt. Extends {Project#inspect_release} metadata with `file`, `sha256`, `run_id`, and `signing`; writes the receipt to `pkg/release.json` and Actions outputs when configured.
30
+ # @returns [Hash] The release receipt. Extends {Project#inspect_release} metadata with `file`, `sha256`, and `run_id`; writes the receipt to `pkg/release.json` and Actions outputs when configured.
32
31
  # @raises [RuntimeError] If the workflow identity, source, or retained artifact is invalid, or published bytes cannot be recovered.
33
32
  def build(number)
34
33
  guard_environment
@@ -165,7 +164,6 @@ module Bake
165
164
  file: filename,
166
165
  sha256: Digest::SHA256.file(package).hexdigest,
167
166
  run_id: run,
168
- signing: @config.fetch("signing"),
169
167
  )
170
168
  File.write(File.join(path, "release.json"), JSON.pretty_generate(receipt) + "\n")
171
169
 
@@ -198,10 +196,8 @@ module Bake
198
196
  end
199
197
  end
200
198
 
201
- # Verify the optional certificate signature and both attestation formats.
199
+ # Verify both attestation formats.
202
200
  def verify_artifact(package, bundle)
203
- verify_certificate(package) if @config.fetch("signing")
204
-
205
201
  identity = "https://github.com/#{@repository}/.github/workflows/release-publish.yaml@refs/heads/#{@config.fetch('branch')}"
206
202
  gem_command(
207
203
  "exec", "sigstore-cli:0.2.3", "verify", package, "--bundle", bundle,
@@ -347,34 +343,8 @@ module Bake
347
343
  raise "Publishing requires the default branch workflow." unless ENV["GITHUB_REF"] == "refs/heads/#{@config.fetch('branch')}"
348
344
  end
349
345
 
350
- def verify_certificate(path)
351
- policy = ::Gem::Security::Policy.new("Release", only_trusted: false)
352
- package = ::Gem::Package.new(path, policy)
353
- package.verify
354
-
355
- signer = OpenSSL::X509::Certificate.new(package.spec.cert_chain.last)
356
- expected = OpenSSL::X509::Certificate.new(File.read(File.join(@root, "release.cert")))
357
- raise "Package signer differs from release.cert." unless signer.to_der == expected.to_der
358
- end
359
-
360
346
  def build_package(path)
361
- unless @config.fetch("signing")
362
- return @release.worktree("HEAD"){|source| @release.bake(source, "gem:build", root: path, signing_key: false)}
363
- end
364
-
365
- certificate = OpenSSL::X509::Certificate.new(File.read(File.join(@root, "release.cert")))
366
- key = OpenSSL::PKey.read(ENV.fetch("GEM_SIGNING_KEY"))
367
- raise "Signing key does not match release.cert." unless certificate.check_private_key(key)
368
- raise "Signing certificate is not currently valid." unless (certificate.not_before..certificate.not_after).cover?(Time.now)
369
-
370
- return Tempfile.create("gem-signing-key") do |file|
371
- file.chmod(0600)
372
- file.write(ENV.fetch("GEM_SIGNING_KEY"))
373
- file.flush
374
- package = @release.worktree("HEAD"){|source| @release.bake(source, "gem:build", root: path, signing_key: file.path)}
375
- verify_certificate(package)
376
- package
377
- end
347
+ return @release.worktree("HEAD"){|source| @release.bake(source, "gem:build", root: path, signing_key: false)}
378
348
  end
379
349
 
380
350
  def output(receipt, restored:)
@@ -24,11 +24,10 @@ module Bake
24
24
  # @parameter checks [Array(String)] Required CI job names; release validation is added automatically.
25
25
  # @parameter approvals [Integer] Required approvals, between one and six.
26
26
  # @parameter reviewers [Array(String) | Nil] Publishing environment reviewers, as user logins or organization/team names. Nil leaves environment settings unmanaged.
27
- # @parameter signing [Boolean] Whether publishing requires the certificate and matching private key.
28
27
  # @parameter ruby [String] The Ruby version used by release workflows.
29
28
  # @returns [Array(String)] Generated paths relative to the repository root.
30
29
  # @raises [RuntimeError] If configuration is invalid or an existing generated file differs.
31
- def generate(repository:, branch: "main", checks:, approvals: 2, reviewers: nil, signing: File.file?(File.join(@root, "release.cert")), ruby: "3.4")
30
+ def generate(repository:, branch: "main", checks:, approvals: 2, reviewers: nil, ruby: "3.4")
32
31
  raise "Expected owner/repository." unless repository.match?(/\A[\w.-]+\/[\w.-]+\z/)
33
32
  raise "Unsupported branch name." unless branch.match?(/\A[\w.\/-]+\z/)
34
33
  raise "Select the required CI check names." if checks.empty?
@@ -40,7 +39,6 @@ module Bake
40
39
  "branch" => branch,
41
40
  "checks" => (checks + ["Release validation"]).uniq,
42
41
  "approvals" => approvals,
43
- "signing" => signing,
44
42
  "ruby" => ruby,
45
43
  "environment" => "rubygems",
46
44
  }
@@ -145,10 +143,10 @@ module Bake
145
143
  end
146
144
 
147
145
  def render(config)
146
+ config.delete("signing")
148
147
  self.class.validate_reviewers(config["reviewers"]) if config.key?("reviewers")
149
148
  branch = config.fetch("branch")
150
149
  ruby = config.fetch("ruby")
151
- signing = config.fetch("signing")
152
150
 
153
151
  templates = File.expand_path("../../../../templates", __dir__)
154
152
  files = {"config/release.yaml" => YAML.dump(config)}
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ require "json"
7
+ require "rubygems/gemcutter_utilities"
8
+ require "rubygems/user_interaction"
9
+ require "uri"
10
+ require_relative "project"
11
+
12
+ module Bake
13
+ module Gem
14
+ module GitHub
15
+ # Registers the reviewed release workflow with RubyGems.org using its owner API.
16
+ class TrustedPublisher
17
+ include ::Gem::UserInteraction
18
+ include ::Gem::GemcutterUtilities
19
+
20
+ # The RubyGems API scope for managing trusted publishers.
21
+ SCOPE = :configure_trusted_publishers
22
+
23
+ # The provider type accepted by the RubyGems trusted publisher API.
24
+ TYPE = "OIDC::TrustedPublisher::GitHubAction"
25
+
26
+ # Load the gem identity and reviewed publisher settings from the current project.
27
+ # @parameter root [String] The repository root, which must also be the working directory.
28
+ # @parameter options [Hash] Authentication options passed to {initialize}.
29
+ # @returns [TrustedPublisher] The configured RubyGems client.
30
+ def self.load(root, **options)
31
+ project = Project.new(root)
32
+ name = Helper.new(root).gemspec.name
33
+
34
+ new(name, project.trusted_publisher, **options)
35
+ end
36
+
37
+ # Configure an existing gem's expected GitHub Actions publisher.
38
+ # @parameter name [String] The gem name.
39
+ # @parameter settings [Hash] Repository owner/name, workflow filename, and environment.
40
+ # @parameter key [Symbol | Nil] An explicitly selected key in RubyGems credentials.
41
+ # @parameter otp [String | Nil] An optional MFA code; RubyGems can prompt when required.
42
+ def initialize(name, settings, key: nil, otp: nil)
43
+ @path = "api/v1/gems/#{URI.encode_www_form_component(name)}/trusted_publishers"
44
+ @settings = settings.transform_keys(&:to_s)
45
+ @options = {key: key, otp: otp}
46
+ @host = "https://rubygems.org"
47
+ @api_key = nil
48
+ end
49
+
50
+ # @attribute [Hash] Options used by RubyGems authentication and MFA support.
51
+ attr_reader :options
52
+
53
+ # Read the matching publisher without changing publisher configuration.
54
+ # @returns [Hash] Whether the publisher is configured and its existing API record, if any.
55
+ # @raises [RuntimeError] If RubyGems cannot list the gem's publishers.
56
+ def status
57
+ sign_in(scope: SCOPE) unless api_key
58
+ publishers = request(:get, expected: "200")
59
+ raise "Invalid RubyGems trusted publishers response." unless publishers.is_a?(Array)
60
+ publisher = publishers.find{|record| matching?(record)}
61
+
62
+ return {configured: !publisher.nil?, publisher: publisher}
63
+ end
64
+
65
+ # Register a missing publisher, preserving all existing publisher registrations.
66
+ # @returns [Hash] Whether registration was created and the matching API record.
67
+ # @raises [RuntimeError] If RubyGems rejects registration or returns different settings.
68
+ def register
69
+ current = status
70
+ return {created: false, publisher: current.fetch(:publisher)} if current.fetch(:configured)
71
+
72
+ publisher = request(:post, expected: "201", payload: {trusted_publisher_type: TYPE, trusted_publisher: @settings})
73
+ raise "RubyGems returned unexpected trusted publisher settings." unless matching?(publisher)
74
+
75
+ return {created: true, publisher: publisher}
76
+ end
77
+
78
+ # Use the session key or an explicitly supplied credential, leaving the default push key alone.
79
+ # @returns [String | Nil] The API key used for this session.
80
+ def api_key
81
+ @api_key || ENV["GEM_HOST_API_KEY"] || (options[:key] && verify_api_key(options[:key]))
82
+ end
83
+
84
+ # Keep newly issued credentials in memory rather than changing the user's credentials file.
85
+ # @parameter host [String] The authenticated RubyGems host.
86
+ # @parameter key [String] The newly issued API key.
87
+ def set_api_key(host, key)
88
+ @api_key = key
89
+ end
90
+
91
+ private
92
+
93
+ def get_mfa_params(profile)
94
+ super.merge(expires_at: (Time.now.utc + 900).strftime("%Y-%m-%d %H:%M:%S UTC"))
95
+ end
96
+
97
+ def matching?(record)
98
+ return false unless record.fetch("trusted_publisher_type") == TYPE
99
+ settings = record.fetch("trusted_publisher")
100
+
101
+ # Generated publishing workflows run in the configured repository, not a reusable workflow repository:
102
+ @settings.all?{|key, value| settings[key] == value} &&
103
+ settings["workflow_repository_owner"].nil? && settings["workflow_repository_name"].nil?
104
+ end
105
+
106
+ def request(method, expected:, payload: nil)
107
+ response = rubygems_api_request(method, @path, scope: SCOPE) do |request|
108
+ request["Authorization"] = api_key
109
+ request["Accept"] = "application/json"
110
+ if payload
111
+ request["Content-Type"] = "application/json"
112
+ request.body = JSON.generate(payload)
113
+ end
114
+ end
115
+ unless response.code == expected
116
+ raise "RubyGems trusted publisher #{method.to_s.upcase} failed (HTTP #{response.code}): #{clean_text(response.body)}"
117
+ end
118
+
119
+ JSON.parse(response.body)
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -9,7 +9,7 @@ module Bake
9
9
  module Gem
10
10
  # GitHub pull request and release orchestration for bake-gem.
11
11
  module GitHub
12
- VERSION = "0.5.0"
12
+ VERSION = "0.7.0"
13
13
  end
14
14
  end
15
15
  end
data/readme.md CHANGED
@@ -24,6 +24,16 @@ Please see the [project documentation](https://socketry.github.io/bake-gem-githu
24
24
 
25
25
  Please see the [project releases](https://socketry.github.io/bake-gem-github/releases/index) for all releases.
26
26
 
27
+ ### v0.7.0
28
+
29
+ - Remove RubyGems certificate signing and its private-key requirement. Publishing always builds unsigned gems and verifies Sigstore and GitHub provenance attestations.
30
+ - Remove the setup `signing` option. Regenerate workflows with `gem:github:setup:update` to remove legacy configuration and signing-secret references.
31
+
32
+ ### v0.6.0
33
+
34
+ - Register RubyGems trusted publishers from the gemspec and release configuration with `gem:github:setup:publisher`, reusing existing registrations and RubyGems authentication/MFA support.
35
+ - Check publisher registration explicitly with `gem:github:setup:plan publisher=true`.
36
+
27
37
  ### v0.5.0
28
38
 
29
39
  - Support rebase merging by requiring each release PR to contain exactly one commit, while leaving ordinary PRs unrestricted. Generated rules allow merge, squash, and rebase methods according to repository settings.
@@ -62,10 +72,6 @@ Please see the [project releases](https://socketry.github.io/bake-gem-github/rel
62
72
  - Preserve verified release files in a draft GitHub release before uploading to RubyGems, so reruns can recover when Actions artifacts disappear.
63
73
  - Wait for RubyGems registry propagation before finalizing releases.
64
74
 
65
- ### v0.0.1
66
-
67
- - Initial implementation.
68
-
69
75
  ## Contributing
70
76
 
71
77
  We welcome contributions to this project.
data/releases.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Releases
2
2
 
3
+ ## v0.7.0
4
+
5
+ - Remove RubyGems certificate signing and its private-key requirement. Publishing always builds unsigned gems and verifies Sigstore and GitHub provenance attestations.
6
+ - Remove the setup `signing` option. Regenerate workflows with `gem:github:setup:update` to remove legacy configuration and signing-secret references.
7
+
8
+ ## v0.6.0
9
+
10
+ - Register RubyGems trusted publishers from the gemspec and release configuration with `gem:github:setup:publisher`, reusing existing registrations and RubyGems authentication/MFA support.
11
+ - Check publisher registration explicitly with `gem:github:setup:plan publisher=true`.
12
+
3
13
  ## v0.5.0
4
14
 
5
15
  - Support rebase merging by requiring each release PR to contain exactly one commit, while leaving ordinary PRs unrestricted. Generated rules allow merge, squash, and rebase methods according to repository settings.
@@ -68,9 +68,6 @@ jobs:
68
68
  id: build
69
69
  env:
70
70
  GITHUB_TOKEN: ${{ github.token }}
71
- <% if signing -%>
72
- GEM_SIGNING_KEY: ${{ secrets.GEM_SIGNING_KEY }}
73
- <% end -%>
74
71
  run: bundle exec bake gem:github:release:build
75
72
  - name: Sign RubyGems attestation
76
73
  if: steps.build.outputs.restored != 'true'
metadata CHANGED
@@ -1,37 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bake-gem-github
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  bindir: bin
9
- cert_chain:
10
- - |
11
- -----BEGIN CERTIFICATE-----
12
- MIIEFDCCAnygAwIBAgIBATANBgkqhkiG9w0BAQsFADAwMREwDwYDVQQKDAhTb2Nr
13
- ZXRyeTEbMBkGA1UEAwwSU29ja2V0cnkgUnVieSBHZW1zMB4XDTI2MDkyMTA3NTgx
14
- NFoXDTI3MDkyMTA3NTgxNFowMDERMA8GA1UECgwIU29ja2V0cnkxGzAZBgNVBAMM
15
- ElNvY2tldHJ5IFJ1YnkgR2VtczCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoC
16
- ggGBAM/QgjVgDzDo/xJEQoFvAzcVFP7msnswkhPJB2UDsbxXCZmers5jV512TM5s
17
- NwLHfzJiC4DcI5ax9ZYKM9Q+dS21YYagNqjtg3YPyDqR6phoibEA0VoMuInUQW68
18
- i5OkCJzYKGD2pYYVZnuFNqyM2ECUvXh/fBmvPoHbncAHhWPaCBH8mQJ8sRNc6+RV
19
- SoZZu1Yo/aW1zQ+SpZwad7s1ZmigfDNHKhJ22KwZHk+/5Zw1QXVfcajjswV0Mm2P
20
- irgjKN3fyNVkwlly63EBlR4VydT+g9QtJtqh7ee0ThhI+v4wYovf4dbLNcEBTHu1
21
- x1pGbXGx/2fBAST5eVwaXIx1V8VU22AJcBk1H2o5/1F0HfbD2HQjmFOA112KUwBW
22
- 9TtspZD3g6rCQFX53XvL9h6j2y1ukl7s5AdEzOe/x6r1MO8tSDtgcYoF89wgF/88
23
- Q/Eski0FckQ+znfESZcFcpzs2sPDoYW6SNVX4tZcNty85Y6WBHfHKio14x63PeyC
24
- CG1gMwIDAQABozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU
25
- SuMc0x24Xshtaa8SQVkBr2Z5WzIwDQYJKoZIhvcNAQELBQADggGBABI62ey5lDWm
26
- j8jsTQaNBMBb7LbKS3XkBwyL1UNGEwlicp399rJDeuNgVSHqBCZ/nE4yleNjgW9Y
27
- N6DKdxXCvXmFUoHvUINeAvThHxmlEGhSfXl1x55xHEig0rEP4jgdjnYdQI4fqeOM
28
- zIDN0F3ruArke4Y62SQgWVN7vspdAA41hBIRl1vsvs0KWG8DIVQ8cmR+TG6zjOmK
29
- iUiUZGNPnStV1O1xW83c+Ba4Am0krP6/forxDPhRvTehqkVYvMdPfYcICNb5IM58
30
- 5vaYvuj5AtfZuZWN0F/0KtSphhNC17rh6h8QmuYdMJ1clvlrkiEaO1UjPVwjgtxC
31
- x/ARh5X6q0/YTXl4r7EfSJEeqW7qhgu9EUj3mGIPHYdX0Dqih/NgK20F3GvQtTfB
32
- 7sse0duKBHXONYVwKAsceUVvqtCfyF608bCilCkbhw3QaInRj+BkRQKJ5Tuj2PZR
33
- 76a/hwaV2wWn5RtAFBaUQzQdo/xTqJ7IkwaFjOZe/QyvyoRjCK9Rdg==
34
- -----END CERTIFICATE-----
9
+ cert_chain: []
35
10
  date: 1980-01-02 00:00:00.000000000 Z
36
11
  dependencies:
37
12
  - !ruby/object:Gem::Dependency
@@ -107,10 +82,10 @@ files:
107
82
  - lib/bake/gem/github/publisher.rb
108
83
  - lib/bake/gem/github/registry.rb
109
84
  - lib/bake/gem/github/setup.rb
85
+ - lib/bake/gem/github/trusted_publisher.rb
110
86
  - lib/bake/gem/github/version.rb
111
87
  - license.md
112
88
  - readme.md
113
- - release.cert
114
89
  - releases.md
115
90
  - templates/release-prepare.yaml.erb
116
91
  - templates/release-publish.yaml.erb
checksums.yaml.gz.sig DELETED
@@ -1 +0,0 @@
1
- �?f�h�
data/release.cert DELETED
@@ -1,24 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIEFDCCAnygAwIBAgIBATANBgkqhkiG9w0BAQsFADAwMREwDwYDVQQKDAhTb2Nr
3
- ZXRyeTEbMBkGA1UEAwwSU29ja2V0cnkgUnVieSBHZW1zMB4XDTI2MDkyMTA3NTgx
4
- NFoXDTI3MDkyMTA3NTgxNFowMDERMA8GA1UECgwIU29ja2V0cnkxGzAZBgNVBAMM
5
- ElNvY2tldHJ5IFJ1YnkgR2VtczCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoC
6
- ggGBAM/QgjVgDzDo/xJEQoFvAzcVFP7msnswkhPJB2UDsbxXCZmers5jV512TM5s
7
- NwLHfzJiC4DcI5ax9ZYKM9Q+dS21YYagNqjtg3YPyDqR6phoibEA0VoMuInUQW68
8
- i5OkCJzYKGD2pYYVZnuFNqyM2ECUvXh/fBmvPoHbncAHhWPaCBH8mQJ8sRNc6+RV
9
- SoZZu1Yo/aW1zQ+SpZwad7s1ZmigfDNHKhJ22KwZHk+/5Zw1QXVfcajjswV0Mm2P
10
- irgjKN3fyNVkwlly63EBlR4VydT+g9QtJtqh7ee0ThhI+v4wYovf4dbLNcEBTHu1
11
- x1pGbXGx/2fBAST5eVwaXIx1V8VU22AJcBk1H2o5/1F0HfbD2HQjmFOA112KUwBW
12
- 9TtspZD3g6rCQFX53XvL9h6j2y1ukl7s5AdEzOe/x6r1MO8tSDtgcYoF89wgF/88
13
- Q/Eski0FckQ+znfESZcFcpzs2sPDoYW6SNVX4tZcNty85Y6WBHfHKio14x63PeyC
14
- CG1gMwIDAQABozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU
15
- SuMc0x24Xshtaa8SQVkBr2Z5WzIwDQYJKoZIhvcNAQELBQADggGBABI62ey5lDWm
16
- j8jsTQaNBMBb7LbKS3XkBwyL1UNGEwlicp399rJDeuNgVSHqBCZ/nE4yleNjgW9Y
17
- N6DKdxXCvXmFUoHvUINeAvThHxmlEGhSfXl1x55xHEig0rEP4jgdjnYdQI4fqeOM
18
- zIDN0F3ruArke4Y62SQgWVN7vspdAA41hBIRl1vsvs0KWG8DIVQ8cmR+TG6zjOmK
19
- iUiUZGNPnStV1O1xW83c+Ba4Am0krP6/forxDPhRvTehqkVYvMdPfYcICNb5IM58
20
- 5vaYvuj5AtfZuZWN0F/0KtSphhNC17rh6h8QmuYdMJ1clvlrkiEaO1UjPVwjgtxC
21
- x/ARh5X6q0/YTXl4r7EfSJEeqW7qhgu9EUj3mGIPHYdX0Dqih/NgK20F3GvQtTfB
22
- 7sse0duKBHXONYVwKAsceUVvqtCfyF608bCilCkbhw3QaInRj+BkRQKJ5Tuj2PZR
23
- 76a/hwaV2wWn5RtAFBaUQzQdo/xTqJ7IkwaFjOZe/QyvyoRjCK9Rdg==
24
- -----END CERTIFICATE-----
data.tar.gz.sig DELETED
Binary file
metadata.gz.sig DELETED
@@ -1 +0,0 @@
1
- ���y0�a�tq��ok��̤�ebَk��z�3�!�:ւ/�đ�U����кq�-�e���V��<ӽ�0["� n���xϼ�ڄd�eS_��;��J��1#����4 D��w�0��P�t܁G)!�����ș?Ǔ[䱭&�^O@���wƁ}E�x��x����F�#U3w�.D2��ϒ\�,m����O��pV�u�!&�M]�Z��4�}jv���s2����W�=I���~�|�RhE��5��LK��� �l^v���3ӏ�:�,&z-��MNs�7���4� �X�թ��Fbrjst6P�����b�"���֝�S�D��h��I�@����+P�ߗ�