From 6cf701509e0e3c3b216530b2f937a46b0a031caf Mon Sep 17 00:00:00 2001 From: Patrick Cherry Date: Wed, 14 Oct 2026 10:53:45 +0100 Subject: [PATCH 1/5] ci: configure release-please Add release-please (manifest mode, ruby release type) to manage version bumps, CHANGELOG.md, tags and GitHub releases, starting from v4.5.0. - release-please workflow opens/updates the release PR on pushes to main, re-locks Gemfile.lock and the Appraisal lockfiles on the release branch, and publishes the gem when a release is created. - build_publish accepts `ref` and `publish` inputs so it can be called from the release workflow (tags created with GITHUB_TOKEN do not trigger CI). - Replace the "changelog must be edited" check with a Conventional Commits PR title check. - Remove the hand-maintained Unreleased section from CHANGELOG.md, as release-please inserts new entries above the first version heading. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/build_publish.yml | 15 +++++- .github/workflows/changelog.yml | 29 ----------- .github/workflows/pr_title.yml | 25 ++++++++++ .github/workflows/release-please.yml | 72 ++++++++++++++++++++++++++++ .release-please-manifest.json | 3 ++ CHANGELOG.md | 5 +- README.md | 25 ++++++---- release-please-config.json | 13 +++++ 8 files changed, 145 insertions(+), 42 deletions(-) delete mode 100644 .github/workflows/changelog.yml create mode 100644 .github/workflows/pr_title.yml create mode 100644 .github/workflows/release-please.yml create mode 100644 .release-please-manifest.json create mode 100644 release-please-config.json diff --git a/.github/workflows/build_publish.yml b/.github/workflows/build_publish.yml index 9f2a645..eea94e0 100644 --- a/.github/workflows/build_publish.yml +++ b/.github/workflows/build_publish.yml @@ -1,7 +1,16 @@ name: Build and publish on: - workflow_call: {} + workflow_call: + inputs: + ref: + description: Git ref to build (defaults to the ref that triggered the workflow) + type: string + default: '' + publish: + description: Publish the gem even when not triggered by a tag push + type: boolean + default: false jobs: build: @@ -12,6 +21,8 @@ jobs: packages: read steps: - uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref }} - name: Set up Ruby uses: ruby/setup-ruby@v1 @@ -31,7 +42,7 @@ jobs: publish: name: Publish needs: build - if: github.ref_type == 'tag' + if: inputs.publish || github.ref_type == 'tag' runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml deleted file mode 100644 index 5926552..0000000 --- a/.github/workflows/changelog.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Changelog - -on: - pull_request: - branches: - - '**' - -jobs: - changelog-updated: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - name: Check if changelog updated - id: changed-files-specific - uses: tj-actions/changed-files@v46 - with: - base_sha: ${{ github.event.pull_request.base.sha }} - files: | - CHANGELOG.md - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Fail job if changelog not updated - if: steps.changed-files-specific.outputs.any_changed == 'false' - run: | - exit 1 - diff --git a/.github/workflows/pr_title.yml b/.github/workflows/pr_title.yml new file mode 100644 index 0000000..1210c0a --- /dev/null +++ b/.github/workflows/pr_title.yml @@ -0,0 +1,25 @@ +name: PR title + +# release-please builds the changelog and picks the next version from +# Conventional Commit messages, so PR titles (which become the squash-merge +# commit message) must follow https://www.conventionalcommits.org/ + +on: + pull_request: + types: + - opened + - edited + - reopened + - synchronize + +permissions: + pull-requests: read + +jobs: + conventional-title: + name: Conventional PR title + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v6 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..b3cbc12 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,72 @@ +name: Release Please + +on: + push: + branches: + - main + +permissions: {} + +jobs: + release-please: + name: Release Please + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + outputs: + release_created: ${{ steps.release.outputs.release_created }} + tag_name: ${{ steps.release.outputs.tag_name }} + pr_branch: ${{ steps.release.outputs.pr && fromJSON(steps.release.outputs.pr).headBranchName || '' }} + steps: + - uses: googleapis/release-please-action@v5 + id: release + + # release-please bumps lib/rpi_auth/version.rb but does not fully update the + # lockfiles (it misses the CHECKSUMS entry and the Appraisal gemfiles), which + # makes `bundle install` fail in frozen mode. Re-lock them on the release PR. + update-lockfiles: + name: Update lockfiles on release PR + needs: release-please + if: needs.release-please.outputs.pr_branch != '' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ needs.release-please.outputs.pr_branch }} + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + + - name: Re-lock gemfiles + run: | + bundle lock + for gemfile in gemfiles/*.gemfile; do + BUNDLE_GEMFILE="${gemfile}" bundle lock + done + + - name: Commit and push lockfiles + run: | + if git diff --quiet -- Gemfile.lock gemfiles/; then + echo "Lockfiles already up to date" + exit 0 + fi + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add Gemfile.lock gemfiles/*.gemfile.lock + git commit -m "chore: update lockfiles for release" + git push + + build_publish: + name: Build and publish + needs: release-please + if: needs.release-please.outputs.release_created == 'true' + permissions: + contents: read + packages: write + uses: ./.github/workflows/build_publish.yml + with: + ref: ${{ needs.release-please.outputs.tag_name }} + publish: true diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..7aa3d56 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "4.5.0" +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 57bebce..31b786b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +From v4.6.0 onwards this file is maintained by +[release-please](https://github.com/googleapis/release-please). Do not edit it +by hand; see the "Releasing" section of the README. ## [v4.5.0] @@ -184,7 +186,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - rails model concern to allow host app to add auth behaviour to a model - callback, logout and failure routes to handle auth -[Unreleased]: https://github.com/RaspberryPiFoundation/rpi-auth/compare/v4.5.0...HEAD [v4.5.0]: https://github.com/RaspberryPiFoundation/rpi-auth/releases/tag/v4.5.0 [v4.4.0]: https://github.com/RaspberryPiFoundation/rpi-auth/releases/tag/v4.4.0 [v4.3.0]: https://github.com/RaspberryPiFoundation/rpi-auth/releases/tag/v4.3.0 diff --git a/README.md b/README.md index ca2505b..9a743eb 100644 --- a/README.md +++ b/README.md @@ -324,17 +324,24 @@ After changing `Appraisals` or the gemspec dependencies, regenerate the gemfiles ## Releasing -Ensure that the version number has been updated in: https://github.com/RaspberryPiFoundation/rpi-auth/blob/main/lib/rpi_auth/version.rb +Releases are managed by [release-please](https://github.com/googleapis/release-please). -Ensure that the changelog has been updated in: https://github.com/RaspberryPiFoundation/rpi-auth/blob/main/CHANGELOG.md +PR titles must follow [Conventional Commits](https://www.conventionalcommits.org/), +because the squash-merge commit message is used to pick the next version and +build the changelog: -Create and push a new tag from `main`: +* `fix: ...` produces a patch release. +* `feat: ...` produces a minor release. +* `feat!: ...`, or a `BREAKING CHANGE:` footer in the commit body, produces a major release. +* Other types such as `chore:`, `ci:`, `docs:`, `test:` and `refactor:` do not trigger a release on their own. -``` -git tag v1.2.2 -git push --tags -``` +Do not edit `CHANGELOG.md` or `lib/rpi_auth/version.rb` by hand. -Create a new release at: https://github.com/RaspberryPiFoundation/rpi-auth/releases/new +When releasable commits land on `main`, release-please opens or updates a +release PR. That PR bumps the version, updates the changelog and lockfiles. To +release, review and merge the release PR. release-please then tags the merge +commit (e.g. `v1.2.3`), creates a GitHub release, and the gem is built and +published to GitHub Packages. -Select the newly created tag, the target should be `main`, and the release name should be the same as the tag name eg. `v1.2.2`. Enter a short description of the release (generally best to copy / paste the changelog entry). +To force a particular version, add a `Release-As: x.y.z` footer to a commit +message on `main`. diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..5285cbc --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "include-component-in-tag": false, + "include-v-in-tag": true, + "packages": { + ".": { + "release-type": "ruby", + "package-name": "rpi_auth", + "version-file": "lib/rpi_auth/version.rb", + "changelog-path": "CHANGELOG.md" + } + } +} From fe6ab020da10044f765744703b5113c78f376bdd Mon Sep 17 00:00:00 2001 From: Patrick Cherry Date: Wed, 14 Oct 2026 10:59:36 +0100 Subject: [PATCH 2/5] ci: dispatch CI on the release PR branch Pushes made with GITHUB_TOKEN don't trigger workflows, so the required status checks never reported on release-please PRs. workflow_dispatch events are exempt from that rule, so have the release workflow dispatch CI against the release branch once the lockfiles are updated. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 3 +++ .github/workflows/release-please.yml | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index df8fdc9..26d2557 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,9 @@ on: - '**' tags: - '**' + # Allows the release-please workflow to run CI on the release PR branch: + # pushes made with GITHUB_TOKEN do not trigger workflows, but dispatches do. + workflow_dispatch: {} jobs: test: diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index b3cbc12..8cd7c78 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -32,6 +32,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: write + actions: write steps: - uses: actions/checkout@v4 with: @@ -59,6 +60,15 @@ jobs: git commit -m "chore: update lockfiles for release" git push + # Pushes made with GITHUB_TOKEN don't trigger CI, so the required status + # checks would never report on the release PR. Dispatch CI explicitly so + # it runs against the final head commit of the release branch. + - name: Run CI on release PR + run: gh workflow run ci.yml --repo "${{ github.repository }}" --ref "${BRANCH}" + env: + GH_TOKEN: ${{ github.token }} + BRANCH: ${{ needs.release-please.outputs.pr_branch }} + build_publish: name: Build and publish needs: release-please From 800f3e3deea2410080763b5b8104f5c47815de47 Mon Sep 17 00:00:00 2001 From: Patrick Cherry Date: Wed, 14 Oct 2026 11:12:04 +0100 Subject: [PATCH 3/5] docs: clarify release process in README Explain that the PR title and description become the squash-merge commit message, list all release-producing types, and remove the outdated instruction to update version.rb by hand. Co-Authored-By: Claude Opus 5.5 --- README.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 9a743eb..bfa3c16 100644 --- a/README.md +++ b/README.md @@ -300,8 +300,6 @@ If running Hydra locally you will need to configure a new client with the follow There is a seed in the Profile repo to set this client up correctly, running the v1 setup tasks will create this client -Ensure to update `lib/rpi_auth/version.rb` when publishing a new version. - ### Testing ```bash @@ -326,22 +324,24 @@ After changing `Appraisals` or the gemspec dependencies, regenerate the gemfiles Releases are managed by [release-please](https://github.com/googleapis/release-please). -PR titles must follow [Conventional Commits](https://www.conventionalcommits.org/), -because the squash-merge commit message is used to pick the next version and -build the changelog: +PR titles must follow [Conventional Commits](https://www.conventionalcommits.org/). +When a PR is squash-merged, its title becomes the commit message on `main`, and +release-please uses these messages to choose the next version and write the +changelog: -* `fix: ...` produces a patch release. -* `feat: ...` produces a minor release. -* `feat!: ...`, or a `BREAKING CHANGE:` footer in the commit body, produces a major release. -* Other types such as `chore:`, `ci:`, `docs:`, `test:` and `refactor:` do not trigger a release on their own. +* `fix:`, `perf:` and `revert:` produce a patch release. +* `feat:` produces a minor release. +* `feat!:`, `fix!:`, or a `BREAKING CHANGE:` footer in the PR description, produces a major release. +* Other types, such as `chore:`, `ci:`, `docs:`, `test:` and `refactor:`, do not produce a release and are left out of the changelog. Do not edit `CHANGELOG.md` or `lib/rpi_auth/version.rb` by hand. -When releasable commits land on `main`, release-please opens or updates a -release PR. That PR bumps the version, updates the changelog and lockfiles. To -release, review and merge the release PR. release-please then tags the merge -commit (e.g. `v1.2.3`), creates a GitHub release, and the gem is built and -published to GitHub Packages. +When a PR that produces a release is merged into `main`, release-please opens +or updates a release PR. The release PR updates the version number, the +changelog and the lockfiles, and CI runs against it. To release, review and +merge the release PR. release-please then tags the merge commit (for example +`v4.6.0`) and creates a GitHub release, and the gem is built and published to +GitHub Packages. -To force a particular version, add a `Release-As: x.y.z` footer to a commit -message on `main`. +To release a specific version, add a `Release-As: x.y.z` footer to the +description of a PR before squash-merging it. From dd938df691afa0c540b89226590056286b9c57ce Mon Sep 17 00:00:00 2001 From: Patrick Cherry Date: Wed, 14 Oct 2026 11:14:09 +0100 Subject: [PATCH 4/5] Update CHANGELOG for release management details Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31b786b..2c6b450 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -From v4.6.0 onwards this file is maintained by -[release-please](https://github.com/googleapis/release-please). Do not edit it +Releases after v4.5.0 are maintained by +[release-please](https://github.com/googleapis/release-please). Do not edit this file by hand; see the "Releasing" section of the README. ## [v4.5.0] From fa00f2b8498b52df8cf82cdfb78ffc22cd8bfa07 Mon Sep 17 00:00:00 2001 From: Patrick Cherry Date: Wed, 14 Oct 2026 11:27:34 +0100 Subject: [PATCH 5/5] docs: keep the README installation example version up to date Update the example tag to v4.5.0 and wrap it in release-please version markers, with README.md listed in extra-files, so each release PR updates it automatically. Co-Authored-By: Claude Opus 5.5 --- README.md | 7 +++++-- release-please-config.json | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bfa3c16..19a6550 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,11 @@ The Engine includes the [Rails CSRF protection gem](https://github.com/cookpad/o Add this line to your application's Gemfile: + ```ruby -gem 'rpi_auth', git: 'https://github.com/RaspberryPiFoundation/rpi-auth.git', tag: 'v3.2.0' +gem 'rpi_auth', git: 'https://github.com/RaspberryPiFoundation/rpi-auth.git', tag: 'v4.5.0' ``` + And then execute: @@ -338,7 +340,8 @@ Do not edit `CHANGELOG.md` or `lib/rpi_auth/version.rb` by hand. When a PR that produces a release is merged into `main`, release-please opens or updates a release PR. The release PR updates the version number, the -changelog and the lockfiles, and CI runs against it. To release, review and +changelog, the lockfiles and the version in the installation example above, and +CI runs against it. To release, review and merge the release PR. release-please then tags the merge commit (for example `v4.6.0`) and creates a GitHub release, and the gem is built and published to GitHub Packages. diff --git a/release-please-config.json b/release-please-config.json index 5285cbc..4d26524 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -7,7 +7,8 @@ "release-type": "ruby", "package-name": "rpi_auth", "version-file": "lib/rpi_auth/version.rb", - "changelog-path": "CHANGELOG.md" + "changelog-path": "CHANGELOG.md", + "extra-files": ["README.md"] } } }