Skip to content

Commit 1e69a21

Browse files
authored
Remove RubyGems certificate signing. (#37)
Signed-off-by: Samuel Williams <samuel.williams@oriontransfer.co.nz>
1 parent a15528f commit 1e69a21

22 files changed

Lines changed: 70 additions & 111 deletions

File tree

‎.github/workflows/release-publish.yaml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ jobs:
6868
id: build
6969
env:
7070
GITHUB_TOKEN: ${{ github.token }}
71-
GEM_SIGNING_KEY: ${{ secrets.GEM_SIGNING_KEY }}
7271
run: bundle exec bake gem:github:release:build
7372
- name: Sign RubyGems attestation
7473
if: steps.build.outputs.restored != 'true'

‎bake-gem-github.gemspec‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ Gem::Specification.new do |spec|
1515
"changelog_uri" => "https://github.com/socketry/bake-gem-github/blob/main/releases.md",
1616
"source_code_uri" => "https://github.com/socketry/bake-gem-github.git",
1717
}
18-
spec.cert_chain = ["release.cert"]
19-
spec.signing_key = File.expand_path("~/.gem/socketry-release.pem")
20-
spec.files = Dir.glob(["{bake,context,lib,templates}/**/*", "*.md", "release.cert"], base: __dir__)
18+
spec.files = Dir.glob(["{bake,context,lib,templates}/**/*", "*.md"], base: __dir__)
2119
spec.required_ruby_version = ">= 3.3"
2220
spec.add_dependency "bake-gem", ">= 0.15.0"
2321
spec.add_dependency "bake-releases", "~> 0.6"

‎bake/gem/github.rb‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99
# @parameter branch [String] Default branch name; discovered through GitHub when omitted.
1010
# @parameter approvals [Integer] Number of approving reviews.
1111
# @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.
1312
# @parameter ruby [String] Ruby version for release workflows.
1413
# @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")
1615
require "bake/gem/github/setup"
1716
require "bake/gem/shell"
1817

@@ -31,7 +30,6 @@ def setup(checks:, repository: nil, branch: nil, approvals: 2, reviewers: nil, s
3130
reviewers: reviewers,
3231
ruby: ruby,
3332
}
34-
options[:signing] = signing unless signing.nil?
3533

3634
Bake::Gem::GitHub::Setup.new(context.root).generate(**options)
3735
end

‎config/release.yaml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ checks:
1515
- validate
1616
- Release validation
1717
approvals: 2
18-
signing: true
1918
ruby: '3.4'
2019
environment: rubygems
2120
reviewers:

‎context/getting-started.md‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ bundle exec bake gem:github:setup:plan publisher=true
6666

6767
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.
6868

69-
For a gem that has never been published, configure a pending publisher manually. Account ownership, MFA enrollment, the GitHub environment, and signing bootstrap 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.
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.
7070

71-
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.
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.
7272

73-
Ensure another maintainer can administer the repository and recover its RubyGems account and signing key.
73+
Ensure another maintainer can administer the repository and recover its RubyGems account.
7474

7575
## Authorize publishing
7676

@@ -133,6 +133,8 @@ git diff
133133

134134
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.
135135

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+
136138
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.
137139

138140
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.

‎context/preparing-releases.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Merging into the configured default branch triggers `release-publish.yaml` throu
3636

3737
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.
3838

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.
4040

4141
## Resume interrupted preparation
4242

‎context/verifying-releases.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Use this when checking a completed release or confirming which source commit pro
66

77
## What publishing verifies
88

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:
1010

1111
- A Sigstore bundle submitted explicitly with `gem push --attestation` using RubyGems 4.0.21.
1212
- 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.

‎fixtures/bake/gem/github/publication_context.rb‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ module GitHub
2828
end
2929

3030
before do
31-
Setup.new(root).generate(repository: "socketry/example", checks: ["Test"], signing: false)
31+
Setup.new(root).generate(repository: "socketry/example", checks: ["Test"])
3232

3333
FileUtils.mkdir_p(File.join(root, "pkg"))
3434
File.write(File.join(root, "pkg", receipt.fetch(:file)), "Exact signed bytes")

‎fixtures/bake/gem/github/repository_context.rb‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def after_gem_release_version_increment(version)
4848
end
4949
RUBY
5050
File.write(File.join(repository, ".gitignore"), "/pkg/\n")
51-
Setup.new(repository).generate(repository: "socketry/example", checks: ["Tests"], signing: false)
51+
Setup.new(repository).generate(repository: "socketry/example", checks: ["Tests"])
5252
git("init", "--quiet", "--initial-branch=main")
5353
git("config", "core.hooksPath", File::NULL)
5454
git("config", "commit.gpgsign", "false")

‎guides/getting-started/readme.md‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ bundle exec bake gem:github:setup:plan publisher=true
6666

6767
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.
6868

69-
For a gem that has never been published, configure a pending publisher manually. Account ownership, MFA enrollment, the GitHub environment, and signing bootstrap 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.
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.
7070

71-
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.
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.
7272

73-
Ensure another maintainer can administer the repository and recover its RubyGems account and signing key.
73+
Ensure another maintainer can administer the repository and recover its RubyGems account.
7474

7575
## Authorize publishing
7676

@@ -133,6 +133,8 @@ git diff
133133

134134
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.
135135

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+
136138
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.
137139

138140
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.

0 commit comments

Comments
 (0)