Skip to content

ci(release): auto-create GitHub Release after PyPI publish#57

Merged
amavashev merged 1 commit into
mainfrom
chore/auto-create-github-release
May 6, 2026
Merged

ci(release): auto-create GitHub Release after PyPI publish#57
amavashev merged 1 commit into
mainfrom
chore/auto-create-github-release

Conversation

@amavashev
Copy link
Copy Markdown
Contributor

@amavashev amavashev commented May 6, 2026

Summary

Adds a create-release job to python-publish.yml that runs after publish-to-pypi succeeds and creates a GitHub Release with body extracted from the corresponding CHANGELOG.md section.

Eliminates the manual gh release create step every release. v0.4.1 had to be created manually because the workflow only handled PyPI publish; this PR closes that loop.

How it works

  1. Tag push (v*) triggers the workflow as before — buildpublish-to-pypi.
  2. New: create-release runs after PyPI publish succeeds (only on tag push, not on manual workflow_dispatch).
  3. Extracts the CHANGELOG section for the version using a portable awk script (string functions, no regex escape issues across awk variants).
  4. Calls softprops/action-gh-release@v3.0.0 with the extracted body.

Tested locally

Scenario Result
v0.4.1 (matches CHANGELOG entry) Clean extraction — body contains just the section between ## [0.4.1] and ## [0.4.0], no heading bleed
v9.9.9 (no matching CHANGELOG entry) Falls back to "Release v9.9.9. See commit history for changes." — does not fail the job

Edge cases handled

  • Missing CHANGELOG entry → fallback body, warning log line, job succeeds.
  • Prerelease versions (v0.5.0-rc.1) → auto-detected via contains(github.ref_name, '-'), marked as prerelease in GitHub.
  • Manual workflow_dispatchcreate-release skipped (only runs on tag push).

Permissions

  • Default contents: read preserved at workflow level.
  • contents: write granted only on the create-release job.

Action SHAs (pinned per the existing convention)

  • softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda (v3.0.0, latest stable)
  • actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd (v6, matches existing jobs)

Test plan

  • Merge this PR.
  • Verify it runs cleanly on the next release (the next v* tag push). The first real exercise will be whatever 0.4.2 or 0.5.0 ships next.
  • If you want to test before the next real release: cut a v0.4.2-test.1 prerelease tag → workflow should publish to PyPI and create a prerelease GitHub Release. Yank from PyPI after if needed.

After this lands

Future releases collapse to one step: bump version + CHANGELOG entry on a PR, merge, then git tag vX.Y.Z && git push origin vX.Y.Z. PyPI + GitHub Release both happen automatically.

Adds a `create-release` job to `python-publish.yml` that runs after
`publish-to-pypi` succeeds and creates a GitHub Release with body
extracted from the corresponding CHANGELOG.md section.

Eliminates the manual `gh release create` step every release. Previously,
v0.4.0 → v0.4.1 each required a separate manual release-creation pass
after the tag-triggered PyPI publish.

Behavior:
- Triggered by tag push only (not manual workflow_dispatch republishes).
- Extracts the CHANGELOG section between `## [VERSION]` and the next
  `## [` heading using a portable string-based awk script (no regex
  escaping issues across awk variants).
- If no CHANGELOG entry is found for the version, falls back to a generic
  "see commit history" body — does not fail the job.
- Title is the tag name (e.g. `v0.4.1`); the descriptive suffix on prior
  releases ("v0.4.0 — Dynamic subject and action fields...") is convention,
  not required, and the user can edit titles after the fact.
- `prerelease: ${{ contains(github.ref_name, '-') }}` flags any tag with
  a hyphen (e.g. `v0.5.0-rc.1`) as prerelease automatically.

Pinned action SHAs:
- softprops/action-gh-release@b430933... (v3.0.0)
- actions/checkout@de0fac2... (v6, matches existing job)

Permissions:
- `contents: write` on this job only; default `contents: read` preserved
  for the workflow-level minimum.

Tested locally:
- Successful extraction for v0.4.1 produces clean body (CHANGELOG section
  without heading or next-version boundary).
- Missing version (e.g. v9.9.9) takes the fallback path without erroring.

This means future releases will be one-step: `git tag vX.Y.Z` + `git
push origin vX.Y.Z` and the workflow handles both PyPI publish and
GitHub Release creation.
@amavashev amavashev enabled auto-merge (squash) May 6, 2026 18:24
@amavashev amavashev disabled auto-merge May 6, 2026 18:26
@amavashev amavashev merged commit c0b3c7a into main May 6, 2026
7 checks passed
@amavashev amavashev deleted the chore/auto-create-github-release branch May 6, 2026 18:26
@amavashev amavashev restored the chore/auto-create-github-release branch May 6, 2026 18:34
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