Release automatically when the gemspec version changes - #83
Merged
Merged
Conversation
Fixes #23. push_gem.yml already published through trusted publishing with rubygems/release-gem, but only by hand, and it had never run. It now runs after CI Test passes on main, and publishes only when singed.gemspec's version isn't on RubyGems yet, so bumping the version is the release, as with the rubyatscale gems that use shared-config's cd.yml. It still works by hand for retries, and skips a version that's already published. - The check job only lets a push to this repo through, since a fork's pull request can come from a branch named main. - `rake release` pushes the current branch along with the tag, so the release job checks out main itself, rather than a detached HEAD, and first confirms main is still the commit CI tested. - Creates the GitHub release, and posts to Slack on failure, like cd.yml. The workflow's filename and the rubygems.org environment stay as they are, since the trusted publisher on RubyGems.org is registered against them.
If `gh release create` failed after the gem was already on RubyGems, a retry skipped everything, since the version was published, so the GitHub release never got created. The check job now also looks for a GitHub release for the version, and a separate job creates it whenever it's missing, whether the gem was just published or already had been.
rubygems/release-gem v1.4.1 stores the token in git's credential cache for the tag push and clears it afterwards, so the checkout doesn't need to leave one behind.
CodeQL flagged actions/cache-poisoning/poisonable-step: the check job checked out the workflow_run head SHA and then ran code from it, since Gem::Specification.load evaluates the gemspec. The job's `if` already limits it to pushes to this repo, but the analysis can't see that. The job now fetches singed.gemspec at that SHA through the API and reads spec.version with a strict pattern, so nothing from the commit runs and the job no longer needs Ruby. If the gemspec ever stops using a string literal for the version, the job fails with an error instead of guessing.
The check job runs after every green push to main, whether or not the version changed, so a timeout or a 5xx from rubygems.org failed it and posted a false alarm to Slack. curl --retry retries those, and still reports a 404 straight away, since a missing version isn't an error.
The error said the run for main's new commit would release the version, but that run only happens if CI passes on the commit. If it fails, the version waits for the next green push or a dispatch, so the message now says so.
A dispatch releases main's tip without checking that CI passed on it, which suits a retry, and dispatching from another branch skips every job without saying why. The header comment now says both.
A version like 1.0.0.rc1 passed the version check but got an ordinary GitHub release, which would have made it Latest. RubyGems treats any version containing a letter as a prerelease, so the release job now passes --prerelease for those.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #23. Releases now happen when
singed.gemspec's version changes, the way the rubyatscale gems that use shared-config'scd.ymlrelease. This is the approach #78 had at 6e0947c, before it moved to release-please. It's here so releases work while #78 waits for approvals; #78 can replace it once it lands.push_gem.ymlalready published through RubyGems trusted publishing withrubygems/release-gem, but only by hand, and it has never run. It now runs after CI Test passes onmain, and publishes only when the gemspec's version isn't on RubyGems yet, so bumping the version is the release. It can still be dispatched frommainto retry, and it skips whatever's already done. A dispatch doesn't wait for CI, so it's meant for whenmainis green.mainthrough, since a fork's pull request can come from a branch namedmain. It readssinged.gemspecthrough the API at the tested SHA instead of checking it out and evaluating it, so no code from the triggering commit runs in this privileged context. It then asks RubyGems whether the version exists and GitHub whether it has a release. The RubyGems lookup retries on transient errors, since the job runs after every green push tomain, not only after a version bump.rake releasepushes the current branch along with the tag, so the job checks outmainitself rather than a detached HEAD. It first confirmsmainis still the commit CI tested. No bundler cache, since it publishes. The checkout doesn't persist credentials:release-gemv1.4.1 puts the token in git's credential cache for the tag push.--prerelease.cd.yml.The workflow's filename and the
rubygems.orgenvironment stay as they are, since the trusted publisher on RubyGems.org is registered against them.These are #78's four commits cherry-picked onto
main. The resultingpush_gem.ymlmatches 6e0947c's except for three action pins, which keepmain's newer versions (harden-runner v2.21.1, checkout v7.0.1, setup-ruby v1.325.0). The first commit's message drops two bullets that #80 and #81 already delivered. The last four commits are follow-ups from review, so the file now also differs from 6e0947c's in those.Test plan
Gemfile.lockalready listsx86_64-linux, and setup-ruby installs theBUNDLED WITHversion, sobundle installshouldn't dirty the tree beforerake release(the failure described in Automate releasing #23).rake release, so a retry after a tag push skips the tag and pushes the gem.gh apifetch would stop the step with gh's own error, since the default shell runsbash -e.mainmoves between check and release, only the newer version is released; the earlier run aborts on purpose and posts to Slack.--verify-tagfails rather than creating a release without a tag.main.