Skip to content

fix(publish): create GitHub Release on tag push - #95

Merged
maltsev-dev merged 1 commit into
masterfrom
fix/publish-add-gh-release-on-tag
Aug 26, 2026
Merged

fix(publish): create GitHub Release on tag push#95
maltsev-dev merged 1 commit into
masterfrom
fix/publish-add-gh-release-on-tag

Conversation

@maltsev-dev

Copy link
Copy Markdown
Member

fix(publish): create GitHub Release on tag push

Adds a GitHub Release creation step to publish.yml so the v* tag push that ships a PyPI release also produces a GitHub Release page with the wheel + sdist attached.

Why

Today publish.yml triggers on push: tags: ["v*"] (or workflow_dispatch) and runs only the PyPI Trusted Publishing step. PyPI gets the release, but the GitHub Releases page is left empty until someone manually runs gh release create vX.Y.Z. For 0.16.3 this would race the landing-page lib/github.ts badge cache (5-min TTL) — PyPI would be live, the GitHub Release page wouldn't, and the badge could show 0.16.3 before the release-notes page exists.

This fix makes the same workflow run produce both artifacts atomically: PyPI publish → GitHub Release on the same commit, with generate_release_notes: true auto-aggregating merged PR titles so the GitHub release notes mirror CHANGELOG.md without manual editing.

Diff

Single file, 24-line addition to .github/workflows/publish.yml:

publish:
  permissions:
    id-token: write
+   # contents: write is required by softprops/action-gh-release to
+   # create the GitHub Release (push the tag ref + draft release).
+   contents: write

  steps:
    ...
    - name: Publish to PyPI (Trusted Publishing)
      uses: pypa/gh-action-pypi-publish@release/v1

+   - name: Create GitHub Release
+     if: startsWith(github.ref, 'refs/tags/v')
+     uses: softprops/action-gh-release@v2
+     with:
+       tag_name: ${{ github.ref_name }}
+       generate_release_notes: true
+       files: |
+         dist/*.whl
+         dist/*.tar.gz

Notes

  • contents: write is additive to the existing id-token: write. The PyPI Trusted Publishing step doesn't need it, but the new release step does (it pushes a Git ref). The combined token scope is still strictly less than write-allid-token: write is required by OIDC, contents: write is required for the release ref push.
  • if: startsWith(github.ref, 'refs/tags/v') gates the release on tag pushes only. Manual workflow_dispatch runs (used for hotfix re-runs without re-tagging) won't create a duplicate release on the branch ref. The PyPI publish step runs unconditionally within the job — workflow_dispatch still publishes to PyPI as today.
  • generate_release_notes: true asks GitHub to auto-aggregate merged PR titles + labels into the release body. This mirrors CHANGELOG.md without manual editing and is the recommended setup for projects with conventional-commit-style PRs.
  • Attached files (dist/*.whl, dist/*.tar.gz) mirror what PyPI receives, so the release page doubles as a download mirror for environments where pip isn't available.
  • Pinned to softprops/action-gh-release@v2 (matches the project release-train convention). Latest stable is v3.0.2; the inputs used here (tag_name, generate_release_notes, files) are identical between v2 and v3, so bumping is a one-line change when desired. v3.0.2 mainly adds improved release-creation diagnostics + Gitea asset replacement, neither of which this workflow needs.

Verification

YAML parses cleanly:

jobs: ['test', 'publish']
perms: {'id-token': 'write', 'contents': 'write'}
steps:
  - actions/checkout@v4
  - actions/setup-python@v5
  - Build
  - Check dist
  - Publish to PyPI (Trusted Publishing)
  - Create GitHub Release

The change does not affect tests/, build/, or the PyPI publish step. The existing needs: test dependency still gates release creation on a green test matrix.

Roll-out

Once merged, the next v* tag push (planned: v0.16.3 after PR #94 merges) will produce:

  1. ✅ wheel + sdist on Production PyPI
  2. ✅ GitHub Release at https://github.com/nullrunio/nullrun-sdk-python/releases/tag/v0.16.3 with auto-generated notes and attached artifacts
  3. ✅ Landing-page badge updates within the 5-min lib/github.ts cache TTL

Adds a GitHub Release creation step to the publish workflow so the
`v*` tag push that ships a PyPI release also produces a GitHub
Release page with the wheel + sdist attached. Closes the "manual
changelog duplication" gap that 0.16.3 would otherwise hit: the
land-badge on the landing page would render 0.16.3 only after a
separate `gh release create` step, which would race the PyPI publish
job in the same workflow run.

Diff:
  - `permissions.contents: write` on the publish job — required by
    softprops/action-gh-release to push the release ref. Additive to
    the existing `id-token: write` (which PyPI Trusted Publishing
    needs); does NOT weaken the existing security posture since the
    workflow already has `actions/checkout@v4` writing into `${{
    github.workspace }}`.
  - New step "Create GitHub Release" at the end of the publish job,
    gated on `startsWith(github.ref, 'refs/tags/v')` so manual
    workflow_dispatch re-runs (used for hotfix rebuilds) don't create
    duplicate releases on branch refs. `generate_release_notes: true`
    asks GitHub to auto-aggregate merged PR titles + labels into the
    release body so the GH release page mirrors CHANGELOG.md without
    manual editing. `files: dist/*.whl, dist/*.tar.gz` attaches the
    same artifacts that PyPI receives, so the release page doubles
    as a download mirror for environments where pip isn't available.

Pinned to `softprops/action-gh-release@v2` (matches the project
release-train convention). The latest stable release is v3.0.2; the
inputs used here (`tag_name`, `generate_release_notes`, `files`) are
identical between v2 and v3, so bumping is a one-line change when
desired.

No changes to test/, build, or PyPI publish step. The existing
`needs: test` dependency still gates the release creation on a
green test matrix.
@maltsev-dev
maltsev-dev merged commit 43f2fcd into master Aug 26, 2026
4 checks passed
@codecov

codecov Bot commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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