Releasing¶
For maintainers. PDLt is published to PyPI as pdl-taskmaster by .github/workflows/release.yml, using trusted publishing: GitHub Actions proves its identity to PyPI with a short-lived OpenID Connect token, so no PyPI password or API token is stored in the repository or its secrets.
One-time setup¶
Both settings must name the same repository, workflow file and environment.
1. On PyPI (an owner of the pdl-taskmaster project): open the project's Manage → Publishing page (https://pypi.org/manage/project/pdl-taskmaster/settings/publishing/) and add a GitHub trusted publisher:
| Field | Value |
|---|---|
| Owner | paragon-ux |
| Repository name | PDLt-Test |
| Workflow name | release.yml |
| Environment name | pypi |
2. On GitHub (a repository admin): Settings → Environments → New environment, named pypi. Recommended protections:
- Required reviewers: yourself, so each upload waits for your approval after the tests and build pass.
- Deployment branches and tags: "Selected branches and tags", with a tag rule
v*.
No secrets are needed in the environment.
Each release¶
- Version. Set the same version in
VERSIONandsrc/pdl_taskmaster/__init__.py(__version__), following the existing scheme: a minor version for new features (2.5.1 to 2.6.0), a patch version for fixes only. -
Check locally, from a source checkout with the test extras installed:
-
Merge to
mainwith CI green. - Create the release: on GitHub, Releases → Draft a new release, tag
v<version>(for examplev2.6.0) onmain, and publish it. Or:gh release create v2.6.0 --target main --title "2.6.0" --generate-notes.
Publishing the release starts release.yml:
| Job | What it does |
|---|---|
tests |
The full CI workflow (ci.yml): the offline suite and integrity gate on Linux and Windows, Python 3.10 to 3.14, and the distribution build on each interpreter |
build |
Checks the tag is v + VERSION + __version__, builds the sdist and wheel once, runs twine check --strict, installs the wheel outside the repository and runs pdlt version, an empty headless session and the sandbox check, then uploads dist/ as an artifact |
publish |
In the pypi environment (and after your approval, if you set required reviewers), uploads exactly the built artifact to PyPI with pypa/gh-action-pypi-publish, which also attaches signed provenance attestations |
Only publish can request an identity token (id-token: write); every other job has read-only repository access.
If something fails¶
| Symptom | Fix |
|---|---|
build fails at "The tag matches the package version" |
The tag and the version files disagree. Delete the release and its tag, fix the version, merge, and release again. |
publish fails with invalid-publisher |
The PyPI trusted publisher does not match: check owner, repository, workflow file name and environment name against the table above. |
publish fails with "File already exists" |
That version is already on PyPI; versions cannot be re-uploaded. Bump the version. |
The documentation site¶
.github/workflows/docs.yml builds the site with Zensical and deploys it to GitHub Pages (paragon-ux.github.io/PDLt-Test) on every push to main that changes docs/, zensical.toml or README.md. Changes on other branches are not published until merged. Build it locally first with zensical build: it must report "No issues found".