Release Process¶
This document outlines the steps to release a new version of azure-functions-durable-graph to PyPI and update the changelog using the existing Makefile and Hatch-based workflows.
The primary release path is GitHub Actions with PyPI trusted publishing (no PyPI tokens required). The legacy ~/.pypirc flow is kept as a fallback below.
Publish to PyPI with GitHub Actions (primary)¶
The .github/workflows/publish-pypi.yml workflow builds and uploads the distribution to PyPI on every v* tag push (or on demand via workflow_dispatch). It uses PyPI trusted publishing over OIDC, so no PyPI API token is stored as a secret.
Trusted publisher configuration¶
PyPI authorizes the upload by matching the OIDC claims presented by GitHub Actions against a trusted publisher registered on the PyPI project. The PyPI publisher config must use these exact values:
| Field on PyPI publisher form | Value |
|---|---|
| PyPI project | azure-functions-durable-graph |
| Owner | yeongseon |
| Repository name | azure-functions-durable-graph-python |
| Workflow filename | publish-pypi.yml |
| Environment name | pypi |
Notes:
- Workflow filename is the file under
.github/workflows/(publish-pypi.yml), not the workflow display name (Publish to PyPI). Entering the display name will not match. - Repository name is the GitHub repository slug (
azure-functions-durable-graph-pythonwith the-pythonsuffix from the toolkit-wide rename), not the PyPI project name (azure-functions-durable-graph) and not the Python import name (azure_functions_durable_graph). - Environment name matches
environment: pypideclared on thebuild-and-publishjob in the workflow. Renaming that environment requires updating the PyPI publisher record. - Enter all values exactly as shown; mismatches in repository name, workflow filename, environment, or project name will cause
invalid-publisherat upload time.
To register the publisher on PyPI:
- If the PyPI project
azure-functions-durable-graphalready exists, open the project page on PyPI → Manage → Publishing → Add a new publisher and enter the values above. - If the PyPI project does not exist yet (first release), register a pending publisher under the maintainer's PyPI account with the same values; the first successful upload will then create the project. A pending publisher does not reserve the project name on PyPI — anyone else can still register the project before the first publish, so cut the first release promptly.
Re-run a failed publish¶
After updating the trusted publisher in PyPI, the existing tag can be re-published without cutting a new version:
- From the GitHub Actions UI, open the failed
Publish to PyPIrun and click Re-run failed jobs, or - Trigger the workflow via
workflow_dispatchwith the existing tag as input (for examplev0.3.0); the workflow checks out that tag and republishes.
Confirm the run succeeds and the new version appears at https://pypi.org/project/azure-functions-durable-graph/.
Troubleshooting trusted publishing¶
invalid-publisher: valid token, but no corresponding publisher¶
PyPI received a valid OIDC token from GitHub but found no trusted publisher record whose claims match. Typical causes:
- The repository was renamed (for example, the toolkit-wide
-pythonsuffix migration) and the publisher record still references the old repository name. - The
environment:value on the workflow job changed and the publisher record references the old environment name. - The workflow filename on the publisher record is wrong — for example, the workflow display name (
Publish to PyPI) was entered instead of the filename (publish-pypi.yml). - The publisher was registered on a different PyPI project (a typo in the project name, or a
pendingpublisher under the wrong account).
To recover:
- Open the PyPI project page for
azure-functions-durable-graph→ Manage → Publishing, or the maintainer's account-level Pending publishers page if the project does not yet exist. - Add or update a publisher with the values from the table above (Owner
yeongseon, Repository nameazure-functions-durable-graph-python, Workflow filenamepublish-pypi.yml, Environmentpypi). - Re-run the failed
Publish to PyPIworkflow as described under Re-run a failed publish.
invalid-publisher is a PyPI-side configuration error, not a missing GitHub secret. The workflow uses OIDC and does not read any PYPI_* repository secret.
Step 1: Bump Version and Generate Changelog¶
Use Makefile targets to bump the version and update the changelog:
make release-patch # Patch release (e.g., v0.10.0 → v0.10.1)
make release-minor # Minor release (e.g., v0.10.1 → v0.11.0)
make release-major # Major release (e.g., v0.11.0 → v1.0.0)
Each command will:
- Update the version in
src/azure_functions_durable_graph/__init__.py - Generate or update
CHANGELOG.mdviagit-cliff - Commit the version bump and changelog
- Create a Git tag (e.g.,
v0.11.0) and push tomain
Make sure your
mainbranch is up-to-date before running these commands.
Changelog Generation¶
The changelog is generated automatically by git-cliff from conventional commit messages.
Configuration¶
cliff.toml— defines commit grouping, categories, and output formatMakefile—make changelogrunsgit-cliff -o CHANGELOG.md
Commit Message Convention¶
Follow Conventional Commits for proper changelog grouping:
| Prefix | Changelog Category |
|---|---|
feat: |
Features |
fix: |
Bug Fixes |
docs: |
Documentation |
refactor: |
Refactor |
style: |
Styling |
test: |
Testing |
perf: |
Performance |
ci: / chore: |
Miscellaneous Tasks |
build: |
Other |
Use scopes for more context: fix(openapi): preserve explicit 200 response
Manual Changelog Regeneration¶
make changelog # Regenerate CHANGELOG.md from all tags
make commit-changelog # Stage and commit the updated changelog
Step 2: Build and Test the Package¶
To test the local build:
Legacy fallback: local publish with ~/.pypirc¶
Cutting a release locally is only used as a fallback when the GitHub Actions workflow cannot run. Prefer the trusted publishing flow above.
Step 3: Publish to PyPI¶
- Uses
hatch publishunder the hood - Relies on
~/.pypircfor authentication (must contain PyPI token)
Step 4: (Optional) Publish to TestPyPI¶
To install from TestPyPI:
Summary of Makefile Commands¶
| Task | Command |
|---|---|
| Version bump + changelog | make release-patch / release-minor / release-major |
| Build distributions | make build |
| Publish to PyPI | make publish-pypi |
| Publish to TestPyPI | make publish-test |
| Regenerate changelog only | make changelog |
| Show current version | make version |