From 21b2ca121f396aa301189f3efe94bc0a2f6dd713 Mon Sep 17 00:00:00 2001 From: Martin Storath Date: Fri, 8 May 2026 04:38:02 +0000 Subject: [PATCH] Auto-create GitHub Release on tag push (alongside PyPI publish) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tag-push currently uploads to PyPI but does not create a GitHub Release entry — the Releases page on github.com/mstorath/CSSD stays out of sync with PyPI. This step closes that gap by extracting the matching `## ` section from CHANGELOG.md (bracket-tolerant, accepts `## [1.0.1]` and `## 1.0.1`) and posting it to GitHub Releases via softprops/action-gh-release@v2, with all wheels and the sdist attached as assets. Implementation: - Job-level `permissions` block added (replaces top-level inherit). Keeps `id-token: write` for OIDC; adds `contents: write` for the release step. - `actions/checkout@v4` added so CHANGELOG.md is on disk. - An awk extractor; falls back to a tag-commits link if no matching heading or no CHANGELOG.md. - `generate_release_notes: true` appends an auto-generated PR/commit summary on top of the changelog body. - Idempotent: updates an existing Release for the tag rather than erroring, so manual pre-creation never blocks a re-run. See devcontainer reports/12-auto-github-release-pattern.md for the shared pattern and the rationale. --- .github/workflows/release.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 191aa0f..af2bb5d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -88,7 +88,12 @@ jobs: needs: [linux, macos, windows, sdist] if: startsWith(github.ref, 'refs/tags/v') environment: pypi + permissions: + id-token: write # required for OIDC trusted publishing + contents: write # required for the GitHub Release step below steps: + - name: Checkout (for CHANGELOG.md) + uses: actions/checkout@v4 - uses: actions/download-artifact@v4 with: path: dist @@ -96,3 +101,28 @@ jobs: - uses: pypa/gh-action-pypi-publish@release/v1 with: skip-existing: true + + - name: Extract release notes from CHANGELOG.md + # Pulls the section bounded by `## ` (bracket-tolerant) and + # the next `## ` heading. Falls back to a tag-commits link if + # the heading is missing or CHANGELOG.md doesn't exist. + run: | + VER="${GITHUB_REF_NAME#v}" + if [ -f CHANGELOG.md ]; then + awk -v ver="$VER" ' + $0 ~ "^## \\[?" ver "\\]?( |$)" { found=1; next } + found && /^## / { exit } + found { print } + ' CHANGELOG.md > release-notes.md + fi + [ -s release-notes.md ] || echo "See [tag commits](https://github.com/${GITHUB_REPOSITORY}/commits/${GITHUB_REF_NAME})." > release-notes.md + + - name: Create GitHub Release + # Idempotent: updates an existing Release for this tag rather + # than erroring, so manual pre-creation never blocks a re-run. + uses: softprops/action-gh-release@v2 + with: + name: ${{ github.ref_name }} + body_path: release-notes.md + generate_release_notes: true + files: dist/*