diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 53eb34a..8c71662 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,10 +1,11 @@ name: Release -# Cut a release by bumping lib/omniauth-shipbob/version.rb, committing, then: -# git tag -a v0.1.0 -m "v0.1.0" && git push origin master --tags +# Cut a release from the GitHub Releases UI: draft a release, set the tag to `vX.Y.Z` +# (matching lib/omniauth-shipbob/version.rb), and publish it. GitHub creates the tag, +# which fires this workflow. on: - push: - tags: ["v*"] + release: + types: [published] jobs: # Never publish a version that has not passed the matrix. @@ -26,11 +27,14 @@ jobs: permissions: id-token: write # mandatory for trusted publishing - contents: write # `rake release` pushes the tag; `gh` creates the release + # GitHub already created the release and its tag, so nothing here writes to + # the repo: `rake release` sees the tag and skips its own tag-and-push step. + contents: read steps: - uses: actions/checkout@v5 with: + ref: ${{ github.event.release.tag_name }} # rubygems/release-gem installs its own short-lived git credentials. persist-credentials: false @@ -40,38 +44,20 @@ jobs: bundler-cache: true # `rake release` builds whatever version.rb says, regardless of the tag. If the - # two disagree it would publish one version and tag another, so stop here first. - - name: Verify the tag matches the gem version + # two disagree it would publish one version under another version's release, so + # stop here first. + - name: Verify the release tag matches the gem version + env: + TAG_NAME: ${{ github.event.release.tag_name }} run: | gem_version="$(ruby -r./lib/omniauth-shipbob/version -e 'print Omniauth::Shipbob::VERSION')" - tag_version="${GITHUB_REF_NAME#v}" + tag_version="${TAG_NAME#v}" if [ "$gem_version" != "$tag_version" ]; then - echo "::error::Tag ${GITHUB_REF_NAME} does not match lib/omniauth-shipbob/version.rb (${gem_version})." + echo "::error::Release tag ${TAG_NAME} does not match lib/omniauth-shipbob/version.rb (${gem_version})." exit 1 fi echo "Releasing omniauth-shipbob ${gem_version}" # Builds the gem and runs `gem push` against the gemspec's allowed_push_host. - # The tag already exists, so bundler skips its own tag-and-push step. - name: Push to RubyGems.org uses: rubygems/release-gem@v1 - - - name: Create the GitHub release - env: - GH_TOKEN: ${{ github.token }} - run: | - notes="$(awk -v v="${GITHUB_REF_NAME#v}" ' - $0 ~ "^## \\[" v "\\]" { flag = 1; next } - flag && /^## \[/ { exit } - flag { print } - ' CHANGELOG.md)" - - if [ -n "$(printf '%s' "$notes" | tr -d '[:space:]')" ]; then - printf '%s\n' "$notes" > release-notes.md - gh release create "$GITHUB_REF_NAME" --verify-tag \ - --title "$GITHUB_REF_NAME" --notes-file release-notes.md - else - echo "No CHANGELOG.md section for ${GITHUB_REF_NAME}; generating notes from commits." - gh release create "$GITHUB_REF_NAME" --verify-tag \ - --title "$GITHUB_REF_NAME" --generate-notes - fi diff --git a/CHANGELOG.md b/CHANGELOG.md index 659215e..a94c360 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,21 @@ # Changelog -All notable changes to this project are documented in this file. +All notable changes to this project are documented in this file. Each version heading +links to its [GitHub release](https://github.com/dropstream/omniauth-shipbob/releases), +where the notes are generated from the merged pull requests. -## [0.1.0] - 2026-08-19 +## [Unreleased] + +### Changed + +- Releases are now cut by publishing a release from the GitHub Releases UI instead of by + pushing a tag from the command line. The `Release` workflow triggers on + `release: published` and no longer creates the GitHub release itself, which previously + failed with `Release.tag_name already exists` when the release came from the UI. + Release notes are now produced by **Generate release notes** in the UI rather than + extracted from this file; this file links to each release instead. + +## [0.1.0] - 2026-08-26 ### Changed @@ -46,3 +59,8 @@ All notable changes to this project are documented in this file. ## [0.0.2] - Initial published strategy. + +[Unreleased]: https://github.com/dropstream/omniauth-shipbob/compare/v0.1.0...master +[0.1.0]: https://github.com/dropstream/omniauth-shipbob/releases/tag/v0.1.0 +[0.0.3]: https://github.com/dropstream/omniauth-shipbob/releases/tag/v0.0.3 +[0.0.2]: https://github.com/dropstream/omniauth-shipbob/releases/tag/v0.0.2 diff --git a/README.md b/README.md index 46fdf9c..17c734e 100644 --- a/README.md +++ b/README.md @@ -82,30 +82,32 @@ To install this gem onto your local machine, run `bundle exec rake install`. ## Releasing -Releases are cut by pushing a tag; GitHub Actions builds and publishes the gem to -[rubygems.org](https://rubygems.org) via +Releases are cut from the [GitHub Releases UI](https://github.com/dropstream/omniauth-shipbob/releases/new); +GitHub Actions builds and publishes the gem to [rubygems.org](https://rubygems.org) via [RubyGems trusted publishing](https://guides.rubygems.org/trusted-publishing/), so no API key is stored in the repo and the gemspec can keep `rubygems_mfa_required`. 1. Bump `VERSION` in `lib/omniauth-shipbob/version.rb` and add a `CHANGELOG.md` section - for it (the release notes are taken from that section). -2. Commit both on `master`. -3. Tag and push: - - ```sh - git tag -a v0.1.0 -m "v0.1.0" - git push origin master --tags - ``` - -The `Release` workflow then runs the full test matrix, refuses to continue if the tag and -`version.rb` disagree, pushes the gem, and opens a GitHub release. + for it, along with a link definition for the new heading at the bottom of that file. + Commit both on `master`. +2. Draft a new release with the target set to `master` and the tag set to the version + prefixed with `v` — `v0.1.0`, not `0.1.0`. The prefix is stripped before comparing + against `version.rb`; the gem version itself carries no `v`. +3. Click **Generate release notes** — the preferred method — then publish. The generated + notes list the merged pull requests; `CHANGELOG.md` carries the curated prose and + links back to each release. + +Publishing creates the tag, which fires the `Release` workflow: it reruns the full test +matrix, refuses to continue if the tag and `version.rb` disagree, and pushes the gem. +Note that RubyGems versions are immutable — a bad release can be yanked, never replaced, +so the version bump has to be committed before the release is published. ### One-time RubyGems setup -Before the first automated release, register this repo as a trusted publisher: on -rubygems.org open the gem → **Trusted publishers** → **Create**, with owner -`dropstream`, repository `omniauth-shipbob`, workflow `release.yml`, and environment -`release`. +Already configured, and only needed again if the gem is renamed or moved: on rubygems.org +open the gem -> **Trusted publishers** -> **Create**, with owner `dropstream`, repository +`omniauth-shipbob`, workflow `release.yml`, and environment `release`. The repo also needs +an environment named `release`. ## Contributing