release: cut a GitHub release for each image push
Assisted-by: Claude Opus 5 via Claude Code
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
change qvlzusnllnzsksqnrqttpzxysqkmpzvp
commit b08f569fc1e61faed73ad647ae9b8b820eb5c30e
author Alpha Chen <alpha@kejadlen.dev>
date
parent zoqtwspo
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 07a499b..4d1e027 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -26,7 +26,7 @@ jobs:
   release:
     runs-on: ubuntu-latest
     permissions:
-      contents: read  # checkout.
+      contents: write # checkout, and cut the release.
       packages: write # push image to GHCR.
 
     steps:
@@ -135,3 +135,37 @@ jobs:
           labels: ${{ steps.meta.outputs.labels }}
           cache-from: type=gha
           cache-to: type=gha,mode=max
+
+      - name: Create GitHub release
+        env:
+          GH_TOKEN: ${{ github.token }}
+          STEPS_VERSIONS_OUTPUTS_CADDY: ${{ steps.versions.outputs.caddy }}
+          STEPS_VERSIONS_OUTPUTS_CALVER: ${{ steps.versions.outputs.calver }}
+          STEPS_VERSIONS_OUTPUTS_TAILSCALE: ${{ steps.versions.outputs.tailscale }}
+          STEPS_VERSIONS_OUTPUTS_RATELIMIT: ${{ steps.versions.outputs.ratelimit }}
+          STEPS_META_OUTPUTS_TAGS: ${{ steps.meta.outputs.tags }}
+        run: |
+          set -euo pipefail
+
+          tag="v$STEPS_VERSIONS_OUTPUTS_CADDY-$STEPS_VERSIONS_OUTPUTS_CALVER"
+
+          # Indented code blocks instead of fences: backticks in --notes-file are
+          # fine, but these notes also go through echo.
+          {
+            echo "| Component | Version |"
+            echo "| --- | --- |"
+            echo "| Caddy | $STEPS_VERSIONS_OUTPUTS_CADDY |"
+            echo "| caddy-tailscale | $STEPS_VERSIONS_OUTPUTS_TAILSCALE |"
+            echo "| caddy-ratelimit | $STEPS_VERSIONS_OUTPUTS_RATELIMIT |"
+            echo
+            echo "Images pushed:"
+            echo
+            sed 's/^/    /' <<< "$STEPS_META_OUTPUTS_TAGS"
+          } > notes.md
+
+          # A same-day rebuild reuses the image tag, so reuse the release too.
+          if gh release view "$tag" > /dev/null 2>&1; then
+            gh release edit "$tag" --notes-file notes.md
+          else
+            gh release create "$tag" --target "$GITHUB_SHA" --notes-file notes.md
+          fi
diff --git a/README.md b/README.md
index 26d3e60..6647665 100644
--- a/README.md
+++ b/README.md
@@ -22,3 +22,7 @@ just release [caddy] [tailscale] [ratelimit]
 Blank versions default to the latest. A plugin version can be a tag, a commit
 hash, or a branch. The run summary and image labels record the plugin versions
 that went into the build.
+
+A successful run also cuts a GitHub release tagged `v<caddy>-<yyyy.mm.dd>`,
+like `v2.11.4-2026.09.14`, with the same versions and the image tags it
+pushed.