Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 20 additions & 16 deletions .github/workflows/auto-release.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
# Auto-tags and cuts a GitHub Release whenever pyproject.toml's version changes
# on main and the Python Test workflow has passed for that commit. Publishing
# a Release (types: [published]) is exactly what python-publish.yml already
# listens for, so this is the only piece needed to make merging to main (with
# a version bump) publish to PyPI, with no separate manual release step.
# Auto-tags, cuts a GitHub Release, and publishes to PyPI whenever
# pyproject.toml's version changes on main and the Python Test workflow has
# passed for that commit. No manual "cut a release" step needed.
#
# The release-creation step deliberately uses the RELEASE_TOKEN secret (a
# PAT), not the default GITHUB_TOKEN: GitHub Actions does not fire other
# workflows' triggers (release: published included) for events performed
# with the automatic GITHUB_TOKEN, to prevent recursive runs. A release
# created with a PAT is attributed to a real actor instead, so it triggers
# python-publish.yml normally. See README "Releasing" for one-time setup.
# The publish job calls python-publish.yml directly via workflow_call rather
# than relying on the release: published event to cascade into it: GitHub
# Actions doesn't fire other workflows' triggers for events performed with
# the automatic GITHUB_TOKEN (anti-recursion safeguard), so a release created
# here wouldn't otherwise trigger it. Calling the job directly sidesteps that
# entirely -- no PAT/secret needed, since it's one run, not two.

name: Auto Release

Expand All @@ -30,6 +28,8 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: write
outputs:
released: ${{ steps.check.outputs.exists == 'false' }}
steps:
- uses: actions/checkout@v4
with:
Expand All @@ -55,13 +55,17 @@ jobs:
- name: Create tag and GitHub release
if: steps.check.outputs.exists == 'false'
env:
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
GH_TOKEN: ${{ github.token }}
run: |
if [ -z "$GH_TOKEN" ]; then
echo "::error::RELEASE_TOKEN repo secret is not set (needed so this release triggers python-publish.yml -- see README 'Releasing')."
exit 1
fi
gh release create "v${{ steps.version.outputs.version }}" \
--title "v${{ steps.version.outputs.version }}" \
--target "${{ github.event.workflow_run.head_sha }}" \
--generate-notes

publish:
needs: release
if: needs.release.outputs.released == 'true'
permissions:
id-token: write
contents: read
uses: ./.github/workflows/python-publish.yml
1 change: 1 addition & 0 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ on:
release:
types: [published]
workflow_dispatch:
workflow_call:

jobs:
deploy:
Expand Down
32 changes: 14 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,21 +300,17 @@ async with pool.connection() as con:
Bump `version` in `pyproject.toml` as part of your PR, same as any other
change. Once that PR merges to `main` and the `Python Test` workflow passes
for that commit, `.github/workflows/auto-release.yml` automatically tags it
`vX.Y.Z` and cuts a GitHub Release (skipping if that version was already
released, e.g. a merge that didn't touch the version) — no manual release
step needed. Publishing a Release is what `.github/workflows/python-publish.yml`
already listens for, so the new release then builds and publishes to PyPI
via trusted (OIDC) publishing automatically.

`workflow_dispatch` on `python-publish.yml` still works as a manual
fallback if you ever need to re-publish a version without going through a
fresh tag/release.

**One-time setup:** `auto-release.yml` needs a `RELEASE_TOKEN` repository
secret — a PAT (classic, `repo` scope, or fine-grained with this repo's
Contents: Read and write) belonging to someone with write access. This is
required because GitHub Actions doesn't fire other workflows' triggers
(`release: published` included) for a release created with the automatic
`GITHUB_TOKEN`, to prevent recursive runs — a release created with a PAT is
attributed to a real actor instead, so it triggers `python-publish.yml`
normally. Add it under Settings → Secrets and variables → Actions.
`vX.Y.Z`, cuts a GitHub Release (skipping if that version was already
released, e.g. a merge that didn't touch the version), and publishes to
PyPI via trusted (OIDC) publishing — no manual release step, and no extra
secret to configure. It calls `python-publish.yml`'s `deploy` job directly
(`workflow_call`) rather than relying on the release it just created to
trigger that workflow on its own — GitHub Actions doesn't fire other
workflows' triggers for events performed with the automatic `GITHUB_TOKEN`,
so a manually-created-via-Action release wouldn't otherwise cascade into a
publish; calling the job directly sidesteps that instead of working around
it with a PAT.

`workflow_dispatch` (or an actual GitHub UI release) on `python-publish.yml`
still works as a manual fallback if you ever need to re-publish a version
without going through `auto-release.yml`.
Loading