Release
Automates the full release process for edictum (Python).
Arguments
version(optional): The semver version to release, e.g./release 0.1.0
Step 1: Pre-flight checks
Run all checks in sequence. Abort immediately on any failure.
Tests:
Bash: pytest tests/ -vAbort if tests fail.
Lint:
Bash: ruff check src/ tests/Abort if lint fails.
Build (dry run):
Bash: python -m build --sdist --wheelAbort if build fails.
Clean working tree:
Bash: git status --porcelainAbort if output is non-empty (dirty tree).
Read current version:
Read: pyproject.tomlExtract the
versionfield from[project]section.
Step 2: Determine new version
- If a version argument was provided (e.g.
/release 0.1.0), use it. - If no argument, ask the user:
AskUserQuestion: "What version should this release be? Current version is {current_version}." - Validate the version:
- Must be valid semver (MAJOR.MINOR.PATCH)
- Must be strictly greater than the current version
- Abort with a clear message if validation fails
Step 3: Bump version
Edit
pyproject.toml:Edit: pyproject.toml old_string: version = "{current_version}" new_string: version = "{new_version}"Audit all version references in the repo:
Grep: pattern="{current_version}" (search tracked files only, exclude CHANGELOG.md)For each match, determine if it is a "current version" reference or a historical reference:
- Current version references — strings like
Current version: **v0.5.3**,version 0.5.3,(v0.5.3)in docs/README/CLAUDE.md that describe the current state of the library. Update these to{new_version}. - Historical references — changelog entries, "What's Shipped" bullet points, test docstrings noting when a fix was introduced (e.g.,
Regression tests for ... (v0.5.2)), git commit messages. Leave these unchanged.
Use
Editto update each current-version reference. Common locations to check:README.md— install/version badges, "Current version" lineCLAUDE.md— "Current version" line in header (but NOT the "What's Shipped" history)docs/index.md— homepage version mentiondocs/roadmap.md— version references in prose- Any other
.mdor.pyfile that mentions the old version as current
If unsure whether a reference is current or historical, leave it unchanged and flag it to the user.
- Current version references — strings like
Commit the change:
Bash: git add -A && git commit -m "chore: bump version to {version}"- Do NOT include
Co-Authored-Byin the commit message.
- Do NOT include
Step 4: Tag and push
Bash: git tag v{version}
Bash: git push origin main && git push origin v{version}
Step 5: Create GitHub Release
Bash: gh release create v{version} --generate-notes
This auto-generates release notes from commits since the previous tag.
Step 6: Wait and verify
Find the publish workflow run:
Bash: gh run list --workflow=publish.yml --limit=1 --json databaseId,status --jq '.[0]'Watch it:
Bash: gh run watch {run_id}Report result:
- If the run succeeds, confirm to the user: "v{version} published to PyPI successfully."
- If the run fails, show the logs:
And report the failure to the user.Bash: gh run view {run_id} --log-failed
Post-release
After successful publish:
- Verify on PyPI:
pip index versions edictum - Test install:
pip install edictum=={version}
Important Notes
- Always run pre-flight checks before anything else — never skip them.
- Never amend a previous commit; always create a new one.
- The publish workflow (
publish.yml) is triggered by the GitHub Releasepublishedevent. - Clean up build artifacts after dry run:
rm -rf dist/ *.egg-info