From 17aa43ee1ea0937c536a8843ac0a7b120a5b8299 Mon Sep 17 00:00:00 2001 From: Elliot Taylor Date: Tue, 14 Jul 2026 11:11:14 +0200 Subject: [PATCH] Harden Release versioning: bump from the latest tag and guard against the remote The Release workflow bumped from the npm `latest` and guarded tag collisions with `git rev-parse` against a checkout that never fetched tags. When a publish lagged (npm behind the tags), every run recomputed the same version and the ineffective guard let the collision surface as a raw HTTP 422 from `gh release create`. Now the bump is computed from the highest of the latest git tag and the npm latest (tag = source of truth), so the next version is always strictly higher, and the guard checks `git ls-remote --tags origin` for a real answer. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/release.yml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 74417d1..e21c760 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: inputs: bump: - description: Semver bump to apply over the current npm latest + description: Semver bump to apply over the latest release type: choice default: patch options: @@ -28,6 +28,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup Node uses: actions/setup-node@v4 @@ -37,13 +39,18 @@ jobs: - name: Compute next version id: version run: | - current="$(npm view @patchstack/connect version 2>/dev/null || echo 0.0.0)" + latest_tag="$(git tag -l 'v*' --sort=-v:refname | head -n1 | sed 's/^v//')" + npm_latest="$(npm view @patchstack/connect version 2>/dev/null || echo 0.0.0)" + current="$(npx --yes semver "${latest_tag:-0.0.0}" "$npm_latest" | tail -n1)" next="$(npx --yes semver -i "${{ inputs.bump }}" "$current")" - echo "Current npm latest: $current" - echo "Next version: $next (bump: ${{ inputs.bump }})" - if git rev-parse "v$next" >/dev/null 2>&1; then - echo "::error::Tag v$next already exists." + echo "Latest git tag: ${latest_tag:-none}" + echo "npm latest: $npm_latest" + echo "Bumping from: $current" + echo "Next version: $next (bump: ${{ inputs.bump }})" + + if git ls-remote --tags origin "refs/tags/v$next" | grep -q .; then + echo "::error::Tag v$next already exists on origin." exit 1 fi