refactor(release): simplify bumps and add graduate

Amolith created

- Consolidated prerelease logic into a case statement
- Added 'graduate' option when current version is prerelease
- Now uses svu's built-in prerelease flag with user-provided suffix
- When graduating, llm-tag generates changelog from last stable tag

Assisted-by: Claude Sonnet 4.5 via Crush

Change summary

Taskfile.yaml | 76 +++++++++++++---------------------------------------
1 file changed, 19 insertions(+), 57 deletions(-)

Detailed changes

Taskfile.yaml 🔗

@@ -98,66 +98,23 @@ tasks:
     desc: Interactive release workflow
     vars:
       BUMP:
-        sh: gum choose "major" "minor" "patch" "prerelease"
-      CURRENT_VERSION:
-        sh: git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0"
-      IS_CURRENT_PRERELEASE:
         sh: |
-          current="{{.CURRENT_VERSION}}"
-          if echo "$current" | grep -qE '\-[a-zA-Z]+\.[0-9]+$'; then
-            echo "yes"
-          else
-            echo "no"
-          fi
-      IS_PRERELEASE:
-        sh: |
-          if [ "{{.BUMP}}" = "prerelease" ]; then
-            echo "yes"
-          else
-            gum confirm "Create pre-release?" && echo "yes" || echo "no"
-          fi
-      PRERELEASE_SUFFIX:
-        sh: |
-          if [ "{{.BUMP}}" = "prerelease" ] && [ "{{.IS_CURRENT_PRERELEASE}}" = "yes" ]; then
-            # Extract suffix from current version (e.g., v1.2.3-beta.0 -> beta)
-            echo "{{.CURRENT_VERSION}}" | sed -E 's/.*-([a-zA-Z]+)\.[0-9]+$/\1/'
-          elif [ "{{.IS_PRERELEASE}}" = "yes" ]; then
-            gum input --placeholder "Enter pre-release suffix (e.g., beta, rc)"
-          fi
-      BASE_NEXT:
-        sh: |
-          if [ "{{.BUMP}}" = "prerelease" ] && [ "{{.IS_CURRENT_PRERELEASE}}" = "yes" ]; then
-            # Extract base version from current prerelease (e.g., v1.2.3-beta.0 -> v1.2.3)
-            echo "{{.CURRENT_VERSION}}" | sed -E 's/-[a-zA-Z]+\.[0-9]+$//'
-          else
-            svu {{.BUMP}}
-          fi
-      SUFFIX_VERSION:
-        sh: |
-          if [ "{{.IS_PRERELEASE}}" = "yes" ] && [ -n "{{.PRERELEASE_SUFFIX}}" ]; then
-            if [ "{{.BUMP}}" = "prerelease" ] && [ "{{.IS_CURRENT_PRERELEASE}}" = "yes" ]; then
-              # Increment the current prerelease number
-              current_num=$(echo "{{.CURRENT_VERSION}}" | sed -E 's/.*-[a-zA-Z]+\.([0-9]+)$/\1/')
-              echo $((current_num + 1))
-            else
-              # Find existing tags with this suffix and get the highest version number
-              highest=$(git tag -l "{{.BASE_NEXT}}-{{.PRERELEASE_SUFFIX}}.*" | \
-                sed 's/.*-{{.PRERELEASE_SUFFIX}}\.//' | \
-                sort -n | tail -1)
-              if [ -n "$highest" ]; then
-                echo $((highest + 1))
-              else
-                echo 0
-              fi
-            fi
+          opts="major minor patch prerelease"
+          if git describe --tags --abbrev=0 2>/dev/null | grep -qE '\-[a-zA-Z]+\.[0-9]+$'; then
+            opts="$opts graduate"
           fi
+          gum choose $opts
       NEXT:
         sh: |
-          if [ "{{.IS_PRERELEASE}}" = "yes" ] && [ -n "{{.PRERELEASE_SUFFIX}}" ]; then
-            echo "{{.BASE_NEXT}}-{{.PRERELEASE_SUFFIX}}.{{.SUFFIX_VERSION}}"
-          else
-            echo "{{.BASE_NEXT}}"
-          fi
+          case "{{.BUMP}}" in
+            graduate) svu next ;;
+            prerelease)
+              suffix=$(gum input --placeholder "Suffix (beta, rc, etc.)")
+              svu prerelease --pre-release "$suffix" ;;
+            *) svu {{.BUMP}} ;;
+          esac
+      LAST_STABLE:
+        sh: git tag -l | grep -v '\-' | sort -V | tail -n 1
     prompt: "Release {{.NEXT}}?"
     preconditions:
       - sh: '[ $(git symbolic-ref --short HEAD) = "main" ] || [ $(git symbolic-ref --short HEAD) = "dev" ]'
@@ -165,7 +122,12 @@ tasks:
       - sh: "[ $(git status --porcelain=2 | wc -l) = 0 ]"
         msg: "Git is dirty"
     cmds:
-      - llm-tag {{.NEXT}}
+      - |
+        if [ "{{.BUMP}}" = "graduate" ]; then
+          llm-tag -b {{.LAST_STABLE}} {{.NEXT}}
+        else
+          llm-tag {{.NEXT}}
+        fi
       - git push soft {{.NEXT}}
       - go list -m git.secluded.site/formatted-commit@{{.NEXT}} > /dev/null
       - echo "Released {{.NEXT}} and notified module proxy"