Skip to content

Release Process

This project follows semantic versioning and a reproducible, fail-closed release flow.

Current version is taken from [project].version in pyproject.toml.

Release tags must be vX.Y.Z and must match the package version. CHANGELOG.md must include a matching heading, for example ## [X.Y.Z] or ## vX.Y.Z.

Versioning policy

  • 0.x: fast iteration is allowed, but public schemas remain versioned.
  • 1.0+: incompatible public API, CLI, or artifact-contract changes require a new version and an explicit compatibility plan.

Release preconditions

Before any release tag is pushed:

  1. Configure a protected GitHub environment named pypi.
  2. Configure the PyPI project sdetkit with a GitHub Actions Trusted Publisher for:
  3. owner: sherif69-sa
  4. repository: DevS69-sdetkit
  5. workflow: release.yml
  6. environment: pypi
  7. Add required reviewers and deployment protection to the GitHub pypi environment.
  8. Do not configure or rely on a long-lived PYPI_API_TOKEN for this workflow.
  9. Confirm:
  10. [project].version is final;
  11. CHANGELOG.md has a matching release heading;
  12. the release tag is vX.Y.Z and matches the package version;
  13. current main and all required release-readiness PRs are green.

Missing or incorrect Trusted Publisher configuration is a release blocker. The workflow does not silently skip PyPI publication and continue to GitHub Release creation.

Manual dispatch accepts only an existing tag matching vX.Y.Z. The input is passed through the environment, validated before shell use, and never interpolated directly into a shell script.

Maintainer path

  1. Finalize release metadata:
  2. update [project].version in pyproject.toml;
  3. add a matching section in CHANGELOG.md;
  4. refresh release-candidate adoption and quality evidence.
  5. Run local preflight:
make release-preflight
  1. Generate the post-release verification plan and validate the install string:
make release-verify-plan
python scripts/release_verify_post_publish.py --assert-install-string
  1. Run focused repository proof:
python -m pre_commit run -a
COV_FAIL_UNDER=95 bash quality.sh cov
NO_MKDOCS_2_WARNING=1 python -m mkdocs build --strict
python -m build
python -m twine check dist/*
python -m check_wheel_contents --ignore W009 dist/*.whl
  1. Merge the release metadata PR only after required checks are green.
  2. Create and push the signed tag:
git tag -s vX.Y.Z -m "Release vX.Y.Z"
git push origin vX.Y.Z
  1. Approve the protected pypi environment deployment only after reviewing the exact tag, source SHA, distribution manifest, and Python-version qualification jobs.
  2. Watch .github/workflows/release.yml complete.
  3. Confirm the public PyPI metadata and distribution digests match the build manifest.
  4. Confirm the public PyPI install verification succeeded.
  5. Confirm the GitHub Release was created only after PyPI verification.

Workflow contract

The release workflow performs these ordered jobs:

  1. Build
  2. validate the requested tag before shell use;
  3. check out the existing tag;
  4. validate tag, package version, and changelog metadata;
  5. run coverage and strict docs proof;
  6. build the wheel and sdist exactly once;
  7. record SHA-256 digests in a distribution manifest.
  8. Qualify exact wheel
  9. download the immutable build artifact;
  10. install and exercise the exact wheel on Python 3.10, 3.11, and 3.12;
  11. run installed-wheel and canonical command contracts.
  12. Attest
  13. attach GitHub build provenance to the qualified distributions.
  14. Publish to PyPI
  15. enter the protected pypi environment;
  16. request a short-lived OIDC credential through Trusted Publishing;
  17. publish the same qualified files;
  18. generate PyPI publish attestations.
  19. Verify public publication
  20. wait for the exact version to appear on PyPI with bounded retries;
  21. compare every published filename and SHA-256 digest with the build manifest;
  22. install the exact version from the public PyPI index and verify metadata and CLI availability.
  23. Create GitHub Release
  24. create the GitHub Release only after successful PyPI verification;
  25. attach the exact published distributions and release diagnostics.

No job rebuilds the distributions after the build job.

What not to claim

Do not claim public availability, successful publication, attestation, or release completion until:

  • the exact-wheel qualification matrix is green;
  • Trusted Publishing completed successfully;
  • the public PyPI digest and install verification is green;
  • the GitHub Release exists and contains the same distribution files;
  • the tag, source SHA, and distribution manifest agree.

A prediction, workflow configuration, pending environment approval, or successful local build is not publication proof.

Post-release verification

The workflow performs automated public-index verification. A maintainer should also verify from a separate clean environment:

python -m venv .venv-release-verify
. .venv-release-verify/bin/activate
python -m pip install -U pip
python -m pip install --index-url https://pypi.org/simple/ sdetkit==X.Y.Z
python -m sdetkit --help
python -m pip show sdetkit

Success means:

  • the package resolves from public PyPI without a private index override;
  • the installed version equals X.Y.Z;
  • the CLI starts successfully;
  • PyPI contains the wheel and sdist with the expected hashes;
  • PyPI publish attestations are present;
  • the GitHub Release contains the exact qualified artifacts.

Record public verification evidence

After a real release is published and externally validated, add a factual record to docs/release-verification.md containing:

  • exact version, tag, and source SHA;
  • exact install and validation commands;
  • verifier OS, Python, and pip versions;
  • distribution hashes;
  • PyPI and GitHub Release references;
  • attestation verification result;
  • support path for failed installation.

Do not add a release-verification entry before publication and clean-room validation actually complete.

Optional TestPyPI rehearsal

A TestPyPI rehearsal must use a separate, explicitly configured Trusted Publisher and protected environment. It is not part of the default production release workflow and must not reuse production release authority.

Required release checklist

  • Version updated in pyproject.toml.
  • Matching version heading added in CHANGELOG.md.
  • Current product-delta and release-candidate evidence reviewed.
  • make release-preflight completed successfully.
  • Full quality, package, and docs proof completed.
  • GitHub pypi environment protection verified.
  • PyPI Trusted Publisher configuration verified.
  • Signed tag vX.Y.Z pushed.
  • Exact wheel qualified on Python 3.10, 3.11, and 3.12.
  • Trusted Publishing and attestations succeeded.
  • Public PyPI digest and installation verification succeeded.
  • GitHub Release created after PyPI verification.
  • External verification record added only after proof.