chore: publish releases from CI with RubyGems trusted publishing - #242
felipefreitag wants to merge 2 commits into
Conversation
A push of a v* tag now runs the Release workflow. It checks the tag against Resend::VERSION, runs rubocop and the specs, builds the gem, pushes it to RubyGems.org through the OIDC trusted publisher with a sigstore attestation, then creates the GitHub release. The publish job needs a trusted publisher on rubygems.org for resend/resend-ruby, workflow release.yml, environment release. Until an owner adds it the publish job fails and releases stay manual. Mirrors resend-node 1097 and resend-python 281. DEV-2133
|
Running ultrareview automatically — This workflow automates production gem publishing and GitHub releases using trusted OIDC permissions, tag/version validation, and concurrency controls, so subtle CI or supply-chain mistakes could publish an incorrect or compromised artifact.. I'll post findings when complete. |
There was a problem hiding this comment.
Ultrareview completed in 3m 35s
1 issue found across 1 file
Confidence score: 3/5
.github/workflows/release.ymluses a constant concurrency group, so a second tag pushed during an active release can cancel the earlier pending run and leave that version unpublished; key the group bygithub.refor remove this concurrency setting.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".github/workflows/release.yml">
<violation number="1" location=".github/workflows/release.yml:10">
P2: When a second tag is pushed while another release is running, this constant group can replace the earlier pending tag run, so that version is never published. Key the group by `github.ref` or remove this concurrency group so each tag run is retained.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| workflow_dispatch: | ||
|
|
||
| concurrency: | ||
| group: release |
There was a problem hiding this comment.
P2: When a second tag is pushed while another release is running, this constant group can replace the earlier pending tag run, so that version is never published. Key the group by github.ref or remove this concurrency group so each tag run is retained.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/release.yml, line 10:
<comment>When a second tag is pushed while another release is running, this constant group can replace the earlier pending tag run, so that version is never published. Key the group by `github.ref` or remove this concurrency group so each tag run is retained.</comment>
<file context>
@@ -0,0 +1,101 @@
+ workflow_dispatch:
+
+concurrency:
+ group: release
+ cancel-in-progress: false
+
</file context>
| group: release | |
| group: release-${{ github.ref }} |
The guard and both publish gates now check the ref type instead of the event name, so a manual run from a tag verifies the tag as well. The smoke test compares the installed gem version to the tag. The version shape accepts the dotted prerelease form this gem has shipped before, such as 1.3.0.alpha.1.
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Confidence score: 2/5
- In
.github/workflows/release.yml, manually dispatching the workflow for a tag now satisfies both release-job conditions, so it can publish the gem and create a GitHub release unexpectedly; require a push event in addition to the tag ref for both jobs.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".github/workflows/release.yml">
<violation number="1" location=".github/workflows/release.yml:71">
P1: When the workflow is manually dispatched against a tag, both release jobs now run because `github.ref_type` is `tag`, publishing the gem and creating a release. Require a push event as well as a tag ref in both job conditions so manual runs remain checks/build only.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
|
|
||
| publish-rubygems: | ||
| needs: ci | ||
| if: github.ref_type == 'tag' |
There was a problem hiding this comment.
P1: When the workflow is manually dispatched against a tag, both release jobs now run because github.ref_type is tag, publishing the gem and creating a release. Require a push event as well as a tag ref in both job conditions so manual runs remain checks/build only.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/release.yml, line 71:
<comment>When the workflow is manually dispatched against a tag, both release jobs now run because `github.ref_type` is `tag`, publishing the gem and creating a release. Require a push event as well as a tag ref in both job conditions so manual runs remain checks/build only.</comment>
<file context>
@@ -65,11 +64,11 @@ jobs:
publish-rubygems:
needs: ci
- if: github.event_name == 'push'
+ if: github.ref_type == 'tag'
runs-on: ubuntu-latest
timeout-minutes: 15
</file context>
Maintainers can now publish a release by pushing a
v*tag. The Release workflow runs the checks, builds the gem, pushes it to RubyGems.org and creates the GitHub release.Before, a release meant a GitHub release made in the UI, then
gem pushfrom a laptop with a personal API key. RubyGems recorded no link between the gem file and the commit that produced it, and no version of the gem carries an attestation.Now every push carries a sigstore attestation that names the repository, the workflow and the commit. The GitHub release exists only after the push succeeds. A tag that does not match the version in
lib/resend/version.rbfails before anything is pushed.How to reach it. Merge a version bump, then tag the merge commit with
vplus the version and push the tag. Watch the Release run. A manual run of the workflow from the Actions tab executes the checks and the build only.Not covered. RubyGems must know the workflow first. A gem owner adds a trusted publisher for
resend/resend-ruby, workflowrelease.yml, environmentrelease. Until then the publish job fails and releases stay manual. This mirrors resend-node #1097 and resend-python #281.DEV-2133
Summary by cubic
Pushing a
v*tag now publishes a release from CI with RubyGems trusted publishing. The workflow checks the tag againstlib/resend/version.rb, runs RuboCop and specs, builds the gem, smoke-tests the installed gem version against the tag, pushes it to RubyGems.org with a sigstore attestation, and only then creates the GitHub release. This replaces the old manualgem pushflow from a laptop, so releases now carry proof of the repository, workflow, and commit that produced them.Setup
resend/resend-rubyas a trusted publisher for therelease.ymlworkflow andreleaseenvironment before publishing can succeed.Behavior
lib/resend/version.rbfails before anything is pushed.Written for commit d264036. Summary will update on new commits.