From 59da9e263fa2f693dbf80940e1b49af45cbdabf1 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Tue, 15 Sep 2026 15:58:49 +0200 Subject: [PATCH 1/4] ci: replace the two-stage release flow with release-please initiate_release.yml opened a release-NN branch with a hand-typed version and release.yml published whatever that branch name said, with publish-new-version.yml as a manual fallback. All three are gone. release-please keeps the bump in a reviewable Release PR, and the suite runs before the tag. This is the one repo where the version was never derived from PR titles, so pr_title.yml is a behaviour change rather than an alignment: titles now decide the version, and a non-conventional title ships nothing. gradle.properties is updated through the generic updater's block form. A .properties file takes a trailing comment as part of the value, so the marker brackets the line instead of sitting on it, and configparser still reads 10.1.1. Tags here have no v prefix, which include-v-in-tag: false preserves. The key is singular; the plural is silently dropped as an unknown key. No last-release-sha is needed, since 10.1.1 is reachable from main, and CHANGELOG.md is already in the format release-please writes, having come from standard-version. The ci.yml job moves into a reusable run_tests.yml that the release gate also calls. ci.yml was already pull_request-only, so no duplicate-run change here. --- .github/workflows/ci.yml | 33 +--- .github/workflows/initiate_release.yml | 48 ------ .github/workflows/pr_title.yml | 17 ++ .github/workflows/publish-new-version.yml | 83 ---------- .github/workflows/release.yml | 184 +++++++++++++++++++--- .github/workflows/run_tests.yml | 41 +++++ .release-please-manifest.json | 3 + CONTRIBUTING.md | 40 +++-- gradle.properties | 4 + release-please-config.json | 11 ++ 10 files changed, 268 insertions(+), 196 deletions(-) delete mode 100644 .github/workflows/initiate_release.yml create mode 100644 .github/workflows/pr_title.yml delete mode 100644 .github/workflows/publish-new-version.yml create mode 100644 .github/workflows/run_tests.yml create mode 100644 .release-please-manifest.json create mode 100644 release-please-config.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 58c23f50..f9b90d4e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,7 @@ name: Build on: [pull_request] -concurrency: +concurrency: group: ${{ github.workflow }}-${{ github.head_ref }} cancel-in-progress: true @@ -11,32 +11,5 @@ permissions: jobs: ci: - name: ๐Ÿงช Test & lint - environment: ci - runs-on: ubuntu-latest - steps: - - name: Check out code - uses: actions/checkout@v5.0.1 - with: - fetch-depth: 0 - -# - name: Commit message lint -# uses: wagoid/commitlint-github-action@v4 - - - name: Setup JDK 17 - uses: actions/setup-java@v5.1.0 - with: - distribution: 'corretto' - java-version: '17' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - - - name: Test - env: - STREAM_BASE_URL: ${{ vars.STREAM_BASE_URL }} - STREAM_API_KEY: ${{ vars.STREAM_API_KEY }} - STREAM_API_SECRET: ${{ secrets.STREAM_API_SECRET }} - run: | - ./gradlew spotlessCheck - ./gradlew build --info + uses: ./.github/workflows/run_tests.yml + secrets: inherit diff --git a/.github/workflows/initiate_release.yml b/.github/workflows/initiate_release.yml deleted file mode 100644 index 6db25a8a..00000000 --- a/.github/workflows/initiate_release.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Create release PR - -on: - workflow_dispatch: - inputs: - version: - description: "The new version number. Example: 1.40.1" - required: true - type: string - pattern: "^[0-9]+\\.[0-9]+\\.[0-9]+$" - -permissions: - contents: write - pull-requests: write - -jobs: - init_release: - name: ๐Ÿš€ Create release PR - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 # gives the changelog generator access to all previous commits - - - name: Update CHANGELOG.md, build.gradle and push release branch - env: - VERSION: ${{ github.event.inputs.version }} - run: | - npx --yes standard-version@9.3.2 --release-as "$VERSION" --skip.tag --skip.commit --tag-prefix= - echo "version=$VERSION" > gradle.properties - git config --global user.name 'github-actions' - git config --global user.email 'release@getstream.io' - git checkout -q -b "release-$VERSION" - git add CHANGELOG.md gradle.properties - git commit -am "chore(release): $VERSION" - git push -q -u origin "release-$VERSION" - - - name: Open pull request - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh pr create \ - -t "Release ${{ github.event.inputs.version }}" \ - -b "# :rocket: ${{ github.event.inputs.version }} - Make sure to use squash & merge when merging! - Once this is merged, another job will kick off automatically and publish the package. - # :memo: Changelog - $(cat CHANGELOG.md)" diff --git a/.github/workflows/pr_title.yml b/.github/workflows/pr_title.yml new file mode 100644 index 00000000..923683d8 --- /dev/null +++ b/.github/workflows/pr_title.yml @@ -0,0 +1,17 @@ +name: Lint PR title + +on: + pull_request: + types: [opened, edited, reopened, synchronize] + +permissions: + pull-requests: read + +jobs: + pr_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/publish-new-version.yml b/.github/workflows/publish-new-version.yml deleted file mode 100644 index 6d62a191..00000000 --- a/.github/workflows/publish-new-version.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: Publish New Version - -# Manual publish of the selected git ref to Maven Central. -# Same trigger as stream-chat-android: Actions โ†’ this workflow โ†’ Run workflow. -# Pick a branch in "Use workflow from", or pass `ref` to publish a different branch -# (needed for old lines like release-4.1.1-feed-counts that do not contain this file). -# -# Does not bump versions or merge to main. Publishes gradle.properties as-is. -on: - workflow_dispatch: - inputs: - ref: - description: "Branch or tag to publish. Leave empty to use the branch selected in Use workflow from." - required: false - type: string - default: "" - prerelease: - description: "Mark the GitHub release as a pre-release" - required: false - type: boolean - default: true - -concurrency: - group: release - cancel-in-progress: false - -permissions: - contents: write - -jobs: - publish: - name: ๐Ÿš€ Publish - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - ref: ${{ inputs.ref != '' && inputs.ref || github.ref }} - fetch-depth: 0 - - - name: Resolve version - run: | - PROP=$(grep '^version=' gradle.properties | cut -d'=' -f2) - if [ -z "$PROP" ]; then - echo "โŒ Could not read version from gradle.properties" - exit 1 - fi - echo "VERSION=$PROP" >> "$GITHUB_ENV" - echo "PUBLISH_SHA=$(git rev-parse HEAD)" >> "$GITHUB_ENV" - echo "Publishing $PROP from $(git rev-parse --abbrev-ref HEAD) @ $(git rev-parse --short HEAD)" - - - name: Setup JDK 17 - uses: actions/setup-java@v5.1.0 - with: - distribution: 'corretto' - java-version: '17' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - - - name: Publish to MavenCentral - run: | - ./gradlew -Pversion="$VERSION" publishToSonatype --no-daemon --max-workers 1 closeAndReleaseSonatypeStagingRepository - env: - STREAM_API_KEY: ${{ vars.STREAM_API_KEY }} - STREAM_API_SECRET: ${{ secrets.STREAM_API_SECRET }} - GPG_KEY_CONTENTS: ${{ secrets.GPG_KEY_CONTENTS }} - OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }} - OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} - SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }} - SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} - SIGNING_SECRET_KEY_RING_FILE: ${{ secrets.SIGNING_SECRET_KEY_RING_FILE }} - SONATYPE_STAGING_PROFILE_ID: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }} - - - name: Create GitHub release - uses: ncipollo/release-action@v1 - with: - tag: ${{ env.VERSION }} - commit: ${{ env.PUBLISH_SHA }} - name: ${{ env.VERSION }} - prerelease: ${{ inputs.prerelease }} - makeLatest: false - token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f70bb3e8..33600998 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,31 +1,175 @@ name: Release on: - pull_request: - types: [closed] + push: branches: - main + - '*.x' + workflow_dispatch: + inputs: + publish_tag: + description: 'Existing tag to (re)publish to Maven Central, e.g. 10.1.2. Leave empty for a normal release run.' + required: false + default: '' permissions: - contents: write + contents: read + +concurrency: + group: release-${{ github.ref_name }} + cancel-in-progress: false jobs: - Release: - name: ๐Ÿš€ Release - if: github.event.pull_request.merged && startsWith(github.head_ref, 'release-') + # Reversible half: keep the Release PR current. Stands down only while a release is + # already pending, because until that one is tagged there is no release commit to stop + # the walk at and it would propose the same commits again in a second Release PR. + release-pr: + name: Release PR + needs: detect + if: needs.detect.outputs.pending != 'true' + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: write + issues: write + pull-requests: write + steps: + - uses: googleapis/release-please-action@v4 + with: + config-file: release-please-config.json + manifest-file: .release-please-manifest.json + target-branch: ${{ github.ref_name }} + skip-github-release: true + + # The tag, the GitHub Release and the Maven Central push are irreversible, so the + # suite has to run before them, which means knowing a release is pending before the + # suite starts. The tag lands on the merged Release PR's merge commit while the suite + # runs on this workflow's own commit, so `ready` also requires those to be the same + # commit. They are, on the path that matters: the push of that merge. + detect: + name: Detect pending release + if: >- + (github.event_name == 'push' || inputs.publish_tag == '') && + (github.ref_name == 'main' || endsWith(github.ref_name, '.x')) + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + pull-requests: read + issues: read + outputs: + pending: ${{ steps.find.outputs.pending }} + ready: ${{ steps.find.outputs.ready }} + steps: + - name: Find a merged Release PR waiting to be tagged + id: find + env: + GH_TOKEN: ${{ github.token }} + BASE: ${{ github.ref_name }} + HEAD_SHA: ${{ github.sha }} + run: | + pending=false + ready=false + + # Query the label directly. Listing closed PRs and filtering client-side loses + # a release that has slipped past the first page, which reads as "nothing to + # release" and passes. Filter before picking, too: a hotfix branch can hold + # its own pending release, and taking the newest label match would drop this + # branch's release on every run until the other one clears. + nums="$(gh api "repos/${GITHUB_REPOSITORY}/issues" \ + -X GET -f state=closed -f labels='autorelease: pending' -f per_page=20 \ + --jq '.[] | select(.pull_request != null) | .number')" + + num="" + sha="" + for n in $nums; do + sha="$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${n}" \ + --jq 'select(.merged_at != null and .base.ref == env.BASE) | .merge_commit_sha // empty')" + if [ -n "$sha" ]; then + num="$n" + break + fi + done + + if [ -z "$sha" ]; then + echo "No pending release on ${BASE}." + elif [ "$sha" != "$HEAD_SHA" ]; then + # Reached when an earlier release run failed after the Release PR merged. + # Tagging $sha here would tag a tree this run never tested, and failing + # would redden every later push, so stand down and say why. + pending=true + echo "::warning::Release PR #${num} is still pending at ${sha}, which is not this run's commit ${HEAD_SHA}. Re-run the workflow run for ${sha} to finish that release." + else + pending=true + ready=true + echo "Pending release #${num} will be tagged at ${sha}." + fi + + { + echo "pending=${pending}" + echo "ready=${ready}" + } >> "$GITHUB_OUTPUT" + + tests: + name: Tests + needs: detect + if: needs.detect.outputs.ready == 'true' + uses: ./.github/workflows/run_tests.yml + secrets: inherit + + # Irreversible half. + release: + name: ๐Ÿš€ Tag and release + needs: [detect, tests] + if: needs.detect.outputs.ready == 'true' runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: write + issues: write + pull-requests: write + outputs: + release_created: ${{ steps.release.outputs.release_created }} + tag_name: ${{ steps.release.outputs.tag_name }} steps: - - uses: actions/checkout@v3 + - uses: googleapis/release-please-action@v4 + id: release with: - fetch-depth: 0 + config-file: release-please-config.json + manifest-file: .release-please-manifest.json + target-branch: ${{ github.ref_name }} + skip-github-pull-request: true + + # Chained rather than triggered on the release event, because a GitHub Release created + # with GITHUB_TOKEN starts no new workflow run. Also reachable on its own through + # workflow_dispatch with publish_tag, which is the recovery path once GitHub has + # retired the original run and "Re-run failed jobs" is gone. + publish: + name: ๐Ÿ“ฆ Publish to Maven Central + needs: release + if: >- + !cancelled() && + (inputs.publish_tag != '' || needs.release.outputs.release_created == 'true') + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: read + steps: + - name: Resolve tag + id: target + env: + PUBLISH_TAG: ${{ inputs.publish_tag }} + RELEASE_TAG: ${{ needs.release.outputs.tag_name }} + run: | + tag="${PUBLISH_TAG:-$RELEASE_TAG}" + echo "tag=${tag}" >> "$GITHUB_OUTPUT" - - uses: actions/github-script@v6 + - uses: actions/checkout@v5.0.1 with: - script: | - // Getting the release version from the PR source branch - // Source branch looks like this: release-1.0.0 - const version = context.payload.pull_request.head.ref.replace(/^release-/, '') - core.exportVariable('VERSION', version) + ref: ${{ steps.target.outputs.tag }} + # The Gradle build runs project code, and nothing here writes to the + # repository, so do not leave GITHUB_TOKEN in .git/config. + persist-credentials: false - name: Setup JDK 17 uses: actions/setup-java@v5.1.0 @@ -36,9 +180,7 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 - - name: Publish to MavenCentral - run: | - ./gradlew publishToSonatype --no-daemon --max-workers 1 closeAndReleaseSonatypeStagingRepository + - name: Publish to Maven Central env: STREAM_API_KEY: ${{ vars.STREAM_API_KEY }} STREAM_API_SECRET: ${{ secrets.STREAM_API_SECRET }} @@ -49,9 +191,5 @@ jobs: SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} SIGNING_SECRET_KEY_RING_FILE: ${{ secrets.SIGNING_SECRET_KEY_RING_FILE }} SONATYPE_STAGING_PROFILE_ID: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }} - - - name: Create release on GitHub - uses: ncipollo/release-action@v1 - with: - tag: ${{ env.VERSION }} - token: ${{ secrets.GITHUB_TOKEN }} + run: | + ./gradlew publishToSonatype --no-daemon --max-workers 1 closeAndReleaseSonatypeStagingRepository diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml new file mode 100644 index 00000000..edb9031b --- /dev/null +++ b/.github/workflows/run_tests.yml @@ -0,0 +1,41 @@ +name: _run-tests + +on: + workflow_call: + secrets: + STREAM_API_SECRET: + required: true + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + ci: + name: Build + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Check out code + uses: actions/checkout@v5.0.1 + + - name: Setup JDK 17 + uses: actions/setup-java@v5.1.0 + with: + distribution: 'corretto' + java-version: '17' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Test + env: + STREAM_BASE_URL: ${{ vars.STREAM_BASE_URL }} + STREAM_API_KEY: ${{ vars.STREAM_API_KEY }} + STREAM_API_SECRET: ${{ secrets.STREAM_API_SECRET }} + run: | + ./gradlew spotlessCheck + ./gradlew build --info diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 00000000..ef408f5b --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "10.1.1" +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1065603d..c9f62563 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -111,16 +111,32 @@ This repository follows a commit message convention in order to automatically ge ## Releasing a new version (for Stream developers) -In order to release new version you need to be a maintainer of the library. +Releases are driven by [release-please](https://github.com/googleapis/release-please). + +- Merge PRs to `main` with conventional-commit titles, using **Squash and merge**. The + title becomes the commit subject and decides the next version: `feat:` is a minor, + `fix:` and `perf:` are a patch, `feat!:` or `(scope)!:` is a major. Other types + (`chore`, `ci`, `docs`, `test`, `refactor`) ship nothing. This is new: the version used + to be typed by hand into the `initiate_release` job, which is gone. +- release-please keeps a Release PR open with the version bump in `gradle.properties` + and `CHANGELOG.md`. It is opened by `github-actions[bot]`, so approve it and run its + held checks like any other PR. Never edit the version by hand, and leave the + `x-release-please-start-version` comments around it in place; a `.properties` file + takes a trailing comment as part of the value, so the marker has to bracket the line. +- Merging the Release PR runs `spotlessCheck` and the build on that merge commit, which + is the commit the tag will point at. Only if that is green does the workflow create the + tag and the GitHub Release and publish to Maven Central. The order matters: a tag, a + GitHub Release and a Maven Central push cannot be withdrawn. + +Tags here have no `v` prefix (`10.1.1`, not `v10.1.1`), which `include-v-in-tag: false` +in `release-please-config.json` preserves. + +To retry a publish that failed after the release was tagged, use "Re-run failed jobs" on +that workflow run. Once GitHub has retired the run, dispatch `Release` from `main` with +`publish_tag` set to the tag, which builds and publishes that tag without touching +release-please. If the suite goes red after the Release PR merged, the release stays +pending and every later push logs a warning naming the commit to go back to. + +To force a specific version, type `Release-As: X.Y.Z` in the commit message box of the +squash dialog when merging a PR; the PR description is not copied there. -- Kick off a job called `initiate_release` ([link](https://github.com/GetStream/stream-sdk-java/actions/workflows/initiate_release.yml)). - -The job creates a pull request with the changelog. Check if it looks good. - -- Merge the pull request. - -Once the PR is merged, it automatically kicks off another job which will upload the Gem to RubyGems.org and creates a GitHub release. - -### Pre-releases - -Push a tag (e.g. `1.0.0-beta.1`), then go to **GitHub Releases โ†’ Draft a new release**, select the tag, check **"Set as a pre-release"**, and publish. The CI job will trigger automatically and publish to MavenCentral. diff --git a/gradle.properties b/gradle.properties index 4b3ef1cd..1eb3a06b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1,5 @@ +# A trailing comment would become part of the value in a .properties file, so the +# release-please marker has to bracket the line instead of sitting on it. +# x-release-please-start-version version=10.1.1 +# x-release-please-end diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 00000000..75ee5905 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "packages": { + ".": { + "release-type": "simple", + "include-component-in-tag": false, + "include-v-in-tag": false, + "extra-files": ["gradle.properties"] + } + } +} From 1ef6336b00a00a93c598805d40396888e4bf16ce Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Tue, 15 Sep 2026 16:04:06 +0200 Subject: [PATCH 2/4] ci: restore the ci environment on the test job Extracting the job into run_tests.yml dropped environment: ci from it. STREAM_API_SECRET, STREAM_API_KEY and STREAM_BASE_URL all live in that environment rather than at repo level, so secrets: inherit had nothing to pass and the call failed before any step ran with "Secret STREAM_API_SECRET is required, but not provided". The secret is also declared required: false, because an environment secret is resolved by the job at runtime rather than handed over at call time. --- .github/workflows/run_tests.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index edb9031b..d097e363 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -4,7 +4,9 @@ on: workflow_call: secrets: STREAM_API_SECRET: - required: true + # Lives in the ci environment, not at repo level, so it is not inheritable at + # call time; the job resolves it by declaring that environment below. + required: false concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -16,6 +18,7 @@ permissions: jobs: ci: name: Build + environment: ci runs-on: ubuntu-latest timeout-minutes: 30 steps: From fbb81df22b1761d9457c6fecd4c5346bc1fc6457 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Tue, 15 Sep 2026 16:10:18 +0200 Subject: [PATCH 3/4] ci: keep the test job named for the required status check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit main requires a status check called '๐Ÿงช Test & lint', which was this job's name before the extraction. Renaming it to Build meant that context would never report again, so every PR would block, including the Release PR release-please opens. A reusable workflow reports as ' / ', so the check becomes 'ci / ๐Ÿงช Test & lint' and the required context still has to be updated from the bare name at merge time. Keeping the name makes that a one-word change. --- .github/workflows/run_tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index d097e363..311da500 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -17,7 +17,9 @@ permissions: jobs: ci: - name: Build + # Keep this name: main requires the status check by name, and calling through a + # reusable workflow already prefixes it with the caller job id. + name: ๐Ÿงช Test & lint environment: ci runs-on: ubuntu-latest timeout-minutes: 30 From 30419f435f31e1aa8ef5de5d16c130eea197602c Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Tue, 15 Sep 2026 16:16:20 +0200 Subject: [PATCH 4/4] ci: re-run the Release PR half after a tag lands A push merged while a release run is in flight is gated out of release-pr by the pending label, and nothing re-runs that half once the tag exists, so those commits sat unreleased until the next unrelated push to main. --- .github/workflows/release.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 33600998..255a03ae 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -140,6 +140,28 @@ jobs: target-branch: ${{ github.ref_name }} skip-github-pull-request: true + # A push that lands while the release above is running is gated out of `release-pr`, + # and nothing re-runs that half once the tag exists, so those commits would sit + # unreleased until the next unrelated push. Run it again now that the walk has a + # release commit to stop at. + release-pr-followup: + name: Release PR (after tagging) + needs: release + if: needs.release.outputs.release_created == 'true' + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: write + issues: write + pull-requests: write + steps: + - uses: googleapis/release-please-action@v4 + with: + config-file: release-please-config.json + manifest-file: .release-please-manifest.json + target-branch: ${{ github.ref_name }} + skip-github-release: true + # Chained rather than triggered on the release event, because a GitHub Release created # with GITHUB_TOKEN starts no new workflow run. Also reachable on its own through # workflow_dispatch with publish_tag, which is the recovery path once GitHub has