CORNETO uses an automated tag-based release process powered by Poetry Dynamic Versioning and GitHub Actions. Git tags serve as the single source of truth for versioning - no manual version bumping in files is required.
Note: This document covers the release process for maintainers. For development setup and contribution guidelines, see CONTRIBUTING.md.
To create a new release:
-
Integrate
devintomain.- Merge via pull request (
dev->main) or fast-forward merge locally.
git checkout dev git pull --ff-only origin dev git checkout main git pull --ff-only origin main git merge --ff-only dev git push origin main
- Merge via pull request (
-
Create and push the release tag from
main:poetry install git checkout main git pull --ff-only origin main poetry run release v1.2.3
- Use pre-release tags as needed:
v1.2.3-alpha.0,v1.2.3-beta.0,v1.2.3-rc.0.
- Use pre-release tags as needed:
-
Automatic pipeline execution:
- GitHub Actions detects the new tag
- Builds the package using Poetry
- Creates GitHub Release with automated release notes
- Publishes to PyPI via OIDC trusted publishing
- Deploys versioned documentation to GitHub Pages
-
Sync
mainback intodevafter tagging:- This keeps
devreachable from the latest release tags used by dynamic versioning. - Without this step,
devmay continue reporting an older pre-release base (e.g.,1.0.0b3+...).
git checkout dev git pull --ff-only origin dev git merge --ff-only origin/main git push origin dev
- This keeps
-
Version resolution:
- Poetry Dynamic Versioning automatically extracts the version from the Git tag
- The package version in
pyproject.tomlremains at0.0.0(placeholder) - Built packages use the actual tag version (e.g.,
1.2.3)
-
Automated Release Notes:
- GitHub automatically generates release notes based on merged PRs and commits
- Uses conventional commit patterns to categorize changes
- Includes contributor acknowledgments and change summaries
- Release notes can be manually edited after creation if needed
# Integrate dev into main
git checkout dev
git pull --ff-only origin dev
git checkout main
git pull --ff-only origin main
git merge --ff-only dev
git push origin main
# Create and push a release tag explicitly
poetry run release v1.0.0-beta.4
# Sync main back into dev so dev sees the latest release tag ancestry
git checkout dev
git pull --ff-only origin dev
git merge --ff-only origin/main
git push origin devThe release pipeline (.github/workflows/build-and-publish.yml) will automatically:
- Build source and wheel distributions
- Create a GitHub Release with automated release notes
- Publish to PyPI using trusted publishing
- Deploy documentation with version switcher
Use the helper command to create and push an explicit tag:
poetry run release v1.2.3
poetry run release v1.0.0-beta.4
poetry run release 1.0.0-rc.1 # 'v' prefix is optionalIt validates release preconditions (clean tree, on main, in sync with origin/main,
origin/dev merged into main, tag not already present), then creates an annotated tag and pushes it to origin.
Useful options:
poetry run release v1.0.0-beta.4 --dry-run # validate only
poetry run release v1.0.0-beta.4 --yes # skip confirmation promptAfter the automated release is created, you can:
- Go to the GitHub Releases page
- Edit the release to add additional context, migration guides, or breaking change notices
- The automated notes will serve as the foundation, with your manual additions
Follow Semantic Versioning:
MAJOR.MINOR.PATCH(e.g.,v1.2.3)- Use
vprefix for tags (e.g.,v1.0.0, not1.0.0) - Pre-releases:
v1.0.0-alpha.0,v1.0.0-beta.0,v1.0.0-rc.0
Before creating a release, ensure the development environment and code quality standards are met:
All maintainers should have the development environment properly configured as described in CONTRIBUTING.md, including:
- Poetry for dependency management
- Pre-commit hooks installed and active
Critical: Pre-commit hooks must be installed and passing for all commits that will be included in the release. The pre-commit configuration ensures:
- Conventional commit messages: Required for automated GitHub release notes generation (feat:, fix:, docs:, etc.)
- Code quality: Linting, formatting, and style checks via Ruff
- Repository hygiene: File validation, trailing whitespace removal, etc.
Important: Conventional commits are essential for the automated release notes feature. Each commit should follow the pattern:
<type>(<optional scope>): <description>
[optional body]
[optional footer(s)]
Common types: feat, fix, docs, chore, refactor, test, ci, build, perf, style, revert
To set up pre-commit hooks:
poetry run pre-commit install --hook-type pre-commit --hook-type commit-msgBefore releasing, run comprehensive quality checks:
# Tests
poetry run pytest
# Linting
poetry run ruff check corneto --exclude tests
# Formatting
poetry run ruff check corneto --exclude tests --fix
poetry run ruff format corneto --exclude tests
# Type checking
poetry run pyrefly check cornetoThe typical development workflow involves:
- Work in the
devbranch for ongoing development - Ensure all commits follow conventional commit format (enforced by pre-commit hooks)
- Run quality checks before merging to main
- Integrate into
mainwhen ready for release (via pull request or fast-forward merge) - Create release tag on the
mainbranch to trigger automated publishing - Sync
mainback intodevimmediately after tagging
The project uses Poetry Dynamic Versioning (configured in pyproject.toml):
[tool.poetry-dynamic-versioning]
enable = true
vcs = "git"
pattern = "default"
style = "pep440"
tagged-metadata = falseThe release workflow (.github/workflows/build-and-publish.yml) is triggered by:
- Push events to tags matching
v*pattern - Uses OIDC trusted publishing for secure PyPI uploads
- Requires no manual secrets or tokens
main: Stable releases and release tagsdev: Active development branch- Recommended integration:
dev->mainfor releases, thenmain->devimmediately after tagging
The documentation uses a centralized version switcher that allows users to navigate between different documentation versions (stable, latest, and specific releases). This system is designed to work across all deployed documentation versions automatically.
The version switcher uses a single, centrally-updated file hosted on GitHub Pages:
-
Switcher Hosting:
switcher.jsonis deployed to the root of the docs site- URL:
https://corneto.org/switcher.json(configured viaDOCS_BASE_URL) - This URL is configured in
docs/conf.pyvia_switcher_url_with_ts() - A timestamp parameter is added to bypass browser caching
- URL:
-
Automated Updates: When documentation is deployed to GitHub Pages:
- The docs workflow generates
switcher.json(scripts/generate_switcher.py) - It is published to the site root alongside the redirect page
- A post-deploy patch step updates existing HTML in
gh-pagesto:- point
theme_switcher_json_urltohttps://corneto.org/switcher.json - correct
theme_switcher_version_matchbased on folder (stable/,latest/,vX.Y.Z/)
- point
- The docs workflow generates
-
Version Mapping: Documentation deployments use the following version identifiers:
devbranch → deployed as"latest"mainbranch → deployed as"stable"(typically marked as preferred)- Git tags (e.g.,
v1.0.0) → deployed using the tag name
The
SPHINX_VERSION_MATCHenvironment variable (set in.github/workflows/deploy-docs.yml) tells the PyData Sphinx Theme which version is currently being viewed. -
Deployment Behavior (Why
destination_diris used withoutkeep_files):- Each docs build replaces only its own folder (
latest/,stable/, orvX.Y.Z/) on thegh-pagesbranch. - This ensures clean regeneration for a given version (no mixing of old/new files) while leaving other versions untouched.
- The root redirect is deployed with
keep_files: trueso it doesn’t delete any versioned folders.
- Each docs build replaces only its own folder (
- Central Management: One
switcher.jsonserves all deployed documentation versions - Automatic Updates: Old deployed docs automatically show new versions in the switcher dropdown
- No Regeneration Needed: Previously deployed documentation doesn't need to be rebuilt to show new versions
- Consistency: All documentation versions display the same version list
If the automatic workflow fails or manual intervention is needed, re-run the docs workflow or regenerate and deploy the root artifacts (redirect + switcher.json) using the same workflow steps.