Skip to main content

Automatically create GitHub releases using Calendar Versioning (CalVer)

Project description

calver-auto-release 🏷️

PyPI Python Versions Coverage Ruff pytest

🏷️ 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:

  1. Users always have access to the latest changes
  2. Version numbers clearly indicate when changes were made
  3. Each change is properly documented through commit messages
  4. 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.

calver

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's release.yml workflow'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_TOKEN variable is automatically populated (see docs). It is enough when this action only needs to create a tag/release, or when later publish steps run in the same workflow job. However, tags and releases created using GITHUB_TOKEN will not trigger other workflows that run on push, create, or release events. If you need downstream workflows to run when a tag or release is created, you'll need to:

  1. Create a Personal Access Token (PAT) with contents: write permissions at https://github.com/settings/tokens, or create an equivalent GitHub App token.
  2. Add it to your repository secrets (e.g., as RELEASE_TOKEN).
  3. Pass it as release_token:
    - uses: basnijholt/calver-auto-release@v1
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        release_token: ${{ secrets.RELEASE_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 year
  • MM: Current month
  • PATCH: 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

  1. Clone the repository
  2. Install development dependencies:
    pip install -e ".[dev]"
    
  3. Install pre-commit hooks:
    pre-commit install
    
  4. 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

calver_auto_release-1.0.7.tar.gz (9.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

calver_auto_release-1.0.7-py3-none-any.whl (20.4 kB view details)

Uploaded Python 3

File details

Details for the file calver_auto_release-1.0.7.tar.gz.

File metadata

  • Download URL: calver_auto_release-1.0.7.tar.gz
  • Upload date:
  • Size: 9.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for calver_auto_release-1.0.7.tar.gz
Algorithm Hash digest
SHA256 610749290d50b26e359eb6234e625226a0cb2d8f2316f2ead1998c7c4a5660b6
MD5 db2906a3f7080224623e70a8fd808229
BLAKE2b-256 78b0fb8aee273422064d81188e6575706ed3804463ce25c529e88a2348707557

See more details on using hashes here.

Provenance

The following attestation bundles were made for calver_auto_release-1.0.7.tar.gz:

Publisher: release.yml on basnijholt/calver-auto-release

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file calver_auto_release-1.0.7-py3-none-any.whl.

File metadata

File hashes

Hashes for calver_auto_release-1.0.7-py3-none-any.whl
Algorithm Hash digest
SHA256 1e20f8d1046411eaf85ba7e532a5d4b5bc1e1b6cbde5179f6a97a05f1202246c
MD5 241cd79c73c1f28ecc9248a20fe586a6
BLAKE2b-256 f06e62648fbcba0ac86236d6c478fb678a05b8721000257fc0ae369381c850d5

See more details on using hashes here.

Provenance

The following attestation bundles were made for calver_auto_release-1.0.7-py3-none-any.whl:

Publisher: release.yml on basnijholt/calver-auto-release

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page