Releasing to PyPI
PSPSO is distributed through the existing pspso project on
PyPI. The one package contains the Python API,
CLI, FastAPI service and compiled dashboard.
Normal pushes and pull requests only verify the repository. Publishing is triggered by a non-prerelease GitHub Release and uses PyPI Trusted Publishing, so no long-lived PyPI token is stored in GitHub.
One-time repository setup
- Create or enable the
mainbranch and make it the default release branch. - In Settings → Pages, choose GitHub Actions as the Pages source. The
documentation workflow deploys https://ayhaidar.github.io/pspso/ after
documentation-related changes reach
main. - Create a GitHub environment named
pypi. Add required reviewers if release approval should be enforced in GitHub. - On PyPI, add a Trusted Publisher to the existing
pspsoproject with:
| Field | Value |
|---|---|
| Owner | ayhaidar |
| Repository | pspso |
| Workflow | publish.yml |
| Environment | pypi |
See the PyPI publisher setup guide and GitHub Pages workflow guide.
Prepare a release
- Update the version in
pyproject.tomlandfrontend/package.json, then refreshfrontend/package-lock.jsonanduv.lock. - Update the release notes, documentation and
RELEASE_CHECKLIST.md. - Build the frontend because its production assets are included in the wheel:
cd frontend
npm ci
npm run build
cd ..
- Run the release checks:
uv sync --locked --all-extras
uv run --no-sync ruff check .
uv run --no-sync ruff format --check .
uv run --no-sync mypy pspso
uv run --no-sync pytest
uv run --no-sync mkdocs build --strict
uv run --no-sync python scripts/build_release.py
uv run --no-sync twine check --strict dist/*.whl dist/*.tar.gz
The build script reads the version from pyproject.toml, creates a clean wheel
and source archive, and checks the bundled dashboard, commands, typing marker
and required source files. twine check --strict validates package metadata and
the README rendering used by PyPI.
Publish
- Merge the verified revision into
mainand wait for the verification and documentation workflows to pass. - Create a GitHub Release from the exact tag
v<version>, such asv1.0.0. Marking it as a prerelease prevents publication. - Publish the GitHub Release. The publishing workflow repeats the release gates, checks that the tag matches the package version, rebuilds the distributions from that tag and uploads them through Trusted Publishing.
- Install the released version in a fresh environment:
uv tool install "pspso==1.0.0"
pspso --version
pspso-dashboard --version
- Check the project description and files on PyPI, open the public documentation, start the dashboard, and complete the example in the CLI workflow.
PyPI versions cannot be replaced. If publication fails after accepting one distribution file, diagnose the workflow before creating a new version.