Sample project demonstrating CalVer (YYYY.MM.DD.MICRO) with hatch
Project description
hatch-calvar-sample
Sample hatch-based Python project demonstrating Calendar Versioning (CalVer) with format YYYY.MM.DD.MICRO and automated PyPI release workflows.
Overview
This project serves as a proof-of-concept and reusable template for implementing CalVer versioning with the hatch build system. It demonstrates:
- Calendar Versioning (YYYY.MM.DD.MICRO) calculated from git tags
- Dynamic versioning with hatch build system
- Version checking CLI tool with multiple commands
- Automated PyPI release via GitHub Actions
- Complete release workflow automation
- Strict type checking with mypy and
py.typedmarker - Python 3.9 -- 3.13 support
Version Format
The project uses CalVer format: YYYY.MM.DD.MICRO
YYYY-- 4-digit year (e.g., 2025)MM-- 2-digit month (01-12)DD-- 2-digit day (01-31)MICRO-- Sequential number for releases on the same day (1, 2, 3, ...)
Examples: 2025.01.18.1, 2025.01.18.2, 2025.03.15.1
Installation
pip install hatch-calvar-sample
Release Workflow
The following diagram shows the fully automated release pipeline:
flowchart LR
A[PR Merged to main] --> B[auto-tag.yml]
B -->|Calculates CalVer\nCreates git tag| C[Tag pushed: vYYYY.MM.DD.MICRO]
C --> D[release.yml]
D -->|Builds & validates\npackage| E[Publish to PyPI]
style A fill:#4a90d9,color:#fff
style B fill:#f5a623,color:#fff
style C fill:#7b68ee,color:#fff
style D fill:#f5a623,color:#fff
style E fill:#50c878,color:#fff
How it works:
- You merge a pull request into
main. auto-tag.ymlruns, calculates the next CalVer version, and creates avYYYY.MM.DD.MICROgit tag.- The tag push triggers
release.yml, which builds the package, validates it with twine, and publishes to PyPI via Trusted Publishing. - CI checks (
ci.yml) run on every push and PR to ensure tests, linting, security, and type checking pass.
CLI Tool
The calver-check CLI provides commands for version management:
# Show CLI version
calver-check --version
# Calculate next version
calver-check calc
# Check current version from different sources
calver-check check
# Validate version format
calver-check validate 2025.01.18.1
# Compare two versions
calver-check compare 2025.01.18.1 2025.01.18.2
# Show version information
calver-check info
# Create a git tag for the next version
calver-check tag
# Preview the tag without creating it
calver-check tag --dry-run
All commands support --json for machine-readable output:
calver-check calc --json
calver-check tag --dry-run --json
Usage Examples
Calculating Next Version
# Using the CLI tool
calver-check calc
# Using the script directly
python scripts/calc_version.py
# With validation
python scripts/calc_version.py --validate --pep440
Creating a Release Tag
# Preview what tag would be created
calver-check tag --dry-run
# Create the tag locally
calver-check tag
# Push the tag to trigger a release
git push origin v2025.01.18.1
Validating Version Format
# Valid version
calver-check validate 2025.01.18.1
# Invalid version (exits with error)
calver-check validate 2025.1.18.1
Comparing Versions
calver-check compare 2025.01.18.1 2025.01.18.2
# Output: 2025.01.18.1 < 2025.01.18.2
Release Process
Fully Automated (Recommended)
- Open a pull request with your changes.
- Merge the pull request to
main. - GitHub Actions automatically:
- Calculates next CalVer version (e.g.,
2025.01.18.1) - Creates tag
v2025.01.18.1 - Builds and validates the package
- Publishes to PyPI
- Calculates next CalVer version (e.g.,
No manual tagging required.
Manual Release (Hotfixes)
# Calculate and preview the next tag
calver-check tag --dry-run
# Create and push the tag
calver-check tag
git push origin v2025.01.18.1
Using Makefile
make version-calc # Calculate next version
make version-check # Check current version
make version-validate VERSION=2025.01.18.1
make release-tag # Create and push release tag (interactive)
make build-test # Build package for testing
Project Structure
hatch-calvar-sample/
├── pyproject.toml # Hatch configuration with dynamic versioning
├── README.md # This file
├── CHANGELOG.md # Changelog with CalVer format
├── CONTRIBUTING.md # Contribution guidelines
├── SECURITY.md # Security policy
├── LICENSE.txt # MIT license
├── Makefile # Convenient make targets
├── .pre-commit-config.yaml # Pre-commit hook configuration
├── .github/
│ └── workflows/
│ ├── ci.yml # Unified CI (test, lint, type-check, security)
│ ├── auto-tag.yml # Auto-create tag on PR merge
│ └── release.yml # Build and publish to PyPI
├── docs/
│ ├── CALVER_MIGRATION_GUIDE.md # Migrating an existing project to CalVer
│ ├── CALVER_QUICK_START.md # Quick-start guide for CalVer
│ ├── PYPROJECT_TOML_MIGRATION.md # pyproject.toml migration reference
│ └── PLANNING.md # Project planning notes
├── scripts/
│ └── calc_version.py # Standalone version calculation script
├── src/
│ └── hatch_calvar_sample/
│ ├── __init__.py # Package with __version__
│ ├── __about__.py # Version metadata
│ ├── calver.py # Core CalVer logic (parse, validate, calculate)
│ ├── cli.py # CLI implementation (calver-check)
│ ├── py.typed # PEP 561 type marker
│ └── VERSION # Version file (generated during build)
└── tests/
├── test_version_calc.py # Unit tests for version calculation
├── test_version_cli.py # Unit tests for CLI tool
└── test_integration.py # Integration tests
Configuration
Dynamic Versioning
The project uses hatch's dynamic versioning feature configured in pyproject.toml:
[tool.hatch.version]
path = "src/hatch_calvar_sample/VERSION"
The VERSION file is created during the release workflow with the version extracted from the git tag.
Version Metadata in Code
The package reads version from importlib.metadata when installed, with fallbacks:
- Package metadata (when installed)
- VERSION file (for development builds)
- Environment variable
HATCH_CALVER_VERSION
Access version programmatically:
from hatch_calvar_sample import __version__
print(__version__) # Output: 2025.01.18.1
Version Calculation Logic
The core logic lives in src/hatch_calvar_sample/calver.py:
- Gets current UTC date (using
datetime.now(timezone.utc)) - Fetches all git tags
- Parses tags matching the strict CalVer regex (
YYYY.MM.DD.MICROwith validated month/day ranges) - Filters tags with the same date
- Calculates next MICRO =
max(existing) + 1or1if none exist - Returns:
YYYY.MM.DD.MICRO
Edge Cases Handled
- No tags -- returns
YYYY.MM.DD.1 - Multiple tags same date -- increments MICRO correctly
- Date boundary crossing -- resets MICRO to 1 for new date
- Invalid tag formats -- skipped gracefully
- Timezone handling -- uses UTC for consistency
How to Adapt This Template
This repository is designed as a starting point. Here is what to change when using it for your own project.
What to Rename
- Package name: Replace
hatch-calvar-sampleandhatch_calvar_sampleeverywhere:pyproject.toml--[project] name,[tool.hatch.version] path, source pathssrc/hatch_calvar_sample/-- rename the directorytests/-- update importsMakefile-- updateSRC_DIR
- CLI entry point: In
pyproject.tomlunder[project.scripts], renamecalver-checkto your desired command name. - Author/URL info: Update
[project] authorsand[project.urls]inpyproject.toml.
What to Delete
docs/PLANNING.md-- project-specific planning notesSUGGESTIONS.md-- internal notes (if present)docs/CALVER_MIGRATION_GUIDE.md-- only needed if migrating from SemVer- Sample test data specific to this demo
What to Configure
- Python version range: Adjust
requires-pythonand classifier list inpyproject.toml. - Coverage threshold: Change
fail_underin[tool.coverage.report](currently 80%). - Linting rules: Adjust
[tool.ruff]select/ignore lists as needed. - Pre-commit hooks: Review
.pre-commit-config.yamland enable/disable hooks. - PyPI Trusted Publishing: Configure your PyPI project to trust your GitHub repository.
First Release Checklist
- Rename the package (see above).
- Replace this README content with your own.
- Clear
CHANGELOG.mdentries (keep the format). - Push to GitHub and configure PyPI Trusted Publishing.
- Open and merge your first PR -- the release will happen automatically.
Development
See CONTRIBUTING.md for full development setup and guidelines.
Quick start:
git clone https://github.com/QAToolist/hatch-calvar-sample.git
cd hatch-calvar-sample
pip install -e ".[dev]"
pre-commit install
make test
Documentation
Detailed guides are in the docs/ directory:
- CalVer Quick Start -- get started with CalVer in minutes
- CalVer Migration Guide -- migrate an existing project from SemVer
- pyproject.toml Migration -- reference for pyproject.toml settings
PEP 440 Compliance
CalVer format YYYY.MM.DD.MICRO is PEP 440 compliant as a release segment:
calver-check validate 2025.01.18.1
Troubleshooting
Version Not Found
- Ensure package is installed:
pip install -e . - Check VERSION file exists:
ls src/hatch_calvar_sample/VERSION - Verify git tags:
git tag
Build Errors
- Verify VERSION file exists with valid format
- Check
pyproject.tomldynamic version configuration - Ensure hatch is installed:
pip install hatchling
CLI Not Found
- Reinstall package:
pip install -e . - Check entry point in
pyproject.toml - Verify PATH includes Python scripts directory
License
hatch-calvar-sample is distributed under the terms of the MIT license.
References
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hatch_calvar_sample-2026.3.30.1.tar.gz.
File metadata
- Download URL: hatch_calvar_sample-2026.3.30.1.tar.gz
- Upload date:
- Size: 39.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f79fd1d99e51711782c84bcb72918256cca3291bb63cffc25e27b78ddb22847
|
|
| MD5 |
944eb91ccd47c5d29d93fc0b841083de
|
|
| BLAKE2b-256 |
9f0821ab4803d0cb1ff3e5d393ff44b0c888a3b71841e842f5361f916d5f3e33
|
Provenance
The following attestation bundles were made for hatch_calvar_sample-2026.3.30.1.tar.gz:
Publisher:
release.yml on qatoolist/hatch-calvar-sample
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hatch_calvar_sample-2026.3.30.1.tar.gz -
Subject digest:
2f79fd1d99e51711782c84bcb72918256cca3291bb63cffc25e27b78ddb22847 - Sigstore transparency entry: 1198859182
- Sigstore integration time:
-
Permalink:
qatoolist/hatch-calvar-sample@dff96c09c68bd2b76d60d40c4b301c7561a53d07 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/qatoolist
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@dff96c09c68bd2b76d60d40c4b301c7561a53d07 -
Trigger Event:
workflow_run
-
Statement type:
File details
Details for the file hatch_calvar_sample-2026.3.30.1-py3-none-any.whl.
File metadata
- Download URL: hatch_calvar_sample-2026.3.30.1-py3-none-any.whl
- Upload date:
- Size: 12.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a3589ab63e21a16c2b687e3f47038064118370c8da91be2eaec84cffd4986114
|
|
| MD5 |
d1f8ac7ac77809034405d4816f3e58f9
|
|
| BLAKE2b-256 |
3fa771905c38a333d5f4b311bddce1973f602cabd4cc7e027bb380ae4726df6d
|
Provenance
The following attestation bundles were made for hatch_calvar_sample-2026.3.30.1-py3-none-any.whl:
Publisher:
release.yml on qatoolist/hatch-calvar-sample
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hatch_calvar_sample-2026.3.30.1-py3-none-any.whl -
Subject digest:
a3589ab63e21a16c2b687e3f47038064118370c8da91be2eaec84cffd4986114 - Sigstore transparency entry: 1198859191
- Sigstore integration time:
-
Permalink:
qatoolist/hatch-calvar-sample@dff96c09c68bd2b76d60d40c4b301c7561a53d07 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/qatoolist
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@dff96c09c68bd2b76d60d40c4b301c7561a53d07 -
Trigger Event:
workflow_run
-
Statement type: