Skip to content

ci: add workflow_dispatch release trigger#7

Merged
abizer merged 1 commit intomasterfrom
nssh-7
May 6, 2026
Merged

ci: add workflow_dispatch release trigger#7
abizer merged 1 commit intomasterfrom
nssh-7

Conversation

@abizer
Copy link
Copy Markdown
Owner

@abizer abizer commented May 6, 2026

Summary

  • Adds workflow_dispatch to release.yml with a bump: patch|minor|major choice input
  • Computes the next semver from the latest v* 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)
  • Existing push: tags path is preserved for manual git push origin vX.Y.Z
  • Guarded so dispatch only runs from master

Test plan

  • Actions → release → Run workflow on master with bump=patch produces the next tag and a goreleaser run
  • Manual git tag vX.Y.Z && git push --tags still 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_dispatch trigger to the release workflow with a bump input (patch|minor|major).

When run manually, the workflow now computes the next vX.Y.Z from the latest existing v* tag, creates and pushes the new tag (only if dispatch runs from master), and then proceeds with the existing GoReleaser release step; the original push-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.

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>
@abizer abizer merged commit 0d0b525 into master May 6, 2026
1 of 2 checks passed
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 4 potential issues.

Fix All in Cursor

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 if conditions on both test and goreleaser so non-master dispatches never run any job with the workflow's contents:write token.
  • ✅ Fixed: Tag parsing includes prereleases
    • Tag listing now filters with grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' and sorts with sort -V, excluding prerelease/RC tags from the bump computation.
  • ✅ 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.

Create PR

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 }}" in

You 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}"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

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
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Fix in Cursor Fix in Web

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)) ;;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

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}"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit eae184a. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant