Automatically create GitHub releases using Calendar Versioning (CalVer)
Project description
calver-auto-release 🏷️
🏷️ Automatically create GitHub releases using Calendar Versioning (CalVer) on every commit.
This tool is perfect for:
- 📦 Packages where users should always use the latest version
- 🔬 Research software where releases are not tied to specific feature completions
- 🔄 Projects with continuous deployment where each merge to main is a potential release
- 🤖 Automating away the decision of "when should we release?"
By automatically creating a release on every commit to your main branch, you ensure that:
- Users always have access to the latest changes
- Version numbers clearly indicate when changes were made
- Each change is properly documented through commit messages
- The release process is completely automated
[!NOTE] For the best experience, we recommend using squash merges for your Pull Requests. This ensures that:
- Each release corresponds to one logical change
- Release notes are clean and meaningful
- The git history remains linear and easy to understand
Configure this in your GitHub repository settings under "Pull Requests" → "Allow squash merging" and uncheck other merge methods.
ToC
Features
- 📅 Automatic Calendar Versioning (
v{YYYY}.{MM}.{PATCH}) - 🤖 Creates GitHub releases automatically
- 📝 Generates release notes from commit messages
- 🏷️ Supports release skipping with commit message flags
- 🔄 Integrates with GitHub Actions
- 🐍 Can be used as a Python package
- 🖥️ Command-line interface included
- 🧪 Dry-run mode for testing
- 📋 Customizable release notes format
Usage
GitHub Action
Add this to your workflow file (e.g., .github/workflows/release.yml):
[!NOTE] See the
basnijholt/home-assistant-streamdeck-yaml'srelease.ymlworkflow's for a full example, and see it's releases page for the result.
A minimal example:
name: Create Release
on:
push:
branches: [main]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: basnijholt/calver-auto-release@v1
id: release
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
And full example including publishing to PyPI:
name: Create Release
on:
push:
branches:
- main
jobs:
release:
runs-on: ubuntu-latest
environment: # Needed for `pypa/gh-action-pypi-publish`
name: pypi
url: https://pypi.org/p/${{ github.repository }}
permissions: # Needed for `pypa/gh-action-pypi-publish`
id-token: write # for PyPI publishing
steps:
# Create release with CalVer
- uses: basnijholt/calver-auto-release@v1
id: release
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
# Optional: custom configuration
skip_patterns: "[skip release],[no-release]"
footer: "Custom footer text"
generate_release_notes: true # Add GitHub's automatic release notes
# Optional: publish to PyPI
# Only run if a new version was created
- name: Build package
if: steps.release.outputs.version != ''
run: |
python -m pip install build
python -m build
# Option 1: Publish with official PyPA action
- name: Publish package distributions to PyPI
if: steps.release.outputs.version != ''
uses: pypa/gh-action-pypi-publish@release/v1
# Option 2: Publish with twine
# - name: Publish package distributions to PyPI
# if: steps.release.outputs.version != ''
# env:
# TWINE_USERNAME: __token__
# TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
# run: |
# python -m pip install twine
# twine upload dist/*
The action creates a new release with CalVer versioning, and you can optionally add your preferred method for publishing to PyPI or any other post-release tasks.
[!IMPORTANT] The
secrets.GITHUB_TOKENvariable is automatically populated (see docs). However, releases created usingGITHUB_TOKENwill not trigger other workflows that run on thereleaseevent. If you need to trigger other workflows when a release is created, you'll need to:
- Create a Personal Access Token (PAT) with
contents: writepermissions at https://github.com/settings/tokens- Add it to your repository secrets (e.g., as
PAT)- Use it in the workflow:
- uses: basnijholt/calver-auto-release@v1 with: github_token: ${{ secrets.PAT }} # Instead of secrets.GITHUB_TOKEN
CLI Usage
# Basic usage
calver-auto-release --repo-path /path/to/repo
# Dry run (show what would happen without creating the release)
calver-auto-release --repo-path /path/to/repo --dry-run
# Custom skip patterns
calver-auto-release --repo-path /path/to/repo --skip-pattern "[no-release]" --skip-pattern "[skip]"
Python API
from calver_auto_release import create_release
# Basic usage
create_release() # Uses current directory
# With custom configuration
create_release(
repo_path="/path/to/repo",
skip_patterns=["[skip]", "[no-release]"],
footer="\nCustom footer text",
dry_run=True, # Show what would happen without creating the release
)
Release Notes Format
The generated release notes will have this format:
🚀 Release YYYY.MM.PATCH
📝 This release includes the following changes:
- First commit message
- Second commit message
- etc.
🙏 Thank you for using this project! Please report any issues or feedback on the GitHub repository
Requirements
- Git repository with an 'origin' remote configured
- Python 3.10 or higher
- Git command-line tools installed
Installation
Install using pip:
pip install calver-auto-release
Or using uv:
uv pip install calver-auto-release
Configuration
Skip Release Patterns
You can skip creating a release by including these patterns in your commit message:
[skip release][pre-commit.ci]⬆️ Update
Version Format
The version format follows CalVer: YYYY.MM.PATCH
YYYY: Current yearMM: Current monthPATCH: Incremental number, resets when year or month changes
Custom Footer
You can customize the footer text that appears at the end of each release note:
create_release(
footer="\nCustom footer text for all releases"
)
Or via CLI:
calver-auto-release --footer "Custom footer text"
Or in the GitHub Action:
- uses: basnijholt/calver-auto-release@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
footer: "Custom footer text"
License
MIT License
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Development
- Clone the repository
- Install development dependencies:
pip install -e ".[dev]"
- Install pre-commit hooks:
pre-commit install - Run tests:
pytest
Project details
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 calver_auto_release-1.0.6.tar.gz.
File metadata
- Download URL: calver_auto_release-1.0.6.tar.gz
- Upload date:
- Size: 9.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4b0b5972998e03a0973fad8507842d7656130e77500107b50f16086b1d11a658
|
|
| MD5 |
ec58b6fa92e5407e41307cb6845e9019
|
|
| BLAKE2b-256 |
ac0adbed9be4a045804cd8dc879d442ccf6c784f32d8ae1e6e221afc053ca5fc
|
Provenance
The following attestation bundles were made for calver_auto_release-1.0.6.tar.gz:
Publisher:
release.yml on basnijholt/calver-auto-release
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
calver_auto_release-1.0.6.tar.gz -
Subject digest:
4b0b5972998e03a0973fad8507842d7656130e77500107b50f16086b1d11a658 - Sigstore transparency entry: 183749759
- Sigstore integration time:
-
Permalink:
basnijholt/calver-auto-release@df4c774ad9a344cb4f9c83db69f0f67fc546a996 -
Branch / Tag:
refs/tags/v1.0.6 - Owner: https://github.com/basnijholt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@df4c774ad9a344cb4f9c83db69f0f67fc546a996 -
Trigger Event:
release
-
Statement type:
File details
Details for the file calver_auto_release-1.0.6-py3-none-any.whl.
File metadata
- Download URL: calver_auto_release-1.0.6-py3-none-any.whl
- Upload date:
- Size: 20.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f9d5de1b4727e246c4d5e51b06f0f2052c7f1f150faf0646e0dc8557de03afde
|
|
| MD5 |
c61ea69c28f76743374ca77da3f3e2fc
|
|
| BLAKE2b-256 |
e5c002b16b34562d48c7e107b2c161a9a37d815fec773c9ed008fcb94b124361
|
Provenance
The following attestation bundles were made for calver_auto_release-1.0.6-py3-none-any.whl:
Publisher:
release.yml on basnijholt/calver-auto-release
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
calver_auto_release-1.0.6-py3-none-any.whl -
Subject digest:
f9d5de1b4727e246c4d5e51b06f0f2052c7f1f150faf0646e0dc8557de03afde - Sigstore transparency entry: 183749761
- Sigstore integration time:
-
Permalink:
basnijholt/calver-auto-release@df4c774ad9a344cb4f9c83db69f0f67fc546a996 -
Branch / Tag:
refs/tags/v1.0.6 - Owner: https://github.com/basnijholt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@df4c774ad9a344cb4f9c83db69f0f67fc546a996 -
Trigger Event:
release
-
Statement type: