From 430477f9c197ed964ddca124ffccb06249b83c38 Mon Sep 17 00:00:00 2001 From: Vincent Giersch Date: Fri, 11 Sep 2026 14:29:54 +0200 Subject: [PATCH] fix(release): tag with the v prefix, and publish a GitHub release Two things the release path got wrong, both visible on the repository page. The tag carried no prefix. Every tag in this repository, and every tag in api-reference, is v-prefixed, and the workflows introduced with the new pipeline created a bare one from the VERSION file. The tag list now mixes the two styles. tag-on-merge creates vX.Y.Z, release.yml triggers on it, and the assertion that the tag matches the packaged version compares against the tag with the v stripped, because the version inside the package never carries it. The four tags already published (2.0.0 and 2.0.1 here, 1.0.0 in the ruby and javascript clients) are left as they are: the registries record those versions and moving a published tag gains nothing. Nothing created a GitHub release, only a tag, so the Releases page still presented a version from 2018 as the latest one, which is what anyone browsing the repository sees first. release.yml now creates it, taking the notes from the CHANGELOG section for the version so the release says what changed. That needs contents: write, which the job did not have. A re-tag is a no-op now, not a failed release. npm error You cannot publish over the previously published versions: 1.0.0. Nothing was damaged: the published package is the same artifact and is still installable. But a red release on a version that is correctly out is the kind of failure people learn to ignore, and re-running a release, or changing the tag scheme as this just did, are both ordinary things to do. The publish step is skipped when the version is already in the registry, and the GitHub release step reports and moves on when the release exists rather than erroring on the create. --- .github/workflows/release.yml | 45 +++++++++++++++++++++++++++--- .github/workflows/tag-on-merge.yml | 4 ++- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3dd52ea..ca5c62a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,10 +4,10 @@ name: Release on: push: - tags: ['[0-9]+.[0-9]+.[0-9]+'] + tags: ['v[0-9]+.[0-9]+.[0-9]+'] permissions: - contents: read + contents: write # create the GitHub release id-token: write # OIDC for RubyGems trusted publishing (FR-021a) jobs: @@ -23,7 +23,9 @@ jobs: - name: The tag must match the packaged version run: | - TAG="${GITHUB_REF_NAME}" + # Every tag in this repository, and in api-reference, carries the v. The version + # inside the package never does, so the tag is compared with it stripped. + TAG="${GITHUB_REF_NAME#v}" PKG="$(ruby -Ilib -e "require 'flat_api/version'; print FlatApi::VERSION")" [ "$TAG" = "$PKG" ] || { echo "tag $TAG != VERSION $PKG"; exit 1; } @@ -37,7 +39,20 @@ jobs: - uses: rubygems/configure-rubygems-credentials@dc5a8d8553e6ee01fc26761a49e99e733d17954a # v2.1.0 # Attestations are generated by rubygems itself when it publishes over trusted publishing. - - run: gem push "flat_api-$(cat VERSION).gem" + - name: Skip the publish if this version is already on RubyGems + id: published + run: | + VERSION="${GITHUB_REF_NAME#v}" + if ( cd "$(mktemp -d)" && gem fetch flat_api --version "$VERSION" >/dev/null 2>&1 ); then + echo "flat_api $VERSION is already on RubyGems; nothing to publish." + echo "skip=true" >> "$GITHUB_OUTPUT" + else + echo "skip=false" >> "$GITHUB_OUTPUT" + fi + + - name: Publish to RubyGems (trusted publishing) + if: steps.published.outputs.skip != 'true' + run: gem push "flat_api-$(cat VERSION).gem" # The push is accepted asynchronously, so confirm the version is actually fetchable rather # than reporting a green release for a gem nobody can install yet. @@ -60,3 +75,25 @@ jobs: echo "flat_api $VERSION did not appear on RubyGems within five minutes. Last attempt:" ( cd "$WORK" && gem fetch flat_api --version "$VERSION" ) || true exit 1 + + # The tag alone left the repository's Releases page showing a version from years ago as + # "Latest", which is what anyone browsing the repository sees first. The notes come from the + # CHANGELOG section for this version, so the release says what changed rather than nothing. + - name: Publish the GitHub release + env: + GH_TOKEN: ${{ github.token }} + run: | + VERSION="${GITHUB_REF_NAME#v}" + NOTES="$(awk -v v="$VERSION" ' + $0 ~ "^## \\[?" v "\\]?" { found = 1; next } + found && /^## / { exit } + found { print } + ' CHANGELOG.md)" + [ -n "$NOTES" ] || NOTES="See CHANGELOG.md for $VERSION." + # Creating one that exists is an error, and a re-run of a release that already happened + # should be a no-op rather than a red build. + if gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then + echo "Release $GITHUB_REF_NAME already exists; nothing to do." + else + gh release create "$GITHUB_REF_NAME" --title "$GITHUB_REF_NAME" --notes "$NOTES" + fi diff --git a/.github/workflows/tag-on-merge.yml b/.github/workflows/tag-on-merge.yml index 477d6d6..f1bc04e 100644 --- a/.github/workflows/tag-on-merge.yml +++ b/.github/workflows/tag-on-merge.yml @@ -36,7 +36,9 @@ jobs: token: ${{ secrets.SDK_RELEASE_TOKEN }} - name: Tag the version if it is new run: | - VERSION="$(cat VERSION)" + # v-prefixed, matching every tag this repository and api-reference already carry. + # The version inside the package stays bare; only the git tag is prefixed. + VERSION="v$(cat VERSION)" if git rev-parse "$VERSION" >/dev/null 2>&1; then echo "Tag $VERSION already exists, nothing to do." exit 0