Version source
project.version in pyproject.toml is the only version this repository
declares. uv version --bump rewrites it and re-locks uv.lock.
ksef2.__version__ reads installed distribution metadata, so an installed SDK
reports the version it was installed as and cannot drift from the declaration.
Check repository setup
Confirm these settings with a repository administrator:
- Protect
mainwith required PR review and CI checks. Merging a release is not authorization to publish; pushing the tag is. - Keep both tag rulesets.
Release tag creationallows only repository administrators to createrefs/tags/v*, andImmutable release tagsrejects updating or deleting them. The publish steps below therefore need administrator rights. - Keep the
pypienvironment's required reviewers and deployment rules. That approval applies to the upload job after integration tests pass. - Configure the PyPI trusted publisher for
stacking-hq/ksef2, workflowpublish.yml, and environmentpypi. The upload uses OIDC, so noPYPI_TOKENor personal access token is involved. - Retain the integration credentials
KSEF_TEST_SUBJECT_NIP,KSEF_TEST_PERSON_NIP, andKSEF_TEST_PERSON_PESEL.
Bump and document
just bump patch # or minor, or major
just changelog-seed # commits since the previous tag, one bullet per line- Edit
CHANGELOG.md. Start the new section with## vX.Y.Z (YYYY-MM-DD)at the top of the file and rewrite the seeded bullets for people who upgrade.scripts/verify_release.pyfails the publish run when that heading is absent. - Run
just release-check. - Open a PR targeting
main. A release changespyproject.toml,uv.lock, andCHANGELOG.md. Review it like any other change, then merge.
Merging publishes nothing.
Publish
just tag 0.21.1just tag refuses when the requested version does not match project.version,
then creates and pushes the annotated tag. Tags are immutable, so check the
version and the commit before pushing.
Pushing vX.Y.Z starts Publish to PyPI:
flowchart LR
B["just bump"] --> P[pyproject.toml and uv.lock]
C[CHANGELOG section] --> PR[reviewed PR]
P --> PR
PR --> M[merge to main]
M --> T["just tag: admin pushes vX.Y.Z"]
T --> I[KSeF TEST integration]
I --> A[pypi approval]
A --> U[release-check, artifact verify, smoke test on 3.12-3.14, upload]Approve the pypi deployment when prompted, then confirm the upload before
announcing anything:
gh run list --workflow=publish.yml --limit 3
gh run watch RUN_IDCreate the GitHub Release only after the upload succeeded, so notes never announce a version that is not installable:
just release 0.21.1just release extracts the ## vX.Y.Z section of CHANGELOG.md, fails when the
section is missing, and passes it to gh release create as the release body. The
changelog section is the source of truth because it is the only release text that
passes review; the GitHub body is derived from it instead of written a second
time.
Publishing does not deploy the documentation. The ksef2-docs site builds from
the latest release tag on a daily schedule, so wait for that run or start the
Docs workflow in stacking-hq/ksef2-docs by hand to publish the new release's
pages now.
Recover a failed release
Never delete, move, or overwrite a release tag. The rulesets reject it, and PyPI rejects a second upload of the same version.
-
Before the tag push, fix
pyproject.toml,uv.lock, orCHANGELOG.mdin a new reviewed PR. A failure before tagging has no side effects. -
If the tag exists and a job failed, rerun the failed jobs of that Publish to PyPI run. The
pypiapproval and the release checks still apply. -
If the tag exists but no run started, dispatch the workflow at the tag. This is the only reason manual dispatch exists, and it runs the same checks against the same immutable tag:
gh workflow run publish.yml --repo stacking-hq/ksef2 --ref v0.21.1bash -
If the upload may have succeeded, inspect PyPI and the run logs before any retry. Code changes after a successful upload need a new release with a higher version.
Concurrent publish runs for the same ref are serialized, but a duplicate run can still attempt an upload. Check existing runs before retrying.
Check the release tooling without publishing
uv run pytest tests/unit/test_verify_release.py -qThe test builds a temporary tree with a fake pyproject.toml, changelog, wheel,
and sdist, then confirms scripts/verify_release.py accepts a matching tag and
reports both a tag that disagrees with project.version and a wheel whose
METADATA disagrees.
