Conversation
Lets you cut a release from the Actions UI by picking patch/minor/major instead of tagging by hand. Computes the next semver from the latest v* tag, pushes it, and lets goreleaser run in the same job (so no PAT is needed — GITHUB_TOKEN-pushed tags don't trigger downstream workflows). The existing tag-push trigger still works. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 4 potential issues.
Bugbot Autofix prepared fixes for all 4 issues found in the latest run.
- ✅ Fixed: Reruns skip failed release tag
- Added an idempotency check that reuses an existing vMAJOR.MINOR.PATCH tag already pointing at HEAD instead of bumping again on rerun.
- ✅ Fixed: Branch guard runs too late
- Moved the master-only check to job-level
ifconditions on bothtestandgoreleaserso non-master dispatches never run any job with the workflow's contents:write token.
- Moved the master-only check to job-level
- ✅ Fixed: Tag parsing includes prereleases
- Tag listing now filters with
grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$'and sorts withsort -V, excluding prerelease/RC tags from the bump computation.
- Tag listing now filters with
- ✅ Fixed: Release dispatches can race
- Added a workflow-level
concurrency: { group: release, cancel-in-progress: false }so concurrent release runs serialize rather than racing on the same latest tag.
- Added a workflow-level
Or push these changes by commenting:
@cursor push 3b2cb23cc8
Preview (3b2cb23cc8)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -15,12 +15,18 @@
permissions:
contents: write
+concurrency:
+ group: release
+ cancel-in-progress: false
+
jobs:
test:
+ if: github.event_name != 'workflow_dispatch' || github.ref == 'refs/heads/master'
uses: ./.github/workflows/test.yaml
goreleaser:
needs: test
+ if: github.event_name != 'workflow_dispatch' || github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
@@ -30,12 +36,20 @@
if: github.event_name == 'workflow_dispatch'
run: |
set -euo pipefail
- if [ "${GITHUB_REF}" != "refs/heads/master" ]; then
- echo "workflow_dispatch must run from master (got ${GITHUB_REF})" >&2
- exit 1
+ git fetch --tags --force
+ # If a previous run already pushed a release tag for HEAD (e.g. it
+ # failed in goreleaser and is being retried), reuse it instead of
+ # bumping again and orphaning the original.
+ existing=$(git tag --points-at HEAD --list 'v*' \
+ | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \
+ | sort -V | tail -n1 || true)
+ if [ -n "${existing}" ]; then
+ echo "Reusing existing tag ${existing} on HEAD"
+ exit 0
fi
- git fetch --tags
- latest=$(git tag --list 'v*' --sort=-v:refname | head -n1)
+ latest=$(git tag --list 'v*' \
+ | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \
+ | sort -V | tail -n1 || true)
latest=${latest:-v0.0.0}
IFS='.' read -r major minor patch <<< "${latest#v}"
case "${{ inputs.bump }}" inYou can send follow-ups to the cloud agent here.
Reviewed by Cursor Bugbot for commit eae184a. Configure here.
| next="v${major}.${minor}.${patch}" | ||
| echo "Bumping ${latest} -> ${next}" | ||
| git tag "${next}" | ||
| git push origin "${next}" |
There was a problem hiding this comment.
Reruns skip failed release tag
Medium Severity
The workflow_dispatch release workflow pushes a new tag before goreleaser completes. If goreleaser fails, this orphaned tag becomes the latest for subsequent runs, leading to an unintended version bump and skipping the original target.
Triggered by team rule: abizer-code-review
Reviewed by Cursor Bugbot for commit eae184a. Configure here.
| set -euo pipefail | ||
| if [ "${GITHUB_REF}" != "refs/heads/master" ]; then | ||
| echo "workflow_dispatch must run from master (got ${GITHUB_REF})" >&2 | ||
| exit 1 |
There was a problem hiding this comment.
Branch guard runs too late
Medium Severity
workflow_dispatch on a non-master ref still reaches the reusable test job before this guard runs. Because the workflow grants contents: write, branch code can execute under a write-scoped checkout token even though dispatch releases are meant to be master-only.
Additional Locations (2)
Triggered by team rule: abizer-code-review
Reviewed by Cursor Bugbot for commit eae184a. Configure here.
| case "${{ inputs.bump }}" in | ||
| major) major=$((major+1)); minor=0; patch=0 ;; | ||
| minor) minor=$((minor+1)); patch=0 ;; | ||
| patch) patch=$((patch+1)) ;; |
There was a problem hiding this comment.
Tag parsing includes prereleases
Medium Severity
git tag --list 'v*' can select prerelease or malformed v* tags, but the bump logic assumes a numeric vX.Y.Z. A latest tag like v1.2.3-rc.1 can fail arithmetic or produce the wrong next release.
Reviewed by Cursor Bugbot for commit eae184a. Configure here.
| next="v${major}.${minor}.${patch}" | ||
| echo "Bumping ${latest} -> ${next}" | ||
| git tag "${next}" | ||
| git push origin "${next}" |
There was a problem hiding this comment.
Release dispatches can race
Medium Severity
workflow_dispatch has no release-level concurrency guard, so two manual runs can read the same latest tag and publish competing next versions from the same commit. Different bump inputs can both succeed, leaving duplicate releases for one HEAD.
Reviewed by Cursor Bugbot for commit eae184a. Configure here.



Summary
workflow_dispatchtorelease.ymlwith abump: patch|minor|majorchoice inputv*tag, tags HEAD, and pushes — then goreleaser runs in the same job (so no PAT needed;GITHUB_TOKEN-pushed tags don't trigger downstream workflows)push: tagspath is preserved for manualgit push origin vX.Y.ZmasterTest plan
masterwithbump=patchproduces the next tag and a goreleaser rungit tag vX.Y.Z && git push --tagsstill triggers the existing path🤖 Generated with Claude Code
Note
Low Risk
Low risk CI-only change, but it adds automated tag creation/pushing which could publish unintended releases if misused or run from the wrong branch (guarded to
master).Overview
Adds a manual
workflow_dispatchtrigger to thereleaseworkflow with abumpinput (patch|minor|major).When run manually, the workflow now computes the next
vX.Y.Zfrom the latest existingv*tag, creates and pushes the new tag (only if dispatch runs frommaster), and then proceeds with the existing GoReleaser release step; the originalpush-on-tag behavior remains unchanged.Reviewed by Cursor Bugbot for commit eae184a. Bugbot is set up for automated code reviews on this repo. Configure here.