Release Management
What you'll do
Cut, tag, document, build, and publish a Craik release. Every release
must be installable, documented, and recoverable — 0.x.0 is not a
license to skip discipline.
0.x.0 MVP, not 1.0.0.
The 0.x.0 series can still change contracts between minor releases,
but each published release must pass the same packaging, docs,
quality, and changelog gates as a stable line.
Release cadence
0.x.00.x.y1.0.0Tag Policy
Release tags use vMAJOR.MINOR.PATCH — e.g. v0.1.0 — and must be
signed annotated tags. The embedded tag signature is the release
integrity source of truth; the GitHub Release also carries the public
release signing key as an operator convenience for verification.
- Update
pyproject.toml,src/craik/init.py, anddocs/package.json. - Move relevant
CHANGELOG.mdentries fromUnreleasedinto the target version section. - Run package, docs, quality, and version checks.
- Open a release PR that links the completed roadmap issue.
- Tag only the merge commit from the release PR with
git tag -s vX.Y.Z -m "vX.Y.Z — Release name". - Push the tag, confirm the GitHub Release is created, and upload the ASCII-armored public signing key as
craik-release-signing-key.asc.
git tag -v vX.Y.Z
git push origin vX.Y.Z
gpg --armor --export KEY_FINGERPRINT > craik-release-signing-key.asc
gh release upload vX.Y.Z craik-release-signing-key.asc --repo eidetic-labs/craik --clobber
gh release view vX.Y.Z --repo eidetic-labs/craik --json assets --jq '.assets[].name'
craik-release-signing-key.asc is a public key export, not a detached
signature. Maintainers must verify that its fingerprint matches the key
reported by git tag -v vX.Y.Z before treating the release as complete.
Local signing-key exports are ignored by the repository. Do not commit
craik-release-signing-key.asc or any private/secret signing key
export; upload the public key only as a GitHub Release asset.
Release Notes
Every release needs a GitHub release entry and a matching
CHANGELOG.md section. The Publish workflow's create-github-release
job extracts the ## X.Y.Z - YYYY-MM-DD block from CHANGELOG.md on
tag push and creates the GitHub Release automatically — title
Craik X.Y.Z, body verbatim from the CHANGELOG section, marked latest.
The job fails fast if the CHANGELOG has no section for the tag version,
so the CHANGELOG is the single source of truth for release notes.
After the release entry appears, upload the public release signing key
asset and verify the asset list before announcing the release.
User-facing additions and fixes
Migration notes and compatibility risks
Provider · policy · persistence · receipt changes
Known limitations remaining
Links to closing issues and release PR
Package verification
Package artifacts are built in CI by the Package workflow, which
checks version consistency, validates release-process docs, builds
sdist + wheel artifacts, runs twine check, smoke-installs the
wheel, and uploads build artifacts.
Local equivalent:
python scripts/check_version_consistency.py
python scripts/check_release_readiness.py
python -m build
python -m twine check dist/*
PyPI publishing
Tag-driven, OIDC-published.
Publishing runs only from the immutable release tag (currently
v0.1.0) after the workflow verifies tag, package version, and
changelog all agree. Manual dispatch builds and validates artifacts
only.
Publishing requires the pypi Protected Environment:
Reviewer approval
At least one maintainer.
Branch / tag restriction
Protected branches and release tags only.
Trusted publishing
Through GitHub OIDC — not stored PyPI tokens.
PyPI publisher config
Aligned with eidetic-labs/craik.
Rollback
PyPI releases are immutable from dependents' perspective. If a bad release ships:
- Publish a patch release with a clear changelog entry and GitHub release note.
- Yank only when installation of the bad artifact is actively harmful.