From c2ca4b998174329213608652154700e930a2b990 Mon Sep 17 00:00:00 2001 From: gok03 Date: Wed, 10 Jun 2026 19:17:39 +0530 Subject: [PATCH] ci(release): auto-create a GitHub Release on every v* tag push MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backfilled the five existing v0.1.0–v0.1.4 releases by hand earlier to fix the broken README badge — wire the workflow up so future tags don't need that manual step. Two changes: - `permissions.contents` raised from `read` to `write` so the workflow can post the Release. - New `Extract release notes from CHANGELOG.md` step pulls the section between `## []` and the next `## [` heading, so the body of the Release tracks CHANGELOG.md without copy-paste drift. Stubs to a short pointer line if the CHANGELOG doesn't have a matching section (emergency hotfix tagged before the promotion). - `softprops/action-gh-release@v2` consumes the file and creates the Release (not a draft, not a prerelease). Ordered after `Attest build provenance` so the Release only fires once the image has been pushed, signed, and attested — no orphan Release if a downstream signing step fails. --- .github/workflows/release.yaml | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 71b58ab..3d254bb 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -6,7 +6,7 @@ on: - "v*" permissions: - contents: read + contents: write # GitHub Release creation packages: write # GHCR push id-token: write # OIDC keyless cosign signing attestations: write # SLSA build provenance for the image @@ -62,3 +62,34 @@ jobs: subject-name: ghcr.io/refusehq/refuse subject-digest: ${{ steps.build.outputs.digest }} push-to-registry: true + + # Extract the matching section from CHANGELOG.md so the GitHub Release + # body matches the changelog without copy-paste drift. awk reads from the + # first `## []` heading through (but not including) the next + # `## [` heading. Falls back to a stub line if the version isn't in the + # CHANGELOG (e.g. emergency hotfix tagged before the changelog promotion). + - name: Extract release notes from CHANGELOG.md + id: notes + run: | + set -euo pipefail + v="${{ steps.meta.outputs.version }}" + awk -v v="$v" ' + $0 ~ "^## \\["v"\\]" { capture=1; next } + capture && /^## \[/ { exit } + capture { print } + ' CHANGELOG.md > /tmp/release-notes.md + if ! [ -s /tmp/release-notes.md ]; then + echo "No CHANGELOG.md section for v$v — emitting a stub" >&2 + printf 'Released v%s. See [CHANGELOG.md](./CHANGELOG.md).\n' "$v" \ + > /tmp/release-notes.md + fi + echo "path=/tmp/release-notes.md" >> "$GITHUB_OUTPUT" + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: v${{ steps.meta.outputs.version }} + name: v${{ steps.meta.outputs.version }} + body_path: ${{ steps.notes.outputs.path }} + draft: false + prerelease: false