BumpCalver Library
| Description | Simple Calendar Versioning Library |
| Author(s) | Mike Ryan |
| Repository | https://github.com/devsetgo/bumpcalver |
| Copyright | Copyright © 2024 - 2026 Mike Ryan |
Table of Contents
Support Python Versions
CI/CD Pipeline:
SonarCloud:
BumpCalver CLI Documentation¶
Overview¶
The BumpCalver CLI is a command-line interface for calendar-based version bumping. It automates the process of updating version strings in your project's files based on the current date and build count. Additionally, it can create Git tags and commit changes automatically. The CLI is highly configurable via a pyproject.toml file and supports various customization options to fit your project's needs.
Table of Contents¶
-
Documentation Site: BumpCalver CLI
- Getting Started
- Command-Line Usage
- Options
- Error Handling
- Support
Installation¶
To install the BumpCalver CLI, you can add it to your project's dependencies. If it's packaged as a Python module, you might install it via:
pip install bumpcalver
Getting Started¶
-
Configure Your Project: Create or update the
pyproject.tomlfile in your project's root directory to include the[tool.bumpcalver]section with your desired settings. -
Run the CLI: Use the
bumpcalvercommand with appropriate options to bump your project's version.
Example:
bumpcalver --build --git-tag --auto-commit
AI Assistant Bootstrap (for app repositories)¶
If you're using Claude, Copilot, or another AI assistant to set up bumpcalver in your project, pull packaged, always-current integration instructions directly from the installed library into your repo's own instruction file — one command, no manual copy-paste of the Configuration section below:
python -m bumpcalver.ai_instructions claude --write # writes ./CLAUDE.md
python -m bumpcalver.ai_instructions copilot --write # writes ./.github/copilot-instructions.md
python -m bumpcalver.ai_instructions generic > AI_INSTRUCTIONS.md
Or from Python:
from bumpcalver import get_app_instructions, suggested_instruction_filename
assistant = "copilot" # or "claude" / "generic"
print(f"Suggested destination: {suggested_instruction_filename(assistant)}")
print(get_app_instructions(assistant))
This avoids an assistant reverse-engineering the [tool.bumpcalver] schema
from scratch and keeps the guidance it produces aligned with the version of
bumpcalver actually installed — including which file_type to pick for a
given file, the three versioning modes, and which config keys have real
(git tag/commit) side effects. See
AI Assistant Instructions
for the full details, including what these instructions do not yet cover.
Configuration¶
The BumpCalver CLI relies on a pyproject.toml configuration file located at the root of your project. This file specifies how versioning should be handled, which files to update, and other settings.
As an alternative, you can use configuration file named bumpcalver.toml. The CLI will look for this file if pyproject.toml is not found.
Configuration Options¶
version_format(string): Format string for the version. Supports{current_date},{build_count}, and the hybrid placeholders{major},{minor},{patch}.date_format(string): Format string for the date. Supports various combinations of year, month, day, quarter, and week.timezone(string): Timezone for date calculations (e.g.,UTC,America/New_York).major(integer, optional): Major version component for hybrid versioning. Defaults to0.minor(integer, optional): Minor version component for hybrid versioning. Defaults to0.patch(integer, optional): Patch version component for hybrid versioning. Defaults to0.beta_format(string, optional): Suffix appended when--betais used. Supports a{beta_count}placeholder for auto-incrementing. Defaults to.beta.rc_format(string, optional): Suffix appended when--rcis used. Supports a{rc_count}placeholder. Defaults to.rc.release_format(string, optional): Suffix appended when--releaseis used. Defaults to.release.file(list of tables): Specifies which files to update and how to find the version string.path(string): Path to the file to be updated.file_type(string): Type of the file (e.g.,python,toml,yaml,json,xml,dockerfile,makefile,properties,env,setup.cfg,text,regex).variable(string, optional): The variable name that holds the version string in the file.pattern(string, optional): A regex pattern to find the version string.version_standard(string, optional): The versioning standard to follow (e.g.,pythonfor PEP 440).git_tag(boolean): Whether to create a Git tag with the new version.auto_commit(boolean): Whether to automatically commit changes when creating a Git tag.
Example Configuration¶
[tool.bumpcalver]
version_format = "{current_date}-{build_count:03}"
date_format = "%y.%m.%d"
timezone = "America/New_York"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "pyproject.toml"
file_type = "toml"
variable = "project.version"
version_standard = "python"
[[tool.bumpcalver.file]]
path = "examples/makefile"
file_type = "makefile"
variable = "APP_VERSION"
version_standard = "default"
[[tool.bumpcalver.file]]
path = "examples/dockerfile"
file_type = "dockerfile"
variable = "arg.VERSION"
version_standard = "default"
[[tool.bumpcalver.file]]
path = "examples/dockerfile"
file_type = "dockerfile"
variable = "env.APP_VERSION"
version_standard = "default"
[[tool.bumpcalver.file]]
path = "examples/p.py"
file_type = "python"
variable = "__version__"
version_standard = "python"
[[tool.bumpcalver.file]]
path = "sonar-project.properties"
file_type = "properties"
variable = "sonar.projectVersion"
version_standard = "default"
[[tool.bumpcalver.file]]
path = ".env"
file_type = "env"
variable = "VERSION"
version_standard = "default"
[[tool.bumpcalver.file]]
path = "setup.cfg"
file_type = "setup.cfg"
variable = "metadata.version"
version_standard = "python"
[[tool.bumpcalver.file]]
path = "VERSION"
file_type = "text"
[[tool.bumpcalver.file]]
path = "lib/version.rb"
file_type = "regex"
variable = "VERSION"
pattern = 'VERSION = "(.+?)"'
Date Format Examples¶
The date_format option allows you to customize the date format used in version strings. Here are some examples of how to format dates:
%Y.%m.%d- Full year, month, and day (e.g.,2024.12.25)%y.%m.%d- Year without century, month, and day (e.g.,24.12.25)%y.Q%q- Year and quarter (e.g.,24.Q1)%y.%m- Year and month (e.g.,24.12)%y.%j- Year and day of the year (e.g.,24.001for January 1st, 2024)%Y.%j- Full year and day of the year (e.g.,2024.001for January 1st, 2024)%Y.%m- Full year and month (e.g.,2024.12)%Y.Q%q- Full year and quarter (e.g.,2024.Q1)
Refer to the Python datetime documentation for more format codes.
Supported File Types¶
BumpCalver supports version management for the following file types:
Core File Types¶
python- Python files with version variables (e.g.,__version__ = "1.0.0")toml- TOML configuration files (e.g.,pyproject.toml)yaml- YAML configuration filesjson- JSON configuration files (e.g.,package.json)xml- XML configuration files
Infrastructure Files¶
dockerfile- Docker files with ARG or ENV variablesmakefile- Makefiles with version variables
Configuration Files¶
properties- Java-style properties files (e.g.,sonar-project.properties)- Format:
key=value - Example:
sonar.projectVersion=2025.02.02 env- Environment variable files (e.g.,.env)- Format:
KEY=valueorKEY="value" - Example:
VERSION=2025.02.02 setup.cfg- Python setup configuration files- Supports both dot notation (
metadata.version) and simple keys (version) - Example:
version = 2025.02.02in[metadata]section
Generic File Types¶
For formats without a dedicated handler above:
text- A bare version file whose entire content is the version, with no key at all (e.g. aVERSIONfile used by shell-based release pipelines).variableis not used.- Example file content:
2025.02.02 regex- Any otherKEY = value-style language (Ruby, Rust, Go, Java, etc.) via a user-suppliedpattern: a regex with exactly one capture group around the version. Everything else on the matched line is left untouched.- Example:
pattern = 'VERSION = "(.+?)"'matches Ruby'sVERSION = "2025.02.02"and replaces only the quoted text.
Custom File Types via Plugins¶
If none of the above fit and text/regex aren't enough, third-party
packages can register their own file_type handlers without forking
bumpcalver, via a bumpcalver.handlers entry point. See the "Distributing
Your Handler as a Plugin" section of the
development guide
and the runnable example at
examples/bumpcalver-plugin-example/.
Command-Line Usage¶
The CLI provides several options to customize the version bumping process. Run
bumpcalver --help for the exact, current list — the same output is also
published at
CLI Reference,
kept byte-for-byte in sync with the code by a test (tests/test_docs.py)
rather than hand-copied here.
Version Bump Options¶
--beta: Appends the configuredbeta_formatsuffix (default.beta) to the version.--rc: Appends the configuredrc_formatsuffix (default.rc) to the version.--release: Appends the configuredrelease_formatsuffix (default.release) to the version.--custom TEXT: Adds a custom suffix to the version.--build: Increments the build count based on the current date.--bump [major|minor|patch]: Increments the specified semantic component (major,minor, orpatch) in config and writes the new value back. Use with hybridversion_formatstrings that contain{major},{minor}, or{patch}.--timezone: Overrides the timezone specified in the configuration.--git-tag/--no-git-tag: Forces Git tagging on or off, overriding the configuration.--auto-commit/--no-auto-commit: Forces auto-commit on or off, overriding the configuration.--dry-run: Prints the version that would be set and which files would change, without writing anything or creating a git tag/commit.--config-file PATH: Use a specificpyproject.toml/bumpcalver.tomlinstead of auto-discovering one in the current directory (also settable via theBUMPCALVER_CONFIGenvironment variable). File paths inside that config resolve relative to the config file's own directory — handy for monorepo tooling or wrapper scripts invokingbumpcalverfrom elsewhere. Cannot be combined with the undo options below.--json: Emit a single JSON object with the result to stdout instead of human-readable log lines (those move to stderr). See Machine-Readable Output below. Cannot be combined with the undo options below.
Machine-Readable Output¶
Pass --json for a script-friendly result instead of log lines — useful in CI
to capture the computed version, or to check which files actually changed:
bumpcalver --build --json 2>/dev/null
# {"version": "2026.07.25.001", "files_updated": ["src/myapp/__init__.py"], "operation_id": "20260725_120000_000", "git_tag": null, "git_commit_hash": null}
Works the same way with --dry-run ({"dry_run": true, ...}), a no-op bump
({"no_op": true, ...}), or an error ({"error": "..."} with a non-zero exit
code) — stdout is always exactly one JSON object, never a mix of log lines and
data. See the CLI Reference
for the full payload shape of each case.
Undo Options¶
BumpCalver includes powerful undo functionality to revert version changes:
--undo: Undo the most recent version bump operation.--undo-id TEXT: Undo a specific operation by its unique ID.--list-history: Show recent version bump operations that can be undone.
Note: Undo options cannot be combined with version bump options (including --dry-run and --config-file).
Examples¶
Basic Version Bump¶
To bump the version using the current date and build count:
bumpcalver --build
Beta Versioning¶
To create a beta version:
bumpcalver --build --beta
Specifying Timezone¶
To use a specific timezone:
bumpcalver --build --timezone Europe/London
Creating a Git Tag with Auto-Commit¶
To bump the version, commit changes, and create a Git tag:
bumpcalver --build --git-tag --auto-commit
Capturing the New Version in CI¶
Use --json plus jq (or any JSON tool) to feed the
computed version into later pipeline steps, e.g. a GitHub Actions step output:
VERSION=$(bumpcalver --build --json 2>/dev/null | jq -r '.version')
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
Undo Operations¶
View recent version bump operations:
bumpcalver --list-history
Undo the last version bump:
bumpcalver --undo
Undo a specific operation by ID:
bumpcalver --undo-id 20251012_143015_123
Pre-release Versioning¶
By default --beta, --rc, and --release append .beta, .rc, and .release:
bumpcalver --build --beta # → 26.05.24.1.beta
bumpcalver --build --rc # → 26.05.24.1.rc
bumpcalver --build --release # → 26.05.24.1.release
Configure the suffix format — including an optional counter — in pyproject.toml:
[tool.bumpcalver]
beta_format = "b{beta_count}" # PEP 440 style: 26.05.24.1b1, 26.05.24.1b2
rc_format = "rc{rc_count}" # PEP 440 style: 26.05.24.1rc1
release_format = ".release" # literal suffix (no counter)
The {beta_count} placeholder auto-increments when the same base version already has a beta suffix in the file; it resets to 1 when the base version changes.
bumpcalver --beta # → 26.05.24.1b1 (first beta of this build)
bumpcalver --beta # → 26.05.24.1b2 (second beta of the same build)
bumpcalver --build --beta # → 26.05.24.2b1 (new build, counter resets)
Hybrid Semantic + Calendar Versioning¶
Combine a SemVer prefix with a CalVer date to signal both maturity and release timing:
[tool.bumpcalver]
major = 1
minor = 0
patch = 0
version_format = "{major}.{minor}-{current_date}.{build_count}"
date_format = "%Y%m%d"
# Standard build — uses major/minor from config
bumpcalver --build
# → 1.0-20260523.1
# Bump minor and rebuild in one step
bumpcalver --build --bump minor
# → 1.1-20260523.1 (config updated: minor = 1)
# Bump major (resets minor and patch to 0)
bumpcalver --build --bump major
# → 2.0-20260523.1 (config updated: major = 2, minor = 0, patch = 0)
See the Hybrid Versioning Guide for full details.
Safety Net Workflow¶
Use undo functionality as a safety net during development:
# Make experimental version bump
bumpcalver --custom "experimental"
# Test your changes...
# If tests pass, make official version
bumpcalver --undo # Undo experimental version
bumpcalver --build --git-tag --auto-commit # Official version
# If tests fail, just undo
bumpcalver --undo # Back to original state
For complete undo documentation, see Undo Docs.
Documentation¶
For comprehensive information about BumpCalver, check out our documentation:
- QuickStart Guide - Get started with BumpCalver quickly
- Calendar Versioning Guide - Comprehensive guide to calendar versioning patterns, real-world examples, and best practices
- Hybrid Versioning Guide - Combining semantic version prefixes (
1.0) with calendar dates for dual-signal versioning - Development Guide - How to contribute to the project, development setup, testing procedures, and PR guidelines
- Undo Operations - How to revert version changes
- Hybrid Versioning Guide - Combining semantic version prefixes with calendar dates
For the full documentation site, visit: BumpCalver CLI Documentation
Error Handling¶
- Unknown Timezone: If an invalid timezone is specified, the default timezone (
America/New_York) is used, and a warning is printed. - File Not Found: If a specified file is not found during version update, an error message is printed.
- Invalid Build Count: If the existing build count in a file is invalid, it resets to
1, and a warning is printed. - Git Errors: Errors during Git operations are caught, and an error message is displayed.
- Malformed Configuration: If the
pyproject.tomlfile is malformed, an error is printed, and the program exits.
Support¶
For issues or questions, please open an issue on the project's repository.
Quick Start¶
Install¶
pip install bumpcalver
Usage¶
Initialize Configuration¶
Create a pyproject.toml file in your project's root directory with the following content:
[tool.bumpcalver]
version_format = "{current_date}-{build_count:03}"
date_format = "%y.%m.%d"
timezone = "America/New_York"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "pyproject.toml"
file_type = "toml"
variable = "project.version"
version_standard = "python"
[[tool.bumpcalver.file]]
path = "examples/makefile"
file_type = "makefile"
variable = "APP_VERSION"
version_standard = "default"
[[tool.bumpcalver.file]]
path = "sonar-project.properties"
file_type = "properties"
variable = "sonar.projectVersion"
version_standard = "default"
[[tool.bumpcalver.file]]
path = ".env"
file_type = "env"
variable = "VERSION"
version_standard = "default"
[[tool.bumpcalver.file]]
path = "setup.cfg"
file_type = "setup.cfg"
variable = "metadata.version"
version_standard = "python"
This configuration tells BumpCalver how to format your version strings, which timezone to use, and which files to update.
Basic Version Bump¶
To bump the version using the current date and build count:
bumpcalver --build
This command will:
- Increment the build count for the current date.
- Update the version in all files listed under
[[tool.bumpcalver.file]]. - Use the timezone specified in your configuration (
America/New_Yorkin this example).
Pre-release Versioning¶
To create a beta version:
bumpcalver --build --beta
This appends .beta to the version by default, producing a version like 26.05.24.1.beta. You can configure the suffix format (including PEP 440-style counters like b{beta_count}) via the beta_format key in [tool.bumpcalver]. See Configuration Examples for details.
Specify Timezone¶
To use a specific timezone (overriding the configuration):
bumpcalver --build --timezone Europe/London
Create a Git Tag with Auto-Commit¶
To bump the version, commit changes, and create a Git tag:
bumpcalver --build --git-tag --auto-commit
This command will:
- Update the version as before.
- Commit the changes to Git.
- Create a Git tag with the new version.
Additional Options¶
- Disable Git Tagging:
bumpcalver --build --no-git-tag
- Disable Auto-Commit:
bumpcalver --build --no-auto-commit
Create Custom Date Formats¶
The date_format option in the configuration file allows you to customize the date format used in version strings. Here are some examples of how to format dates:
%Y.%m.%d- Full year, month, and day (e.g.,2024.12.25)%y.%m.%d- Year without century, month, and day (e.g.,24.12.25)%y.Q%q- Year and quarter (e.g.,24.Q1)%y.%m- Year and month (e.g.,24.12)%y.%j- Year and day of the year (e.g.,24.001for January 1st, 2024)%Y.%j- Full year and day of the year (e.g.,2024.001for January 1st, 2024)%Y.%m- Full year and month (e.g.,2024.12)%Y.Q%q- Full year and quarter (e.g.,2024.Q1)
For comprehensive information about calendar versioning patterns, real-world examples, and best practices, see our Calendar Versioning Guide.
See Documentation¶
For more examples and advanced usage, visit the BumpCalver documentation or the GitHub repository.
Example version.py File¶
Ensure that your version.py file (or the file specified in your configuration) contains the version variable:
__version__ = "0.1.0"
After running bumpcalver --build, it will be updated to (using date_format = "%y.%m.%d" and today's date):
__version__ = "26.05.24-001"
Integrate with Your Project¶
You can import the version into your application as needed:
from version import __version__
print(f"Current version: {__version__}")
Summary¶
With BumpCalver, you can automate version management based on the calendar date and build counts, ensuring consistent and meaningful version numbers across your project.
Calendar Versioning (CalVer) Guide¶
Overview¶
BumpCalver supports a comprehensive range of calendar versioning patterns based on the CalVer specification and real-world industry practices. This guide walks you through the various date formats available and provides practical examples for different use cases.
What is Calendar Versioning?¶
Calendar Versioning (CalVer) is a versioning scheme that uses dates as the primary versioning identifier. Unlike Semantic Versioning (SemVer), CalVer provides immediate context about when a release was made, making it ideal for:
- Regular Release Cycles: Software released on a schedule (Ubuntu, VS Code)
- Date-Sensitive Projects: When knowing the release date is crucial
- Long-Term Support: Identifying support lifecycles by date
- Marketing Alignment: Aligning technical releases with business timelines
Supported Date Format Patterns¶
Basic Year-Month-Day Patterns¶
These are the most common calendar versioning patterns:
Dot-Separated Formats¶
# Ubuntu-style: Short year with month and day
date_format = "%y.%m.%d" # Example: 24.12.07
# Full year variant
date_format = "%Y.%m.%d" # Example: 2024.12.07
# Month only (common for regular releases)
date_format = "%y.%m" # Example: 24.12
date_format = "%Y.%m" # Example: 2024.12
Hyphen-Separated Formats (ISO 8601)¶
# ISO date format
date_format = "%Y-%m-%d" # Example: 2024-12-07
# With build count
version_format = "{current_date}-{build_count:03}"
# Result: 2024-12-07-001
Quarter-Based Patterns¶
Perfect for quarterly releases and business cycles:
# Short year with quarter
date_format = "%y.Q%q" # Example: 24.Q4
# Full year with quarter
date_format = "%Y.Q%q" # Example: 2024.Q4
# With build count
version_format = "{current_date}.{build_count:03}"
# Result: 24.Q4.001
Week-Based Patterns¶
Ideal for agile development with weekly releases:
# ISO week numbers
date_format = "%y.%V" # Example: 24.49 (week 49)
date_format = "%Y.%V" # Example: 2024.49
# Version with build count
version_format = "{current_date}.{build_count:03}"
# Result: 24.49.001
Day-of-Year Patterns (Julian)¶
Common in embedded systems and specialized applications:
# Julian day format
date_format = "%y.%j" # Example: 24.342 (day 342 of year)
date_format = "%Y.%j" # Example: 2024.342
# Useful for daily builds
version_format = "{current_date}.{build_count:03}"
# Result: 24.342.001
Compact Formats¶
No separators for maximum brevity:
# Compact date formats
date_format = "%y%m%d" # Example: 241207
date_format = "%Y%m%d" # Example: 20241207
version_format = "{current_date}.{build_count:03}"
# Result: 241207.001
Real-World Examples¶
Ubuntu Style (LTS and Regular Releases)¶
[tool.bumpcalver]
version_format = "{current_date}"
date_format = "%y.%m"
# Examples: 24.04, 24.10, 26.04 (LTS)
Microsoft Visual Studio Code¶
[tool.bumpcalver]
version_format = "{current_date}.{build_count}"
date_format = "%Y.%m"
# Examples: 2024.11.1, 2024.11.2
Python Twisted Framework¶
[tool.bumpcalver]
version_format = "{current_date}.{build_count}"
date_format = "%y.%m"
# Examples: 24.3.0, 24.7.0
Business Quarterly Releases¶
[tool.bumpcalver]
version_format = "{current_date}.{build_count:02}"
date_format = "%Y.Q%q"
timezone = "America/New_York"
# Examples: 2024.Q4.01, 2025.Q1.01
Daily Build System¶
[tool.bumpcalver]
version_format = "{current_date}.{build_count:03}"
date_format = "%y.%j"
# Examples: 24.342.001, 24.342.002
Language-Specific Support¶
Python Ecosystem¶
Python packages using CalVer are fully supported with PEP 440 compliance:
[[tool.bumpcalver.file]]
path = "pyproject.toml"
file_type = "toml"
variable = "project.version"
version_standard = "python" # Converts hyphens to dots for PEP 440
PEP 440 Transformation:
- Input: 2024-12-07-001
- Python Output: 2024.12.7.1
Popular Python Projects Using CalVer:
- Twisted: 24.3.0 (YY.M.patch)
- pip: 24.3.1 (YY.M.patch)
- setuptools: 75.6.0 (YY.M.patch)
- certifi: 2024.12.14 (YYYY.MM.DD)
JavaScript/Node.js Ecosystem¶
[[tool.bumpcalver.file]]
path = "package.json"
file_type = "json"
variable = "version"
version_standard = "default"
Docker Images¶
[[tool.bumpcalver.file]]
path = "Dockerfile"
file_type = "dockerfile"
variable = "ARG.VERSION"
version_standard = "default"
Make-based Projects¶
[[tool.bumpcalver.file]]
path = "Makefile"
file_type = "makefile"
variable = "APP_VERSION"
version_standard = "default"
Advanced Patterns¶
Pre-release Suffixes¶
BumpCalver supports configurable pre-release suffixes via --beta, --rc, and --release. The default suffix format produces dot-separated labels:
bumpcalver --build --beta # Result: 24.Q4.001.beta
bumpcalver --build --rc # Result: 24.Q4.001.rc
bumpcalver --build --release # Result: 24.Q4.001.release
Configure PEP 440-style suffixes with an auto-incrementing counter:
[tool.bumpcalver]
beta_format = "b{beta_count}" # → 24.Q4.001b1, 24.Q4.001b2, …
rc_format = "rc{rc_count}" # → 24.Q4.001rc1, 24.Q4.001rc2, …
The counter increments when the same base version is re-tagged as a new pre-release, and resets to 1 when the base version changes (e.g., a new day or new --build). See Configuration Examples for the full reference table.
Hybrid Semantic + Calendar Versioning¶
For projects that want to keep a familiar SemVer prefix (1.0, 2.3) while also showing release dates, BumpCalver supports hybrid formats using {major}, {minor}, and {patch} placeholders:
[tool.bumpcalver]
major = 1
minor = 0
version_format = "{major}.{minor}-{current_date}.{build_count}"
date_format = "%Y%m%d"
# Produces: 1.0-20260523.1
Bump the semantic prefix from the CLI:
bumpcalver --build --bump minor # → 1.1-20260523.1
bumpcalver --build --bump major # → 2.0-20260523.1
See the Hybrid Versioning Guide for the full list of supported formats, CLI options, and best practices.
Mixed Separators (Limited Support)¶
While not fully supported, simple mixed separators work:
# Limited support for mixed separators
version_format = "{current_date}_{build_count:03}"
date_format = "%Y-%m-%d"
# May produce: 2024-12-07_001
Custom Business Cycles¶
# Financial year quarters (example: July start)
version_format = "FY{current_date}.{build_count:02}"
date_format = "%y.Q%q"
timezone = "America/New_York"
# Examples: FY24.Q2.01, FY24.Q3.01
Choosing the Right Format¶
Consider Your Release Cycle¶
| Release Frequency | Recommended Pattern | Example |
|---|---|---|
| Monthly | %Y.%m |
2024.12 |
| Quarterly | %y.Q%q |
24.Q4 |
| Weekly | %y.%V |
24.49 |
| Daily | %y.%j |
24.342 |
| Multiple Daily | %y.%m.%d |
24.12.07 |
Consider Your Audience¶
| Audience | Recommended Pattern | Reasoning |
|---|---|---|
| End Users | %Y.%m |
Clear, human-readable |
| Developers | %y.%m.%d |
Detailed, compact |
| Enterprise | %Y.Q%q |
Aligns with business quarters |
| CI/CD Systems | %y.%j |
Daily builds, sequential |
Consider Your Ecosystem¶
| Language/Platform | Considerations |
|---|---|
| Python | Use version_standard = "python" for PEP 440 |
| Node.js | Standard dot notation works well |
| Docker | Short formats recommended for tags |
| Git Tags | Avoid special characters, prefer dots/hyphens |
Best Practices¶
1. Consistency¶
# Good: Consistent separator usage
date_format = "%y.%m.%d"
version_format = "{current_date}.{build_count:03}"
# Avoid: Mixed separators
version_format = "{current_date}-{build_count:03}" # Different separator
2. Timezone Awareness¶
# Always specify timezone for distributed teams
timezone = "UTC" # Global teams
timezone = "America/New_York" # US East Coast
timezone = "Europe/London" # UK/EU
3. Build Count Padding¶
# Good: Consistent width for sorting
version_format = "{current_date}.{build_count:03}" # 001, 002, 010
version_format = "{current_date}.{build_count:02}" # 01, 02, 10
# Avoid: Variable width
version_format = "{current_date}.{build_count}" # 1, 2, 10 (poor sorting)
4. Documentation¶
# Document your versioning strategy
[tool.bumpcalver]
# Strategy: Quarterly releases with weekly build counts
# Format: YY.QQ.BBB (Year.Quarter.Build)
# Example: 24.Q4.001 = Q4 2024, first build
version_format = "{current_date}.{build_count:03}"
date_format = "%y.Q%q"
Testing Your Format¶
# Check recent version bump history to confirm parsing is working
bumpcalver --list-history
Troubleshooting¶
Common Issues¶
-
Mixed Separators Not Working
Error: Version '2024-12-07_001' does not match format Solution: Use consistent separators throughout -
Invalid Year Format
Error: Version 'v24.12.001' rejected Solution: Remove prefixes, ensure year starts version -
Quarter Format Not Recognized
Error: %q not recognized Solution: Use %y.Q%q format, ensure Q is literal
Getting Help¶
- Check the examples directory for working configurations
- Review the test suite for validated patterns
- Open an issue on GitHub for support
This guide covers the comprehensive calendar versioning capabilities of BumpCalver. For more specific use cases or custom requirements, please refer to the API documentation or reach out to the community.
Hybrid Semantic + Calendar Versioning Guide¶
Overview¶
BumpCalver supports hybrid versioning — version strings that combine a Semantic Versioning (SemVer) prefix with a Calendar Versioning (CalVer) date and build count.
A hybrid version communicates two things at once:
- The semantic prefix (
1.0,2.3.1) signals project maturity and compatibility, just like SemVer. - The calendar suffix (
20260523.1) shows exactly when the release was made, just like CalVer.
Example: 1.0-20260523.1
Why Use Hybrid Versioning?¶
| Versioning Style | Strength | Weakness |
|---|---|---|
Pure SemVer (1.4.2) |
Communicates stability and compatibility | No release-date context |
Pure CalVer (2026.05.23.1) |
Shows when a release happened | No maturity signal |
Hybrid (1.0-20260523.1) |
Both signals in one string | Slightly longer version string |
Hybrid versioning is a practical choice for:
- Libraries that want to signal production readiness (
1.0) while keeping release dates visible. - Long-running projects that keep a stable API but release frequently.
- Teams migrating from SemVer who want to add temporal context without abandoning familiar version milestones.
Format Placeholders¶
Hybrid versioning adds three new placeholders alongside the existing {current_date} and {build_count}:
| Placeholder | Description | Source |
|---|---|---|
{major} |
Major version component | major key in config |
{minor} |
Minor version component | minor key in config |
{patch} |
Patch version component | patch key in config |
{current_date} |
Today's date, formatted by date_format |
Computed at runtime |
{build_count} |
Incrementing build number | Computed at runtime |
When any of {major}, {minor}, or {patch} appear in version_format, BumpCalver enters hybrid mode and includes the semantic prefix in the generated version.
Configuration¶
Add major, minor, patch keys to the [tool.bumpcalver] section alongside your existing settings:
[tool.bumpcalver]
major = 1
minor = 0
patch = 0
version_format = "{major}.{minor}-{current_date}.{build_count}"
date_format = "%Y%m%d"
timezone = "America/New_York"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "pyproject.toml"
file_type = "toml"
variable = "project.version"
[[tool.bumpcalver.file]]
path = "src/mypackage/__init__.py"
file_type = "python"
variable = "__version__"
Or in a standalone bumpcalver.toml:
major = 1
minor = 0
patch = 0
version_format = "{major}.{minor}-{current_date}.{build_count}"
date_format = "%Y%m%d"
timezone = "America/New_York"
[[file]]
path = "pyproject.toml"
file_type = "toml"
variable = "project.version"
Supported Format Examples¶
Any combination of semantic placeholders, separators, date formats, and build count formatting is supported:
version_format |
date_format |
Example output |
|---|---|---|
{major}.{minor}-{current_date}.{build_count} |
%Y%m%d |
1.0-20260523.1 |
{major}.{minor}.{patch}-{current_date}.{build_count:03} |
%Y%m%d |
1.0.0-20260523.001 |
{major}.{minor}-{current_date}.{build_count:03} |
%Y.%m.%d |
1.0-2026.05.23.001 |
{major}.{minor}-{current_date}-{build_count:02} |
%Y%m%d |
2.3-20260523-01 |
{major}.{minor}-{current_date}.{build_count} |
%y.Q%q |
1.0-26.Q2.5 |
{major}.{minor}.{patch}-{current_date}.{build_count} |
%Y%m%d |
2.3.4-20260523.10 |
CLI Usage¶
Generating a hybrid version¶
Use --build just as you would for pure CalVer:
bumpcalver --build
# → 1.0-20260523.1
Run again the same day:
bumpcalver --build
# → 1.0-20260523.2 (build count increments)
Run on a new day:
bumpcalver --build
# → 1.0-20260524.1 (date changes, count resets to 1)
Bumping the semantic prefix¶
Use --bump to increment a semantic component. The new value is written back to pyproject.toml (or bumpcalver.toml) automatically so the next plain --build continues from the updated baseline.
# Increment minor version: minor 0→1, patch resets to 0
bumpcalver --build --bump minor
# Config updated: minor = 1, patch = 0
# → 1.1-20260523.1
# Increment major version: major 1→2, minor and patch reset to 0
bumpcalver --build --bump major
# Config updated: major = 2, minor = 0, patch = 0
# → 2.0-20260523.1
# Increment patch version
bumpcalver --build --bump patch
# Config updated: patch = 1
# → 1.0-20260523.1 (with {patch} in format: 1.0.1-20260523.1)
--bump accepts major, minor, or patch as values:
--bump [major|minor|patch] Increment the specified semantic version
component in config
Combining with other options¶
All existing options work alongside --bump:
# Bump minor and tag the release
bumpcalver --build --bump minor --git-tag --auto-commit
# Create a release candidate at a new minor version
bumpcalver --build --bump minor --rc
# → 1.1-20260523.1.rc
How Build Count Increment Works¶
When you run bumpcalver --build with a hybrid format, the library:
- Reads the current version from the first configured file (e.g.,
1.0-20260522.4). - Uses the
version_formatas a regex template to extract the date part (20260522) and build count (4). - Compares the extracted date to today.
- Same day → build count increments by 1.
- Different day → build count resets to 1.
- Applies the
major,minor,patchvalues from config (unchanged unless--bumpwas used). - Formats and writes the new version:
1.0-20260523.1.
The semantic prefix is never parsed or incremented automatically — it only comes from the config values.
Pre-release Suffixes¶
Hybrid versions work with all existing suffix options:
bumpcalver --build --beta
# → 1.0-20260523.1.beta
bumpcalver --build --rc
# → 1.0-20260523.1.rc
bumpcalver --build --custom alpha
# → 1.0-20260523.1.alpha
PEP 440 Considerations¶
When version_standard = "python" is set on a file, BumpCalver applies PEP 440 normalization (converts hyphens to dots, removes leading zeros). A hybrid version like 1.0-20260523.1 would become 1.0.20260523.1.
If you want to preserve the hyphen separator, either:
- Omit
version_standard(defaults to"default", no transformation). - Use a dot separator in your format:
{major}.{minor}.{current_date}.{build_count}→1.0.20260523.1.
Best Practices¶
1. Keep the semantic prefix stable between releases¶
The major, minor, and patch values in config are your deliberate milestones. Only update them when you intentionally want to signal a compatibility or maturity change — not on every build.
2. Use --bump when the API changes¶
# Breaking change → bump major
bumpcalver --build --bump major --git-tag --auto-commit
# New backward-compatible feature → bump minor
bumpcalver --build --bump minor --git-tag --auto-commit
3. Choose a separator that fits your ecosystem¶
# Hyphen (most common hybrid separator)
version_format = "{major}.{minor}-{current_date}.{build_count}"
# Dot only (PEP 440 safe)
version_format = "{major}.{minor}.{current_date}.{build_count}"
4. Pad the build count for consistent sort order¶
version_format = "{major}.{minor}-{current_date}.{build_count:03}"
# → 1.0-20260523.001 instead of 1.0-20260523.1
Troubleshooting¶
Version not parsing on next build¶
If the format stored in a file does not match the current version_format, parsing fails and the build count resets to 1. This is safe — the tool logs a message and continues. It commonly happens when:
- You changed
version_formatafter the last build. - You manually edited the version string.
Semantic values showing as 0¶
If major, minor, or patch are not set in config, they default to 0. Add them explicitly:
[tool.bumpcalver]
major = 1
minor = 0
patch = 0
--bump not persisting to config¶
--bump writes back to pyproject.toml or bumpcalver.toml using regex matching. It requires the key to already exist in the file. If the key is absent, add it manually first.
See Also¶
- Calendar Versioning Guide — pure CalVer patterns and date formats
- Configuration Examples — full configuration reference
- Undo Operations — reverting version bumps
Timezones¶
Here is a list of all timezones that can be utilized. You can search for a specific timezone by typing in the search bar.
This table is generated at build time from Python's own zoneinfo.available_timezones()
by scripts/mkdocs_hooks.py
(registered via mkdocs.yml's hooks: key) — it always reflects whatever
tzdata built the docs, and there is exactly one copy of this data in the
repository rather than a hand-maintained duplicate.
| Timezone | UTC Offset |
|---|---|
| Africa/Abidjan | UTC+00:00 |
| Africa/Accra | UTC+00:00 |
| Africa/Addis_Ababa | UTC+03:00 |
| Africa/Algiers | UTC+01:00 |
| Africa/Asmara | UTC+03:00 |
| Africa/Asmera | UTC+03:00 |
| Africa/Bamako | UTC+00:00 |
| Africa/Bangui | UTC+01:00 |
| Africa/Banjul | UTC+00:00 |
| Africa/Bissau | UTC+00:00 |
| Africa/Blantyre | UTC+02:00 |
| Africa/Brazzaville | UTC+01:00 |
| Africa/Bujumbura | UTC+02:00 |
| Africa/Cairo | UTC+03:00 |
| Africa/Casablanca | UTC+01:00 |
| Africa/Ceuta | UTC+02:00 |
| Africa/Conakry | UTC+00:00 |
| Africa/Dakar | UTC+00:00 |
| Africa/Dar_es_Salaam | UTC+03:00 |
| Africa/Djibouti | UTC+03:00 |
| Africa/Douala | UTC+01:00 |
| Africa/El_Aaiun | UTC+01:00 |
| Africa/Freetown | UTC+00:00 |
| Africa/Gaborone | UTC+02:00 |
| Africa/Harare | UTC+02:00 |
| Africa/Johannesburg | UTC+02:00 |
| Africa/Juba | UTC+02:00 |
| Africa/Kampala | UTC+03:00 |
| Africa/Khartoum | UTC+02:00 |
| Africa/Kigali | UTC+02:00 |
| Africa/Kinshasa | UTC+01:00 |
| Africa/Lagos | UTC+01:00 |
| Africa/Libreville | UTC+01:00 |
| Africa/Lome | UTC+00:00 |
| Africa/Luanda | UTC+01:00 |
| Africa/Lubumbashi | UTC+02:00 |
| Africa/Lusaka | UTC+02:00 |
| Africa/Malabo | UTC+01:00 |
| Africa/Maputo | UTC+02:00 |
| Africa/Maseru | UTC+02:00 |
| Africa/Mbabane | UTC+02:00 |
| Africa/Mogadishu | UTC+03:00 |
| Africa/Monrovia | UTC+00:00 |
| Africa/Nairobi | UTC+03:00 |
| Africa/Ndjamena | UTC+01:00 |
| Africa/Niamey | UTC+01:00 |
| Africa/Nouakchott | UTC+00:00 |
| Africa/Ouagadougou | UTC+00:00 |
| Africa/Porto-Novo | UTC+01:00 |
| Africa/Sao_Tome | UTC+00:00 |
| Africa/Timbuktu | UTC+00:00 |
| Africa/Tripoli | UTC+02:00 |
| Africa/Tunis | UTC+01:00 |
| Africa/Windhoek | UTC+02:00 |
| America/Adak | UTC-09:00 |
| America/Anchorage | UTC-08:00 |
| America/Anguilla | UTC-04:00 |
| America/Antigua | UTC-04:00 |
| America/Araguaina | UTC-03:00 |
| America/Argentina/Buenos_Aires | UTC-03:00 |
| America/Argentina/Catamarca | UTC-03:00 |
| America/Argentina/ComodRivadavia | UTC-03:00 |
| America/Argentina/Cordoba | UTC-03:00 |
| America/Argentina/Jujuy | UTC-03:00 |
| America/Argentina/La_Rioja | UTC-03:00 |
| America/Argentina/Mendoza | UTC-03:00 |
| America/Argentina/Rio_Gallegos | UTC-03:00 |
| America/Argentina/Salta | UTC-03:00 |
| America/Argentina/San_Juan | UTC-03:00 |
| America/Argentina/San_Luis | UTC-03:00 |
| America/Argentina/Tucuman | UTC-03:00 |
| America/Argentina/Ushuaia | UTC-03:00 |
| America/Aruba | UTC-04:00 |
| America/Asuncion | UTC-03:00 |
| America/Atikokan | UTC-05:00 |
| America/Atka | UTC-09:00 |
| America/Bahia | UTC-03:00 |
| America/Bahia_Banderas | UTC-06:00 |
| America/Barbados | UTC-04:00 |
| America/Belem | UTC-03:00 |
| America/Belize | UTC-06:00 |
| America/Blanc-Sablon | UTC-04:00 |
| America/Boa_Vista | UTC-04:00 |
| America/Bogota | UTC-05:00 |
| America/Boise | UTC-06:00 |
| America/Buenos_Aires | UTC-03:00 |
| America/Cambridge_Bay | UTC-06:00 |
| America/Campo_Grande | UTC-04:00 |
| America/Cancun | UTC-05:00 |
| America/Caracas | UTC-04:00 |
| America/Catamarca | UTC-03:00 |
| America/Cayenne | UTC-03:00 |
| America/Cayman | UTC-05:00 |
| America/Chicago | UTC-05:00 |
| America/Chihuahua | UTC-06:00 |
| America/Ciudad_Juarez | UTC-06:00 |
| America/Coral_Harbour | UTC-05:00 |
| America/Cordoba | UTC-03:00 |
| America/Costa_Rica | UTC-06:00 |
| America/Coyhaique | UTC-03:00 |
| America/Creston | UTC-07:00 |
| America/Cuiaba | UTC-04:00 |
| America/Curacao | UTC-04:00 |
| America/Danmarkshavn | UTC+00:00 |
| America/Dawson | UTC-07:00 |
| America/Dawson_Creek | UTC-07:00 |
| America/Denver | UTC-06:00 |
| America/Detroit | UTC-04:00 |
| America/Dominica | UTC-04:00 |
| America/Edmonton | UTC-06:00 |
| America/Eirunepe | UTC-05:00 |
| America/El_Salvador | UTC-06:00 |
| America/Ensenada | UTC-07:00 |
| America/Fort_Nelson | UTC-07:00 |
| America/Fort_Wayne | UTC-04:00 |
| America/Fortaleza | UTC-03:00 |
| America/Glace_Bay | UTC-03:00 |
| America/Godthab | UTC-01:00 |
| America/Goose_Bay | UTC-03:00 |
| America/Grand_Turk | UTC-04:00 |
| America/Grenada | UTC-04:00 |
| America/Guadeloupe | UTC-04:00 |
| America/Guatemala | UTC-06:00 |
| America/Guayaquil | UTC-05:00 |
| America/Guyana | UTC-04:00 |
| America/Halifax | UTC-03:00 |
| America/Havana | UTC-04:00 |
| America/Hermosillo | UTC-07:00 |
| America/Indiana/Indianapolis | UTC-04:00 |
| America/Indiana/Knox | UTC-05:00 |
| America/Indiana/Marengo | UTC-04:00 |
| America/Indiana/Petersburg | UTC-04:00 |
| America/Indiana/Tell_City | UTC-05:00 |
| America/Indiana/Vevay | UTC-04:00 |
| America/Indiana/Vincennes | UTC-04:00 |
| America/Indiana/Winamac | UTC-04:00 |
| America/Indianapolis | UTC-04:00 |
| America/Inuvik | UTC-06:00 |
| America/Iqaluit | UTC-04:00 |
| America/Jamaica | UTC-05:00 |
| America/Jujuy | UTC-03:00 |
| America/Juneau | UTC-08:00 |
| America/Kentucky/Louisville | UTC-04:00 |
| America/Kentucky/Monticello | UTC-04:00 |
| America/Knox_IN | UTC-05:00 |
| America/Kralendijk | UTC-04:00 |
| America/La_Paz | UTC-04:00 |
| America/Lima | UTC-05:00 |
| America/Los_Angeles | UTC-07:00 |
| America/Louisville | UTC-04:00 |
| America/Lower_Princes | UTC-04:00 |
| America/Maceio | UTC-03:00 |
| America/Managua | UTC-06:00 |
| America/Manaus | UTC-04:00 |
| America/Marigot | UTC-04:00 |
| America/Martinique | UTC-04:00 |
| America/Matamoros | UTC-05:00 |
| America/Mazatlan | UTC-07:00 |
| America/Mendoza | UTC-03:00 |
| America/Menominee | UTC-05:00 |
| America/Merida | UTC-06:00 |
| America/Metlakatla | UTC-08:00 |
| America/Mexico_City | UTC-06:00 |
| America/Miquelon | UTC-02:00 |
| America/Moncton | UTC-03:00 |
| America/Monterrey | UTC-06:00 |
| America/Montevideo | UTC-03:00 |
| America/Montreal | UTC-04:00 |
| America/Montserrat | UTC-04:00 |
| America/Nassau | UTC-04:00 |
| America/New_York | UTC-04:00 |
| America/Nipigon | UTC-04:00 |
| America/Nome | UTC-08:00 |
| America/Noronha | UTC-02:00 |
| America/North_Dakota/Beulah | UTC-05:00 |
| America/North_Dakota/Center | UTC-05:00 |
| America/North_Dakota/New_Salem | UTC-05:00 |
| America/Nuuk | UTC-01:00 |
| America/Ojinaga | UTC-05:00 |
| America/Panama | UTC-05:00 |
| America/Pangnirtung | UTC-04:00 |
| America/Paramaribo | UTC-03:00 |
| America/Phoenix | UTC-07:00 |
| America/Port-au-Prince | UTC-04:00 |
| America/Port_of_Spain | UTC-04:00 |
| America/Porto_Acre | UTC-05:00 |
| America/Porto_Velho | UTC-04:00 |
| America/Puerto_Rico | UTC-04:00 |
| America/Punta_Arenas | UTC-03:00 |
| America/Rainy_River | UTC-05:00 |
| America/Rankin_Inlet | UTC-05:00 |
| America/Recife | UTC-03:00 |
| America/Regina | UTC-06:00 |
| America/Resolute | UTC-05:00 |
| America/Rio_Branco | UTC-05:00 |
| America/Rosario | UTC-03:00 |
| America/Santa_Isabel | UTC-07:00 |
| America/Santarem | UTC-03:00 |
| America/Santiago | UTC-04:00 |
| America/Santo_Domingo | UTC-04:00 |
| America/Sao_Paulo | UTC-03:00 |
| America/Scoresbysund | UTC-01:00 |
| America/Shiprock | UTC-06:00 |
| America/Sitka | UTC-08:00 |
| America/St_Barthelemy | UTC-04:00 |
| America/St_Johns | UTC-02:30 |
| America/St_Kitts | UTC-04:00 |
| America/St_Lucia | UTC-04:00 |
| America/St_Thomas | UTC-04:00 |
| America/St_Vincent | UTC-04:00 |
| America/Swift_Current | UTC-06:00 |
| America/Tegucigalpa | UTC-06:00 |
| America/Thule | UTC-03:00 |
| America/Thunder_Bay | UTC-04:00 |
| America/Tijuana | UTC-07:00 |
| America/Toronto | UTC-04:00 |
| America/Tortola | UTC-04:00 |
| America/Vancouver | UTC-07:00 |
| America/Virgin | UTC-04:00 |
| America/Whitehorse | UTC-07:00 |
| America/Winnipeg | UTC-05:00 |
| America/Yakutat | UTC-08:00 |
| America/Yellowknife | UTC-06:00 |
| Antarctica/Casey | UTC+08:00 |
| Antarctica/Davis | UTC+07:00 |
| Antarctica/DumontDUrville | UTC+10:00 |
| Antarctica/Macquarie | UTC+10:00 |
| Antarctica/Mawson | UTC+05:00 |
| Antarctica/McMurdo | UTC+12:00 |
| Antarctica/Palmer | UTC-03:00 |
| Antarctica/Rothera | UTC-03:00 |
| Antarctica/South_Pole | UTC+12:00 |
| Antarctica/Syowa | UTC+03:00 |
| Antarctica/Troll | UTC+02:00 |
| Antarctica/Vostok | UTC+05:00 |
| Arctic/Longyearbyen | UTC+02:00 |
| Asia/Aden | UTC+03:00 |
| Asia/Almaty | UTC+05:00 |
| Asia/Amman | UTC+03:00 |
| Asia/Anadyr | UTC+12:00 |
| Asia/Aqtau | UTC+05:00 |
| Asia/Aqtobe | UTC+05:00 |
| Asia/Ashgabat | UTC+05:00 |
| Asia/Ashkhabad | UTC+05:00 |
| Asia/Atyrau | UTC+05:00 |
| Asia/Baghdad | UTC+03:00 |
| Asia/Bahrain | UTC+03:00 |
| Asia/Baku | UTC+04:00 |
| Asia/Bangkok | UTC+07:00 |
| Asia/Barnaul | UTC+07:00 |
| Asia/Beirut | UTC+03:00 |
| Asia/Bishkek | UTC+06:00 |
| Asia/Brunei | UTC+08:00 |
| Asia/Calcutta | UTC+05:30 |
| Asia/Chita | UTC+09:00 |
| Asia/Choibalsan | UTC+08:00 |
| Asia/Chongqing | UTC+08:00 |
| Asia/Chungking | UTC+08:00 |
| Asia/Colombo | UTC+05:30 |
| Asia/Dacca | UTC+06:00 |
| Asia/Damascus | UTC+03:00 |
| Asia/Dhaka | UTC+06:00 |
| Asia/Dili | UTC+09:00 |
| Asia/Dubai | UTC+04:00 |
| Asia/Dushanbe | UTC+05:00 |
| Asia/Famagusta | UTC+03:00 |
| Asia/Gaza | UTC+03:00 |
| Asia/Harbin | UTC+08:00 |
| Asia/Hebron | UTC+03:00 |
| Asia/Ho_Chi_Minh | UTC+07:00 |
| Asia/Hong_Kong | UTC+08:00 |
| Asia/Hovd | UTC+07:00 |
| Asia/Irkutsk | UTC+08:00 |
| Asia/Istanbul | UTC+03:00 |
| Asia/Jakarta | UTC+07:00 |
| Asia/Jayapura | UTC+09:00 |
| Asia/Jerusalem | UTC+03:00 |
| Asia/Kabul | UTC+04:30 |
| Asia/Kamchatka | UTC+12:00 |
| Asia/Karachi | UTC+05:00 |
| Asia/Kashgar | UTC+06:00 |
| Asia/Kathmandu | UTC+05:45 |
| Asia/Katmandu | UTC+05:45 |
| Asia/Khandyga | UTC+09:00 |
| Asia/Kolkata | UTC+05:30 |
| Asia/Krasnoyarsk | UTC+07:00 |
| Asia/Kuala_Lumpur | UTC+08:00 |
| Asia/Kuching | UTC+08:00 |
| Asia/Kuwait | UTC+03:00 |
| Asia/Macao | UTC+08:00 |
| Asia/Macau | UTC+08:00 |
| Asia/Magadan | UTC+11:00 |
| Asia/Makassar | UTC+08:00 |
| Asia/Manila | UTC+08:00 |
| Asia/Muscat | UTC+04:00 |
| Asia/Nicosia | UTC+03:00 |
| Asia/Novokuznetsk | UTC+07:00 |
| Asia/Novosibirsk | UTC+07:00 |
| Asia/Omsk | UTC+06:00 |
| Asia/Oral | UTC+05:00 |
| Asia/Phnom_Penh | UTC+07:00 |
| Asia/Pontianak | UTC+07:00 |
| Asia/Pyongyang | UTC+09:00 |
| Asia/Qatar | UTC+03:00 |
| Asia/Qostanay | UTC+05:00 |
| Asia/Qyzylorda | UTC+05:00 |
| Asia/Rangoon | UTC+06:30 |
| Asia/Riyadh | UTC+03:00 |
| Asia/Saigon | UTC+07:00 |
| Asia/Sakhalin | UTC+11:00 |
| Asia/Samarkand | UTC+05:00 |
| Asia/Seoul | UTC+09:00 |
| Asia/Shanghai | UTC+08:00 |
| Asia/Singapore | UTC+08:00 |
| Asia/Srednekolymsk | UTC+11:00 |
| Asia/Taipei | UTC+08:00 |
| Asia/Tashkent | UTC+05:00 |
| Asia/Tbilisi | UTC+04:00 |
| Asia/Tehran | UTC+03:30 |
| Asia/Tel_Aviv | UTC+03:00 |
| Asia/Thimbu | UTC+06:00 |
| Asia/Thimphu | UTC+06:00 |
| Asia/Tokyo | UTC+09:00 |
| Asia/Tomsk | UTC+07:00 |
| Asia/Ujung_Pandang | UTC+08:00 |
| Asia/Ulaanbaatar | UTC+08:00 |
| Asia/Ulan_Bator | UTC+08:00 |
| Asia/Urumqi | UTC+06:00 |
| Asia/Ust-Nera | UTC+10:00 |
| Asia/Vientiane | UTC+07:00 |
| Asia/Vladivostok | UTC+10:00 |
| Asia/Yakutsk | UTC+09:00 |
| Asia/Yangon | UTC+06:30 |
| Asia/Yekaterinburg | UTC+05:00 |
| Asia/Yerevan | UTC+04:00 |
| Atlantic/Azores | UTC+00:00 |
| Atlantic/Bermuda | UTC-03:00 |
| Atlantic/Canary | UTC+01:00 |
| Atlantic/Cape_Verde | UTC-01:00 |
| Atlantic/Faeroe | UTC+01:00 |
| Atlantic/Faroe | UTC+01:00 |
| Atlantic/Jan_Mayen | UTC+02:00 |
| Atlantic/Madeira | UTC+01:00 |
| Atlantic/Reykjavik | UTC+00:00 |
| Atlantic/South_Georgia | UTC-02:00 |
| Atlantic/St_Helena | UTC+00:00 |
| Atlantic/Stanley | UTC-03:00 |
| Australia/ACT | UTC+10:00 |
| Australia/Adelaide | UTC+09:30 |
| Australia/Brisbane | UTC+10:00 |
| Australia/Broken_Hill | UTC+09:30 |
| Australia/Canberra | UTC+10:00 |
| Australia/Currie | UTC+10:00 |
| Australia/Darwin | UTC+09:30 |
| Australia/Eucla | UTC+08:45 |
| Australia/Hobart | UTC+10:00 |
| Australia/LHI | UTC+10:30 |
| Australia/Lindeman | UTC+10:00 |
| Australia/Lord_Howe | UTC+10:30 |
| Australia/Melbourne | UTC+10:00 |
| Australia/NSW | UTC+10:00 |
| Australia/North | UTC+09:30 |
| Australia/Perth | UTC+08:00 |
| Australia/Queensland | UTC+10:00 |
| Australia/South | UTC+09:30 |
| Australia/Sydney | UTC+10:00 |
| Australia/Tasmania | UTC+10:00 |
| Australia/Victoria | UTC+10:00 |
| Australia/West | UTC+08:00 |
| Australia/Yancowinna | UTC+09:30 |
| Brazil/Acre | UTC-05:00 |
| Brazil/DeNoronha | UTC-02:00 |
| Brazil/East | UTC-03:00 |
| Brazil/West | UTC-04:00 |
| CET | UTC+02:00 |
| CST6CDT | UTC-05:00 |
| Canada/Atlantic | UTC-03:00 |
| Canada/Central | UTC-05:00 |
| Canada/Eastern | UTC-04:00 |
| Canada/Mountain | UTC-06:00 |
| Canada/Newfoundland | UTC-02:30 |
| Canada/Pacific | UTC-07:00 |
| Canada/Saskatchewan | UTC-06:00 |
| Canada/Yukon | UTC-07:00 |
| Chile/Continental | UTC-04:00 |
| Chile/EasterIsland | UTC-06:00 |
| Cuba | UTC-04:00 |
| EET | UTC+03:00 |
| EST | UTC-05:00 |
| EST5EDT | UTC-04:00 |
| Egypt | UTC+03:00 |
| Eire | UTC+01:00 |
| Etc/GMT | UTC+00:00 |
| Etc/GMT+0 | UTC+00:00 |
| Etc/GMT+1 | UTC-01:00 |
| Etc/GMT+10 | UTC-10:00 |
| Etc/GMT+11 | UTC-11:00 |
| Etc/GMT+12 | UTC-12:00 |
| Etc/GMT+2 | UTC-02:00 |
| Etc/GMT+3 | UTC-03:00 |
| Etc/GMT+4 | UTC-04:00 |
| Etc/GMT+5 | UTC-05:00 |
| Etc/GMT+6 | UTC-06:00 |
| Etc/GMT+7 | UTC-07:00 |
| Etc/GMT+8 | UTC-08:00 |
| Etc/GMT+9 | UTC-09:00 |
| Etc/GMT-0 | UTC+00:00 |
| Etc/GMT-1 | UTC+01:00 |
| Etc/GMT-10 | UTC+10:00 |
| Etc/GMT-11 | UTC+11:00 |
| Etc/GMT-12 | UTC+12:00 |
| Etc/GMT-13 | UTC+13:00 |
| Etc/GMT-14 | UTC+14:00 |
| Etc/GMT-2 | UTC+02:00 |
| Etc/GMT-3 | UTC+03:00 |
| Etc/GMT-4 | UTC+04:00 |
| Etc/GMT-5 | UTC+05:00 |
| Etc/GMT-6 | UTC+06:00 |
| Etc/GMT-7 | UTC+07:00 |
| Etc/GMT-8 | UTC+08:00 |
| Etc/GMT-9 | UTC+09:00 |
| Etc/GMT0 | UTC+00:00 |
| Etc/Greenwich | UTC+00:00 |
| Etc/UCT | UTC+00:00 |
| Etc/UTC | UTC+00:00 |
| Etc/Universal | UTC+00:00 |
| Etc/Zulu | UTC+00:00 |
| Europe/Amsterdam | UTC+02:00 |
| Europe/Andorra | UTC+02:00 |
| Europe/Astrakhan | UTC+04:00 |
| Europe/Athens | UTC+03:00 |
| Europe/Belfast | UTC+01:00 |
| Europe/Belgrade | UTC+02:00 |
| Europe/Berlin | UTC+02:00 |
| Europe/Bratislava | UTC+02:00 |
| Europe/Brussels | UTC+02:00 |
| Europe/Bucharest | UTC+03:00 |
| Europe/Budapest | UTC+02:00 |
| Europe/Busingen | UTC+02:00 |
| Europe/Chisinau | UTC+03:00 |
| Europe/Copenhagen | UTC+02:00 |
| Europe/Dublin | UTC+01:00 |
| Europe/Gibraltar | UTC+02:00 |
| Europe/Guernsey | UTC+01:00 |
| Europe/Helsinki | UTC+03:00 |
| Europe/Isle_of_Man | UTC+01:00 |
| Europe/Istanbul | UTC+03:00 |
| Europe/Jersey | UTC+01:00 |
| Europe/Kaliningrad | UTC+02:00 |
| Europe/Kiev | UTC+03:00 |
| Europe/Kirov | UTC+03:00 |
| Europe/Kyiv | UTC+03:00 |
| Europe/Lisbon | UTC+01:00 |
| Europe/Ljubljana | UTC+02:00 |
| Europe/London | UTC+01:00 |
| Europe/Luxembourg | UTC+02:00 |
| Europe/Madrid | UTC+02:00 |
| Europe/Malta | UTC+02:00 |
| Europe/Mariehamn | UTC+03:00 |
| Europe/Minsk | UTC+03:00 |
| Europe/Monaco | UTC+02:00 |
| Europe/Moscow | UTC+03:00 |
| Europe/Nicosia | UTC+03:00 |
| Europe/Oslo | UTC+02:00 |
| Europe/Paris | UTC+02:00 |
| Europe/Podgorica | UTC+02:00 |
| Europe/Prague | UTC+02:00 |
| Europe/Riga | UTC+03:00 |
| Europe/Rome | UTC+02:00 |
| Europe/Samara | UTC+04:00 |
| Europe/San_Marino | UTC+02:00 |
| Europe/Sarajevo | UTC+02:00 |
| Europe/Saratov | UTC+04:00 |
| Europe/Simferopol | UTC+03:00 |
| Europe/Skopje | UTC+02:00 |
| Europe/Sofia | UTC+03:00 |
| Europe/Stockholm | UTC+02:00 |
| Europe/Tallinn | UTC+03:00 |
| Europe/Tirane | UTC+02:00 |
| Europe/Tiraspol | UTC+03:00 |
| Europe/Ulyanovsk | UTC+04:00 |
| Europe/Uzhgorod | UTC+03:00 |
| Europe/Vaduz | UTC+02:00 |
| Europe/Vatican | UTC+02:00 |
| Europe/Vienna | UTC+02:00 |
| Europe/Vilnius | UTC+03:00 |
| Europe/Volgograd | UTC+03:00 |
| Europe/Warsaw | UTC+02:00 |
| Europe/Zagreb | UTC+02:00 |
| Europe/Zaporozhye | UTC+03:00 |
| Europe/Zurich | UTC+02:00 |
| Factory | UTC+00:00 |
| GB | UTC+01:00 |
| GB-Eire | UTC+01:00 |
| GMT | UTC+00:00 |
| GMT+0 | UTC+00:00 |
| GMT-0 | UTC+00:00 |
| GMT0 | UTC+00:00 |
| Greenwich | UTC+00:00 |
| HST | UTC-10:00 |
| Hongkong | UTC+08:00 |
| Iceland | UTC+00:00 |
| Indian/Antananarivo | UTC+03:00 |
| Indian/Chagos | UTC+06:00 |
| Indian/Christmas | UTC+07:00 |
| Indian/Cocos | UTC+06:30 |
| Indian/Comoro | UTC+03:00 |
| Indian/Kerguelen | UTC+05:00 |
| Indian/Mahe | UTC+04:00 |
| Indian/Maldives | UTC+05:00 |
| Indian/Mauritius | UTC+04:00 |
| Indian/Mayotte | UTC+03:00 |
| Indian/Reunion | UTC+04:00 |
| Iran | UTC+03:30 |
| Israel | UTC+03:00 |
| Jamaica | UTC-05:00 |
| Japan | UTC+09:00 |
| Kwajalein | UTC+12:00 |
| Libya | UTC+02:00 |
| MET | UTC+02:00 |
| MST | UTC-07:00 |
| MST7MDT | UTC-06:00 |
| Mexico/BajaNorte | UTC-07:00 |
| Mexico/BajaSur | UTC-07:00 |
| Mexico/General | UTC-06:00 |
| NZ | UTC+12:00 |
| NZ-CHAT | UTC+12:45 |
| Navajo | UTC-06:00 |
| PRC | UTC+08:00 |
| PST8PDT | UTC-07:00 |
| Pacific/Apia | UTC+13:00 |
| Pacific/Auckland | UTC+12:00 |
| Pacific/Bougainville | UTC+11:00 |
| Pacific/Chatham | UTC+12:45 |
| Pacific/Chuuk | UTC+10:00 |
| Pacific/Easter | UTC-06:00 |
| Pacific/Efate | UTC+11:00 |
| Pacific/Enderbury | UTC+13:00 |
| Pacific/Fakaofo | UTC+13:00 |
| Pacific/Fiji | UTC+12:00 |
| Pacific/Funafuti | UTC+12:00 |
| Pacific/Galapagos | UTC-06:00 |
| Pacific/Gambier | UTC-09:00 |
| Pacific/Guadalcanal | UTC+11:00 |
| Pacific/Guam | UTC+10:00 |
| Pacific/Honolulu | UTC-10:00 |
| Pacific/Johnston | UTC-10:00 |
| Pacific/Kanton | UTC+13:00 |
| Pacific/Kiritimati | UTC+14:00 |
| Pacific/Kosrae | UTC+11:00 |
| Pacific/Kwajalein | UTC+12:00 |
| Pacific/Majuro | UTC+12:00 |
| Pacific/Marquesas | UTC-09:30 |
| Pacific/Midway | UTC-11:00 |
| Pacific/Nauru | UTC+12:00 |
| Pacific/Niue | UTC-11:00 |
| Pacific/Norfolk | UTC+11:00 |
| Pacific/Noumea | UTC+11:00 |
| Pacific/Pago_Pago | UTC-11:00 |
| Pacific/Palau | UTC+09:00 |
| Pacific/Pitcairn | UTC-08:00 |
| Pacific/Pohnpei | UTC+11:00 |
| Pacific/Ponape | UTC+11:00 |
| Pacific/Port_Moresby | UTC+10:00 |
| Pacific/Rarotonga | UTC-10:00 |
| Pacific/Saipan | UTC+10:00 |
| Pacific/Samoa | UTC-11:00 |
| Pacific/Tahiti | UTC-10:00 |
| Pacific/Tarawa | UTC+12:00 |
| Pacific/Tongatapu | UTC+13:00 |
| Pacific/Truk | UTC+10:00 |
| Pacific/Wake | UTC+12:00 |
| Pacific/Wallis | UTC+12:00 |
| Pacific/Yap | UTC+10:00 |
| Poland | UTC+02:00 |
| Portugal | UTC+01:00 |
| ROC | UTC+08:00 |
| ROK | UTC+09:00 |
| Singapore | UTC+08:00 |
| Turkey | UTC+03:00 |
| UCT | UTC+00:00 |
| US/Alaska | UTC-08:00 |
| US/Aleutian | UTC-09:00 |
| US/Arizona | UTC-07:00 |
| US/Central | UTC-05:00 |
| US/East-Indiana | UTC-04:00 |
| US/Eastern | UTC-04:00 |
| US/Hawaii | UTC-10:00 |
| US/Indiana-Starke | UTC-05:00 |
| US/Michigan | UTC-04:00 |
| US/Mountain | UTC-06:00 |
| US/Pacific | UTC-07:00 |
| US/Samoa | UTC-11:00 |
| UTC | UTC+00:00 |
| Universal | UTC+00:00 |
| W-SU | UTC+03:00 |
| WET | UTC+01:00 |
| Zulu | UTC+00:00 |
| localtime | UTC+00:00 |
API Reference
API Reference¶
This page is generated directly from the library's docstrings via mkdocstrings, so it always reflects the installed version's actual signatures and behavior rather than a hand-maintained copy that can drift out of sync with the code.
For the command-line options, see CLI Reference instead —
that page is generated from the CLI's live --help output.
CLI Entry Point¶
bumpcalver.cli.main(beta, rc, build, release, custom, timezone, git_tag, auto_commit, undo, undo_id, list_history, bump, dry_run, config_file, json_output)
¶
Bump this project's version and write it to every configured file.
Reads [tool.bumpcalver] from pyproject.toml (or bumpcalver.toml) for
the file list and defaults; CLI flags override config values where both
exist. At most one of --beta/--rc/--release/--custom may be set.
Optionally creates a git tag and/or commit — or preview with --dry-run
instead of writing anything. Undo a previous run with --undo,
--undo-id, or --list-history (mutually exclusive with every
version-bump option, including --dry-run). Pass --json for a single
machine-readable JSON result on stdout instead of the log lines below.
Versioning Utilities¶
bumpcalver.utils.get_current_date(timezone=default_timezone, date_format='%Y.%m.%d')
¶
Returns the current date in the specified timezone.
Falls back to default_timezone (printing a warning) if timezone isn't
a recognized IANA name, rather than raising.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timezone
|
str
|
The IANA timezone name to use (e.g. "Europe/London"). |
default_timezone
|
date_format
|
str
|
The strftime format string for the returned date. |
'%Y.%m.%d'
|
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
The current date formatted according to date_format. |
Example
current_date = get_current_date(timezone="UTC")
bumpcalver.utils.get_current_datetime_version(timezone=default_timezone, date_format='%Y.%m.%d')
¶
Returns the current date/time formatted as a version string.
Falls back to default_timezone (printing a warning) if timezone isn't
a recognized IANA name, rather than raising. Supports the %q quarter
placeholder (1-4) in date_format in addition to standard strftime codes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timezone
|
str
|
The IANA timezone name to use (e.g. "Europe/London"). |
default_timezone
|
date_format
|
str
|
The strftime format string; may include |
'%Y.%m.%d'
|
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
The current date/time formatted according to date_format. |
Example
version = get_current_datetime_version(timezone="UTC", date_format="%y.Q%q")
bumpcalver.utils.get_build_version(file_config, version_format, timezone, date_format, major=0, minor=0, patch=0)
¶
Returns the build version string based on the provided file configuration.
This function reads the current version from the specified file, increments the build count if the date matches the current date, and returns the formatted build version string.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file_config
|
Dict[str, Any]
|
A dictionary containing file configuration details. - "path" (str): The path to the file. - "file_type" (str): The type of the file (e.g., "python", "toml", "yaml", "json", "xml", "dockerfile", "makefile"). - "variable" (str, optional): The variable name that holds the version string. - "directive" (str, optional): The directive for Dockerfile (e.g., "ARG" or "ENV"). |
required |
version_format
|
str
|
The format string for the version. |
required |
timezone
|
str
|
The timezone to use for date calculations. |
required |
date_format
|
str
|
The format string for the date. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
The formatted build version string. |
Example
file_config = { "path": "version.py", "file_type": "python", "variable": "version" } build_version = get_build_version(file_config, "{current_date}-{build_count:03}", "America/New_York", "%Y.%m.%d")
bumpcalver.utils.parse_version(version, version_format=None, date_format=None)
¶
Parses a version string and returns a tuple of date and count.
This function can parse version strings in various formats. If version_format and date_format are provided, it will use them to dynamically parse the version. Otherwise, it falls back to the legacy 'YYYY-MM-DD-XXX' format for backwards compatibility.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
version
|
str
|
The version string to parse. |
required |
version_format
|
str
|
The format string used to create the version (e.g., "{current_date}.{build_count:03}") |
None
|
date_format
|
str
|
The date format string (e.g., "%y.Q%q") |
None
|
Returns:
| Type | Description |
|---|---|
Optional[tuple]
|
Optional[tuple]: A tuple containing the date string and count, or None if the version string is invalid. |
Examples:
version_info = parse_version("2023-10-05-001") # Legacy format version_info = parse_version("25.Q4.001", "{current_date}.{build_count:03}", "%y.Q%q") # Custom format
bumpcalver.utils.apply_prerelease_suffix(base_version, suffix_format, current_raw_version='')
¶
Apply a pre-release suffix to base_version, honouring {xxx_count} placeholders.
If suffix_format contains no placeholder the literal string is appended. When a placeholder is present the count is derived from current_raw_version: if it starts with base_version + the suffix prefix the existing count is incremented; otherwise the count starts at 1.
bumpcalver.utils.update_semantic_in_config(key, value)
¶
Update major/minor/patch integer in pyproject.toml or bumpcalver.toml.
bumpcalver.utils.parse_dot_path(dot_path, file_type)
¶
Parses a dot-separated path and converts it to a file path.
This function converts a dot-separated path to a file path. If the input path is already a valid file path (contains '/' or '\' or is an absolute path), it returns the input path as is. For Python files, it ensures the path ends with '.py'.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dot_path
|
str
|
The dot-separated path to parse. |
required |
file_type
|
str
|
The type of the file (e.g., "python"). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
The converted file path. |
Example
file_path = parse_dot_path("src.module", "python")
Configuration¶
bumpcalver.config.load_config(config_path=None)
¶
Load BumpCalver's configuration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config_path
|
Optional[str]
|
Explicit path to a config file (from |
None
|
Git Integration¶
bumpcalver.git_utils.create_git_tag(version, files_to_commit, auto_commit)
¶
Creates a Git tag and optionally commits changes.
This function checks if the specified Git tag already exists. If it does not, it creates the tag. If auto-commit is enabled, it stages the specified files and commits them before creating the tag.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
version
|
str
|
The version string to use as the Git tag. |
required |
files_to_commit
|
List[str]
|
A list of file paths to commit if auto-commit is enabled. |
required |
auto_commit
|
bool
|
Whether to automatically commit changes before creating the tag. |
required |
Raises:
| Type | Description |
|---|---|
CalledProcessError
|
If there is an error during Git operations. |
Example
To create a Git tag and commit changes: create_git_tag("v1.0.0", ["file1.py", "file2.py"], auto_commit=True)
File Handlers¶
Every supported file_type (see Configuration)
is backed by a VersionHandler subclass. All of them share the same
read_version/update_version contract defined on the abstract base class —
see the handler extension guide
if you're adding support for a new file format, or
distributing your handler as a plugin
if you'd rather ship it as a separate installable package via the
bumpcalver.handlers entry-point group.
bumpcalver.handlers.VersionHandler
¶
Bases: ABC
Abstract base class for version handlers.
Subclasses implement read_version/update_version for one file format;
see the handler extension guide
for the shared helpers (_read_key_value_file, _update_key_value_file,
_handle_regex_update, etc.) available for reuse.
Source code in src/bumpcalver/handlers.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | |
format_pep440_version(version)
¶
Formats the version string according to PEP 440.
This method replaces hyphens and underscores with dots and ensures no leading zeros in numeric segments.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
version
|
str
|
The version string to format. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
The formatted version string. |
Source code in src/bumpcalver/handlers.py
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | |
format_version(version, standard)
¶
Formats the version string according to the specified standard.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
version
|
str
|
The version string to format. |
required |
standard
|
str
|
The versioning standard to use (e.g., "python" for PEP 440). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
The formatted version string. |
Source code in src/bumpcalver/handlers.py
71 72 73 74 75 76 77 78 79 80 81 82 83 | |
read_version(file_path, variable, **kwargs)
abstractmethod
¶
Reads the version string from the specified file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file_path
|
str
|
The path to the file. |
required |
variable
|
str
|
The variable name that holds the version string. |
required |
**kwargs
|
Any
|
Additional keyword arguments. |
{}
|
Returns:
| Type | Description |
|---|---|
Optional[str]
|
Optional[str]: The version string if found, otherwise None. |
Source code in src/bumpcalver/handlers.py
40 41 42 43 44 45 46 47 48 49 50 51 52 53 | |
update_version(file_path, variable, new_version, **kwargs)
abstractmethod
¶
Updates the version string in the specified file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file_path
|
str
|
The path to the file. |
required |
variable
|
str
|
The variable name that holds the version string. |
required |
new_version
|
str
|
The new version string. |
required |
**kwargs
|
Any
|
Additional keyword arguments. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if the version was successfully updated, otherwise False. |
Source code in src/bumpcalver/handlers.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
bumpcalver.handlers.get_version_handler(file_type)
¶
Return a handler instance for the given file type.
Checks built-in handlers first, then third-party plugins registered via
the bumpcalver.handlers entry-point group (see
docs/development-guide.md) — a plugin can never override a built-in
file_type.
Raises ValueError for unsupported types.
bumpcalver.handlers.available_file_types()
¶
Return every file_type usable with get_version_handler().
Includes both built-in handlers and any discovered via the
bumpcalver.handlers plugin entry-point group.
bumpcalver.handlers.update_version_in_files(new_version, file_configs)
¶
Updates the version string in multiple files based on the provided configurations.
This function iterates over the provided file configurations, updates the version string in each file using the appropriate version handler, and returns a list of files that were successfully updated.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
new_version
|
str
|
The new version string to set in the files. |
required |
file_configs
|
List[Dict[str, Any]]
|
A list of dictionaries containing file configuration details. Each dictionary should have the following keys: - "path" (str): The path to the file. - "file_type" (str): The type of the file (e.g., "python", "toml", "yaml", "json", "xml", "dockerfile", "makefile", "properties", "env", "setup.cfg", "text", "regex"). - "variable" (str, optional): The variable name that holds the version string. - "directive" (str, optional): The directive for Dockerfile (e.g., "ARG" or "ENV"). - "pattern" (str, optional): Regex with one capture group, required for file_type="regex". - "version_standard" (str, optional): The versioning standard to follow (default is "default"). |
required |
Returns:
| Type | Description |
|---|---|
List[str]
|
List[str]: A list of file paths that were successfully updated. |
Example
file_configs = [ {"path": "version.py", "file_type": "python", "variable": "version"}, {"path": "pyproject.toml", "file_type": "toml", "variable": "tool.bumpcalver.version"}, ] updated_files = update_version_in_files("2023.10.05", file_configs)
Format-specific handlers¶
bumpcalver.handlers.PythonVersionHandler
¶
Bases: VersionHandler
Handler for variable = "..."-style assignments in Python files, e.g. __version__.
bumpcalver.handlers.TomlVersionHandler
¶
Bases: VersionHandler
Handler for TOML files (e.g. pyproject.toml), using tomlkit.
Uses tomlkit rather than the plain toml package so comments and
formatting elsewhere in the file survive an update — toml.load/toml.dump
round-trip through a plain dict and silently drop every comment, which
matters since this handler's primary target commonly carries them.
bumpcalver.handlers.YamlVersionHandler
¶
Bases: VersionHandler
Handler for YAML files, using ruamel.yaml's round-trip mode.
Uses ruamel.yaml rather than the plain PyYAML package so comments,
key order, and quote style elsewhere in the file survive an update —
yaml.safe_load/yaml.safe_dump round-trip through plain dicts and
silently drop every comment (and, unless sort_keys=False is passed,
alphabetize every key too). Mirrors why TomlVersionHandler uses
tomlkit instead of the plain toml package.
bumpcalver.handlers.JsonVersionHandler
¶
Bases: VersionHandler
Handler for JSON files (e.g. package.json); variable is a top-level key only.
bumpcalver.handlers.XmlVersionHandler
¶
Bases: VersionHandler
Handler for XML files, using xml.etree.ElementTree.
update_version preserves the <?xml ?> declaration and any comments nested
inside the root element. Comments in the prolog (before the root element's
opening tag) are not preserved — an ElementTree limitation (Element/
TreeBuilder model the tree from the root element down, so anything outside
it is dropped on write regardless of parser options); lxml would be needed
for full prolog fidelity.
read_version(file_path, variable, **kwargs)
¶
Reads the text of the element at variable, an ElementTree find() path (e.g. "version" or "metadata/version").
update_version(file_path, variable, new_version, **kwargs)
¶
Updates the text of the element at variable in place (see class docstring for formatting fidelity).
bumpcalver.handlers.DockerfileVersionHandler
¶
Bases: VersionHandler
Handler for ARG/ENV directives in Dockerfiles; requires a directive kwarg.
bumpcalver.handlers.MakefileVersionHandler
¶
Bases: VersionHandler
Handler for VAR = value / VAR := value lines in Makefiles.
bumpcalver.handlers.PropertiesVersionHandler
¶
Bases: VersionHandler
Handler for key=value properties files (e.g. sonar-project.properties).
read_version(file_path, variable, **kwargs)
¶
Reads the value of the variable key from a key=value line.
bumpcalver.handlers.EnvVersionHandler
¶
Bases: VersionHandler
Handler for KEY=VALUE .env files; strips surrounding quotes on read.
read_version(file_path, variable, **kwargs)
¶
Reads the value of the variable key from a KEY=value line, stripping surrounding quotes if present.
bumpcalver.handlers.SetupCfgVersionHandler
¶
Bases: VersionHandler
Handler for setup.cfg's INI-style sections and key=value pairs.
read_version(file_path, variable, **kwargs)
¶
Reads variable's value: "section.key" reads that section directly, a bare key searches all sections.
update_version(file_path, variable, new_version, **kwargs)
¶
Updates variable's value in place; a bare key not found in any section is created under [metadata].
Generic handlers¶
For formats with no dedicated handler above.
bumpcalver.handlers.TextVersionHandler
¶
Bases: VersionHandler
Handler for bare version files whose entire content is the version
(e.g. a VERSION file containing just 1.2.3, as used by many
shell-based release pipelines). variable is ignored — there is no key,
the whole file is the value.
bumpcalver.handlers.RegexVersionHandler
¶
Bases: VersionHandler
Generic handler for formats with no dedicated handler (Ruby VERSION = "...",
Rust const VERSION: &str = "...";, Go var Version = "...", etc.).
Driven entirely by a pattern kwarg: a regex string with exactly one capture
group around the version. Set file_type = "regex" and pass pattern in the
file's config, e.g. pattern = 'VERSION = "(.+?)"' for a Ruby file. variable
is not used for matching — it only appears in log messages — since the pattern
itself locates the version.
AI Assistant Instructions¶
See AI Assistant Instructions for the full narrative guide (what's covered, what isn't, the security contract). API reference:
bumpcalver.ai_instructions.get_app_instructions(profile='generic')
¶
Return packaged app-side integration instructions for an AI assistant profile.
Aliases are accepted (for example: github-copilot, anthropic-claude).
bumpcalver.ai_instructions.available_instruction_profiles()
¶
Return canonical app-integration instruction profiles bundled with the package.
bumpcalver.ai_instructions.suggested_instruction_filename(profile='generic')
¶
Return a suggested filename for app repositories.
This is only a recommendation and is not written automatically unless the caller opts into --write / --output via the CLI.
Undo / Backup¶
bumpcalver.backup_utils.BackupManager
¶
Manages file backups and operation history for undo functionality.
__init__(backup_dir=None, history_file=None)
¶
cleanup_old_backups(days_to_keep=30)
¶
Remove backup files older than specified days.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
days_to_keep
|
int
|
Number of days of backups to retain |
30
|
create_backup(file_path)
¶
get_latest_operation()
¶
get_operation_history(limit=None)
¶
store_operation_history(operation_id, version, files_updated, backups, git_tag=False, git_commit=False, git_commit_hash=None, git_tag_name=None)
¶
Store metadata about a version bump operation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
operation_id
|
str
|
Unique identifier for this operation |
required |
version
|
str
|
The version that was set |
required |
files_updated
|
List[str]
|
List of files that were updated |
required |
backups
|
Dict[str, str]
|
Mapping of original file paths to backup file paths |
required |
git_tag
|
bool
|
Whether a git tag was created |
False
|
git_commit
|
bool
|
Whether files were committed to git |
False
|
git_commit_hash
|
Optional[str]
|
Hash of the git commit (if created) |
None
|
git_tag_name
|
Optional[str]
|
Name of the git tag (if created) |
None
|
bumpcalver.undo_utils.undo_last_operation(backup_manager=None)
¶
Undo the most recent version bump operation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backup_manager
|
Optional[BackupManager]
|
Optional backup manager instance |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
True if undo was successful, False otherwise |
bumpcalver.undo_utils.undo_operation_by_id(operation_id, backup_manager=None)
¶
Undo a specific operation by its ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
operation_id
|
str
|
The ID of the operation to undo |
required |
backup_manager
|
Optional[BackupManager]
|
Optional backup manager instance |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
True if undo was successful, False otherwise |
bumpcalver.undo_utils.list_undo_history(backup_manager=None, limit=10)
¶
List recent operations that can be undone.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backup_manager
|
Optional[BackupManager]
|
Optional backup manager instance |
None
|
limit
|
int
|
Maximum number of operations to display |
10
|
CLI Reference¶
This is the literal output of bumpcalver --help. A test
(tests/test_docs.py::test_cli_reference_matches_help_output) asserts this
block stays byte-for-byte in sync with the live click.Command — if you add,
remove, or reword a CLI option, that test will fail until this page is
regenerated to match.
Usage: bumpcalver [OPTIONS]
Bump this project's version and write it to every configured file.
Reads `[tool.bumpcalver]` from `pyproject.toml` (or `bumpcalver.toml`) for the
file list and defaults; CLI flags override config values where both exist. At
most one of `--beta`/`--rc`/`--release`/`--custom` may be set. Optionally
creates a git tag and/or commit — or preview with `--dry-run` instead of
writing anything. Undo a previous run with `--undo`, `--undo-id`, or `--list-
history` (mutually exclusive with every version-bump option, including `--dry-
run`). Pass `--json` for a single machine-readable JSON result on stdout
instead of the log lines below.
Options:
-V, --version Show the version and exit.
--beta Add -beta to version
--rc Add -rc to version
--release Add -release to version
--custom TEXT Add -<WhatEverYouWant> to version
--build Use build count versioning
--timezone TEXT Timezone for date calculations (default: value
from config or America/New_York)
--git-tag / --no-git-tag Create a Git tag with the new version
--auto-commit / --no-auto-commit
Automatically commit changes when creating a
Git tag
--undo Undo the last version bump operation
--undo-id TEXT Undo a specific operation by ID
--list-history List recent operations that can be undone
--bump [major|minor|patch] Increment the specified semantic version
component in config
--dry-run Show what would change without writing any
files or creating a git tag/commit
--config-file FILE Path to a pyproject.toml/bumpcalver.toml to
use instead of auto-discovery in the current
directory (env var: BUMPCALVER_CONFIG). File
paths inside it are resolved relative to the
config file's own directory, not the current
directory.
--json Emit a single JSON object with the result to
stdout instead of human-readable log lines
(those move to stderr). Not compatible with
--undo/--undo-id/--list-history.
--help Show this message and exit.
Notes¶
--beta,--rc,--release, and--customare mutually exclusive — only one pre-release suffix option may be set per invocation.--undo,--undo-id, and--list-historyare mutually exclusive with every version-bump option (--beta/--rc/--release/--custom/--build/--bump/--dry-run/--config-file); combining them raises a usage error before any version logic runs.--git-tag/--auto-commitand their--no-counterparts override thegit_tag/auto_commitconfig values for a single invocation.--dry-runcomputes and prints the version/files that would change without writing anything or touching git.--config-file(orBUMPCALVER_CONFIG) points at a config outside the current directory. File paths inside that config — and the undo backups/history for the resulting operation — resolve relative to the config file's own directory, not whereverbumpcalverwas invoked from.--jsonemits exactly one JSON object on stdout and moves every other log line to stderr — see Machine-Readable Output below for the payload shape and examples. Not compatible with--undo/--undo-id/--list-history(those commands don't return structured data yet).- See the Configuration section for the
corresponding
pyproject.toml/bumpcalver.tomlsettings (version_format,beta_format,rc_format,release_format,major/minor/patch, etc.).
Machine-Readable Output (--json)¶
Pass --json to get a single JSON object on stdout instead of the
human-readable log lines above (those move to stderr — pipe them away with
2>/dev/null for fully quiet output, or keep them for debugging). Useful for
CI steps that need the computed version, or scripts that want to react to
which files actually changed.
A normal bump:
$ bumpcalver --build --json 2>/dev/null
{"version": "2026.07.25.001", "files_updated": ["src/myapp/__init__.py"], "operation_id": "20260725_120000_000", "git_tag": null, "git_commit_hash": null}
--dry-run --json (no files are written):
$ bumpcalver --build --dry-run --json 2>/dev/null
{"dry_run": true, "version": "2026.07.25.001", "files_that_would_change": ["src/myapp/__init__.py"], "git_tag_would_create": null, "auto_commit": false}
If every configured file already contains the computed version, or an error
occurs, --json still emits exactly one object ({"no_op": true, ...} or
{"error": "..."} respectively, the latter with a non-zero exit code) — a
caller never has to guess whether stdout is JSON or not.
Examples
Configuration Recipes¶
Each recipe below is a ready-to-copy starter for a specific language or workflow. Every recipe shows:
- The
[tool.bumpcalver]block to add topyproject.toml(orbumpcalver.toml) - The
[[tool.bumpcalver.file]]entries for the files to update - An example version string the recipe produces
Working copies of the version-bearing files referenced below live in the examples/ directory of the repository. See File Layout Examples for the full catalog.
Using
bumpcalver.tomlinstead ofpyproject.toml? Drop the[tool.bumpcalver]wrapper and[[tool.bumpcalver.file]]prefix — use bare key/value sections with[[file]]instead. See Standalone bumpcalver.toml at the bottom.
Pure CalVer Recipes¶
Python Package¶
Produces: 26.05.24.001
Updates: pyproject.toml project version + package __init__.py
[tool.bumpcalver]
version_format = "{current_date}.{build_count:03}"
date_format = "%y.%m.%d"
timezone = "UTC"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "pyproject.toml"
file_type = "toml"
variable = "project.version"
version_standard = "python"
[[tool.bumpcalver.file]]
path = "src/mypackage/__init__.py"
file_type = "python"
variable = "__version__"
version_standard = "python"
__init__.py before → after:
__version__ = "0.1.0"
__version__ = "26.05.24.001"
Node.js / JavaScript¶
Produces: 2026.05.24.1
Updates: package.json
[tool.bumpcalver]
version_format = "{current_date}.{build_count}"
date_format = "%Y.%m.%d"
timezone = "UTC"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "package.json"
file_type = "json"
variable = "version"
version_standard = "default"
package.json before → after:
{ "version": "1.0.0" }
{ "version": "2026.05.24.1" }
The
jsonhandler updates the top-level key named byvariable. Nested keys are not supported.
Rust¶
Produces: 2026.05.24.1
Updates: Cargo.toml
[tool.bumpcalver]
version_format = "{current_date}.{build_count}"
date_format = "%Y.%m.%d"
timezone = "UTC"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "Cargo.toml"
file_type = "toml"
variable = "package.version"
version_standard = "default"
Cargo.toml before → after:
[package]
version = "0.1.0"
[package]
version = "2026.05.24.1"
Java — Gradle¶
Produces: 2026.05.24.1
Updates: gradle.properties
[tool.bumpcalver]
version_format = "{current_date}.{build_count}"
date_format = "%Y.%m.%d"
timezone = "UTC"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "gradle.properties"
file_type = "properties"
variable = "version"
version_standard = "default"
gradle.properties before → after:
version=1.0.0
version=2026.05.24.1
Reference it in build.gradle:
version = project.findProperty('version')
Java — Maven¶
Produces: 2026.05.24.1
Updates: version.properties (imported by Maven)
Maven's pom.xml uses XML namespaces that complicate direct editing. The recommended pattern is a dedicated properties file that the Properties Maven Plugin imports at build time:
[tool.bumpcalver]
version_format = "{current_date}.{build_count}"
date_format = "%Y.%m.%d"
timezone = "UTC"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "version.properties"
file_type = "properties"
variable = "project.version"
version_standard = "default"
version.properties:
project.version=2026.05.24.1
Load it in pom.xml with the Properties Maven Plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>initialize</phase>
<goals><goal>read-project-properties</goal></goals>
<configuration>
<files><file>version.properties</file></files>
</configuration>
</execution>
</executions>
</plugin>
Then reference ${project.version} in your POM as normal.
Go¶
Produces: 2026.05.24.001
Updates: Makefile + version.txt
Go's const/var keyword before the identifier prevents direct matching, so the idiomatic pattern is a Makefile variable (passed via -ldflags) combined with an embedded version.txt file.
[tool.bumpcalver]
version_format = "{current_date}.{build_count:03}"
date_format = "%Y.%m.%d"
timezone = "UTC"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "Makefile"
file_type = "makefile"
variable = "APP_VERSION"
version_standard = "default"
[[tool.bumpcalver.file]]
path = "version.txt"
file_type = "env"
variable = "VERSION"
version_standard = "default"
Makefile:
APP_VERSION = 2026.05.24.001
build:
go build -ldflags="-X main.Version=$(APP_VERSION)" ./...
version.txt:
VERSION=2026.05.24.001
Embed version.txt in Go code:
import (
_ "embed"
"strings"
)
//go:embed version.txt
var versionFile string
var Version = strings.TrimPrefix(strings.TrimSpace(versionFile), "VERSION=")
Ruby Gem¶
Produces: 2026.05.24.1
Updates: lib/mygem/version.rb
There's no dedicated Ruby handler, so use the generic regex file type with a
pattern — a regex with exactly one capture group around the version.
Everything else on the matched line (the VERSION = "..." assignment, in
this case) is left untouched.
[tool.bumpcalver]
version_format = "{current_date}.{build_count}"
date_format = "%Y.%m.%d"
timezone = "UTC"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "lib/mygem/version.rb"
file_type = "regex"
variable = "VERSION"
pattern = 'VERSION = "(.+?)"'
version_standard = "default"
version.rb before → after:
module MyGem
VERSION = "1.0.0"
end
module MyGem
VERSION = "2026.05.24.1"
end
Earlier versions of this recipe pointed the
pythonhandler at Ruby files, since itsVARIABLE = "value"regex happens to also match Ruby constants. That's a coincidence of the two languages' assignment syntax looking similar, not real Ruby support — useregexinstead, which is explicit about matching an arbitrary pattern rather than implying Python-specific handling.
Bare VERSION File (Shell Scripts / Generic Pipelines)¶
Produces: 2026.05.24.1
Updates: VERSION
Some release pipelines use a VERSION file whose entire content is the
version string, with no key at all (e.g. cat VERSION in a shell script).
Use file_type = "text" — variable isn't needed since there's no key to
look up.
[tool.bumpcalver]
version_format = "{current_date}.{build_count}"
date_format = "%Y.%m.%d"
timezone = "UTC"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "VERSION"
file_type = "text"
version_standard = "default"
VERSION before → after:
1.0.0
2026.05.24.1
.NET / C¶
Produces: 2026.05.24.1
Updates: MyApp.csproj
[tool.bumpcalver]
version_format = "{current_date}.{build_count}"
date_format = "%Y.%m.%d"
timezone = "UTC"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "MyApp.csproj"
file_type = "xml"
variable = "PropertyGroup/Version"
version_standard = "default"
MyApp.csproj before → after:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version>1.0.0</Version>
</PropertyGroup>
</Project>
The
xmlhandler accepts simple XPath paths.PropertyGroup/Versionfinds<Version>nested directly under<PropertyGroup>at the document root.
Docker / Container Image¶
Produces: 2026.05.24.1
Updates: Dockerfile ARG and ENV in a single pass
[tool.bumpcalver]
version_format = "{current_date}.{build_count}"
date_format = "%Y.%m.%d"
timezone = "UTC"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "Dockerfile"
file_type = "dockerfile"
variable = "arg.VERSION"
version_standard = "default"
[[tool.bumpcalver.file]]
path = "Dockerfile"
file_type = "dockerfile"
variable = "env.APP_VERSION"
version_standard = "default"
Dockerfile before → after:
ARG VERSION=1.0.0
ENV APP_VERSION=1.0.0
ARG VERSION=2026.05.24.1
ENV APP_VERSION=2026.05.24.1
Prefix with
arg.forARGinstructions andenv.forENVinstructions. The same file can appear twice in the config to update both.
Hybrid Recipes (Semantic Prefix + Calendar Date)¶
These recipes combine a SemVer prefix (1.0, 2.3.1) with a CalVer date to signal both project maturity and release timing in one string. See the Hybrid Versioning Guide for the full reference.
Python Library — Stable API¶
Produces: 1.0-20260524.1
Use case: A library with a stable public API that releases frequently. The 1.0 prefix signals compatibility; the date shows recency.
[tool.bumpcalver]
major = 1
minor = 0
patch = 0
version_format = "{major}.{minor}-{current_date}.{build_count}"
date_format = "%Y%m%d"
timezone = "UTC"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "pyproject.toml"
file_type = "toml"
variable = "project.version"
[[tool.bumpcalver.file]]
path = "src/mypackage/__init__.py"
file_type = "python"
variable = "__version__"
CLI workflow:
bumpcalver --build # → 1.0-20260524.1
bumpcalver --build # → 1.0-20260524.2 (same day, count increments)
bumpcalver --build --bump minor # → 1.1-20260524.1 (new feature, minor bumped)
bumpcalver --build --bump major # → 2.0-20260524.1 (breaking change)
PEP 440 note: Add
version_standard = "python"to convert hyphens to dots for PEP 440:1.0.20260524.1. Or use a dot separator inversion_formatfrom the start:{major}.{minor}.{current_date}.{build_count}.
Enterprise Quarterly Release¶
Produces: 26.Q2.01
Use case: A team that ships on a quarterly cadence and wants the quarter explicit in the version string.
[tool.bumpcalver]
version_format = "{current_date}.{build_count:02}"
date_format = "%y.Q%q"
timezone = "America/New_York"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "pyproject.toml"
file_type = "toml"
variable = "project.version"
version_standard = "python"
[[tool.bumpcalver.file]]
path = "RELEASE_VERSION"
file_type = "env"
variable = "VERSION"
version_standard = "default"
Hybrid with Full Patch + Padded Build Count¶
Produces: 1.0.0-20260524.001
Use case: A project that wants all three semantic components explicit and a zero-padded three-digit build count for lexicographic sort order.
[tool.bumpcalver]
major = 1
minor = 0
patch = 0
version_format = "{major}.{minor}.{patch}-{current_date}.{build_count:03}"
date_format = "%Y%m%d"
timezone = "UTC"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "pyproject.toml"
file_type = "toml"
variable = "project.version"
[[tool.bumpcalver.file]]
path = "src/mypackage/__init__.py"
file_type = "python"
variable = "__version__"
Pre-release Recipes¶
PEP 440 Beta / RC Workflow¶
Produces: 26.05.24.1b1 → 26.05.24.1rc1 → 26.05.24.1
[tool.bumpcalver]
version_format = "{current_date}.{build_count}"
date_format = "%y.%m.%d"
timezone = "UTC"
beta_format = "b{beta_count}"
rc_format = "rc{rc_count}"
release_format = ""
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "pyproject.toml"
file_type = "toml"
variable = "project.version"
version_standard = "python"
[[tool.bumpcalver.file]]
path = "src/mypackage/__init__.py"
file_type = "python"
variable = "__version__"
version_standard = "python"
Typical release cycle:
bumpcalver --build --beta # → 26.05.24.1b1 (first beta)
bumpcalver --beta # → 26.05.24.1b2 (second beta, same build)
bumpcalver --build --rc # → 26.05.24.2rc1 (promote to rc, new build)
bumpcalver --build # → 26.05.24.3 (final release, no suffix)
Suffix format reference:
| Config key | Example output | Notes |
|---|---|---|
beta_format = ".beta" |
26.05.24.1.beta |
Default — omit the key |
beta_format = "b{beta_count}" |
26.05.24.1b1 |
PEP 440 style |
rc_format = ".rc" |
26.05.24.1.rc |
Default |
rc_format = "rc{rc_count}" |
26.05.24.1rc1 |
PEP 440 style |
release_format = ".release" |
26.05.24.1.release |
Default |
release_format = "" |
26.05.24.1 |
No suffix added |
Multi-file / Polyglot Projects¶
Full-Stack Web App¶
Updates Python backend, Node.js frontend, Docker, Make, and Sonar in one command:
[tool.bumpcalver]
version_format = "{current_date}.{build_count:03}"
date_format = "%y.%m.%d"
timezone = "UTC"
git_tag = true
auto_commit = true
[[tool.bumpcalver.file]]
path = "pyproject.toml"
file_type = "toml"
variable = "project.version"
version_standard = "python"
[[tool.bumpcalver.file]]
path = "src/backend/__init__.py"
file_type = "python"
variable = "__version__"
version_standard = "python"
[[tool.bumpcalver.file]]
path = "frontend/package.json"
file_type = "json"
variable = "version"
version_standard = "default"
[[tool.bumpcalver.file]]
path = "Dockerfile"
file_type = "dockerfile"
variable = "arg.VERSION"
version_standard = "default"
[[tool.bumpcalver.file]]
path = "Makefile"
file_type = "makefile"
variable = "APP_VERSION"
version_standard = "default"
[[tool.bumpcalver.file]]
path = "sonar-project.properties"
file_type = "properties"
variable = "sonar.projectVersion"
version_standard = "default"
Standalone bumpcalver.toml¶
If you don't use pyproject.toml, create a bumpcalver.toml at the project root. Omit the [tool.bumpcalver] wrapper and use [[file]] instead of [[tool.bumpcalver.file]]:
version_format = "{current_date}.{build_count:03}"
date_format = "%y.%m.%d"
timezone = "America/New_York"
git_tag = true
auto_commit = true
# Pre-release suffix formats (defaults shown — omit keys to use defaults)
# beta_format = ".beta"
# rc_format = ".rc"
# release_format = ".release"
[[file]]
path = "Makefile"
file_type = "makefile"
variable = "APP_VERSION"
version_standard = "default"
[[file]]
path = ".env"
file_type = "env"
variable = "VERSION"
version_standard = "default"
File Layout Examples¶
Below are examples of the version-bearing files BumpCalver can update across different languages and file formats. Each section shows what the file looks like and the [[tool.bumpcalver.file]] entry that targets it.
Working copies of every file shown here live in the examples/ directory of the repository. For complete ready-to-run configurations, see the Configuration Recipes.
Python¶
pyproject.toml¶
[project]
name = "mypackage"
version = "2026.05.24.001"
# bumpcalver config entry
[[tool.bumpcalver.file]]
path = "pyproject.toml"
file_type = "toml"
variable = "project.version"
version_standard = "python"
__init__.py¶
__version__ = "2026.05.24.001"
[[tool.bumpcalver.file]]
path = "src/mypackage/__init__.py"
file_type = "python"
variable = "__version__"
version_standard = "python"
setup.cfg¶
[metadata]
name = example-package
version = 2026.05.24.001
author = Your Name
author_email = your.email@example.com
description = A short description of the package
[options]
packages = find:
python_requires = >=3.9
install_requires =
click>=8.0.0
[[tool.bumpcalver.file]]
path = "setup.cfg"
file_type = "setup.cfg"
variable = "metadata.version"
version_standard = "python"
Node.js / JavaScript¶
package.json¶
{
"name": "my-app",
"version": "2026.05.24.1",
"description": "My application",
"main": "index.js"
}
[[tool.bumpcalver.file]]
path = "package.json"
file_type = "json"
variable = "version"
version_standard = "default"
The
jsonhandler updates the top-level key. Nested keys are not supported.
Rust¶
Cargo.toml¶
[package]
name = "myapp"
version = "2026.05.24.1"
edition = "2021"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
[[tool.bumpcalver.file]]
path = "Cargo.toml"
file_type = "toml"
variable = "package.version"
version_standard = "default"
Java¶
gradle.properties (Gradle)¶
version=2026.05.24.1
group=com.example
description=My Application
[[tool.bumpcalver.file]]
path = "gradle.properties"
file_type = "properties"
variable = "version"
version_standard = "default"
Reference the version in build.gradle:
version = project.findProperty('version')
version.properties (Maven)¶
project.version=2026.05.24.1
[[tool.bumpcalver.file]]
path = "version.properties"
file_type = "properties"
variable = "project.version"
version_standard = "default"
Load it in pom.xml with the Properties Maven Plugin and reference ${project.version} as usual. See the Maven recipe for the plugin setup.
Go¶
Makefile (version passed via -ldflags)¶
APP_VERSION = 2026.05.24.001
build:
go build -ldflags="-X main.Version=$(APP_VERSION)" ./...
.PHONY: build
[[tool.bumpcalver.file]]
path = "Makefile"
file_type = "makefile"
variable = "APP_VERSION"
version_standard = "default"
version.txt (embedded via //go:embed)¶
VERSION=2026.05.24.001
[[tool.bumpcalver.file]]
path = "version.txt"
file_type = "env"
variable = "VERSION"
version_standard = "default"
Go code to read it:
import (
_ "embed"
"strings"
)
//go:embed version.txt
var versionFile string
var Version = strings.TrimPrefix(strings.TrimSpace(versionFile), "VERSION=")
Ruby¶
lib/mygem/version.rb¶
module MyGem
VERSION = "2026.05.24.1"
end
[[tool.bumpcalver.file]]
path = "lib/mygem/version.rb"
file_type = "python"
variable = "VERSION"
version_standard = "default"
Ruby constants (
CONSTANT = "value") match the same line pattern as Python variables, sofile_type = "python"works correctly here.
.NET / C¶
MyApp.csproj¶
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version>2026.05.24.1</Version>
<AssemblyVersion>2026.05.24.1</AssemblyVersion>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>
[[tool.bumpcalver.file]]
path = "MyApp.csproj"
file_type = "xml"
variable = "PropertyGroup/Version"
version_standard = "default"
The
xmlhandler accepts simple XPath paths.PropertyGroup/Versionfinds<Version>nested directly inside<PropertyGroup>at the document root.
Docker / Containers¶
Dockerfile¶
FROM python:3.14-slim
WORKDIR /app
COPY . /app
ARG VERSION=2026.05.24.1
ENV APP_VERSION=2026.05.24.1
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 80
CMD ["python", "app.py"]
# Update ARG
[[tool.bumpcalver.file]]
path = "Dockerfile"
file_type = "dockerfile"
variable = "arg.VERSION"
version_standard = "default"
# Update ENV
[[tool.bumpcalver.file]]
path = "Dockerfile"
file_type = "dockerfile"
variable = "env.APP_VERSION"
version_standard = "default"
Prefix
arg.forARGinstructions andenv.forENVinstructions. The same file can appear in multiple entries.
General / Infrastructure¶
Makefile¶
APP_VERSION = 2026.05.24.001
PYTHON = python3
PIP = $(PYTHON) -m pip
.PHONY: build test
build:
$(PIP) install -e .
test:
$(PYTHON) -m pytest
[[tool.bumpcalver.file]]
path = "Makefile"
file_type = "makefile"
variable = "APP_VERSION"
version_standard = "default"
YAML config file¶
application:
name: ExampleApp
version: "2026.05.24.001"
database:
host: localhost
port: 5432
[[tool.bumpcalver.file]]
path = "config.yaml"
file_type = "yaml"
variable = "application.version"
version_standard = "default"
XML config file¶
<configuration>
<version>2026.05.24.001</version>
<application>
<name>ExampleApp</name>
</application>
</configuration>
[[tool.bumpcalver.file]]
path = "config.xml"
file_type = "xml"
variable = "version"
version_standard = "default"
Environment file (.env)¶
VERSION=2026.05.24.001
APP_NAME=myapp
DEBUG=false
DATABASE_URL=postgresql://localhost/mydb
[[tool.bumpcalver.file]]
path = ".env"
file_type = "env"
variable = "VERSION"
version_standard = "default"
Properties file (sonar-project.properties)¶
sonar.projectKey=myorg_myproject
sonar.organization=myorg
sonar.projectName=myproject
sonar.projectVersion=2026.05.24.001
sonar.sources=src
sonar.tests=tests
[[tool.bumpcalver.file]]
path = "sonar-project.properties"
file_type = "properties"
variable = "sonar.projectVersion"
version_standard = "default"
Documentation
BumpCalver Undo Documentation¶
Overview¶
BumpCalver now includes powerful undo functionality that allows you to revert version bump operations. This feature automatically creates backups of files before modification and maintains a history of operations that can be undone.
Features¶
- Automatic Backups: Files are automatically backed up before any version changes
- Operation History: Complete history of version operations with metadata
- Git Integration: Can undo git commits and tags created during version bumps
- Safety Validation: Checks for potential conflicts before undoing operations
- Selective Undo: Undo specific operations by ID or just the latest operation
CLI Commands¶
List Operation History¶
View recent version bump operations that can be undone:
bumpcalver --list-history
Example output:
Recent operations (showing last 10):
--------------------------------------------------------------------------------
1. 2025-10-12 14:30:15 | 2025.10.12.003 | 3 file(s) [TAG] [COMMIT]
ID: 20251012_143015_123
2. 2025-10-12 14:25:10 | 2025.10.12.002 | 2 file(s) [TAG]
ID: 20251012_142510_456
3. 2025-10-12 14:20:05 | 2025.10.12.001 | 1 file(s)
ID: 20251012_142005_789
--------------------------------------------------------------------------------
Use 'bumpcalver --undo' to undo the latest operation
Use 'bumpcalver --undo-id <operation_id>' to undo a specific operation
Undo Latest Operation¶
Undo the most recent version bump operation:
bumpcalver --undo
This will: 1. Restore all modified files from their backups 2. Delete any git tags that were created 3. Reset git commits (if auto-commit was used)
Undo Specific Operation¶
Undo a specific operation by its ID:
bumpcalver --undo-id 20251012_143015_123
How It Works¶
Backup Process¶
When you run a version bump command, BumpCalver automatically:
- Creates Backups: Before modifying any files, creates timestamped backups in
.bumpcalver/backups/ - Records Metadata: Stores operation details in
bumpcalver-history.json(root level) including: - Timestamp and operation ID
- New version number
- List of files modified
- Git operations performed (tags, commits)
-
Backup file locations
-
Performs Update: Executes the version bump as normal
- Saves History: Updates the history file for future undo operations
Undo Process¶
When you undo an operation, BumpCalver:
- Validates Safety: Checks if files have been modified since the backup
- Restores Files: Copies backup files over the current versions
- Undoes Git Operations:
- Deletes git tags that were created
- Resets git commits (if they match the recorded commit hash)
Safety Features¶
Validation Checks¶
Before performing an undo, BumpCalver validates:
- Backup files still exist
- Original files haven't been significantly modified since backup
- Git repository state is consistent
Warning Messages¶
You may see warnings like:
- File example.py may have been modified since backup - File was changed after the version bump
- Backup file not found - The backup file has been deleted or moved
- Current HEAD is not the expected commit - Git history has changed since the operation
Conflict Resolution¶
If warnings are detected, the undo operation will still proceed but may not be complete. You can:
- Review Changes: Check what files were restored vs. what couldn't be restored
- Manual Restoration: Manually fix any files that couldn't be automatically restored
- Git Operations: Manually undo git operations if they couldn't be automatically reverted
Configuration¶
Backup Storage¶
Backups and history are stored as follows:
your-project/
├── bumpcalver-history.json # Operation history (root level)
├── .bumpcalver/
│ └── backups/
│ ├── 20251012_143015_123_file1.py # Timestamped backups
│ ├── 20251012_143015_124_file2.toml
│ └── ...
├── your-source-files...
└── pyproject.toml
History Limits¶
- Operation Limit: Keeps last 50 operations to prevent unbounded growth
- File Cleanup: Old backup files can be cleaned up automatically
- Storage Location: Customize backup directory location if needed
Cleanup¶
Remove old backups (older than 30 days):
from bumpcalver.backup_utils import BackupManager
backup_manager = BackupManager()
backup_manager.cleanup_old_backups(days_to_keep=30)
Integration Examples¶
Basic Workflow¶
# Make a version bump
bumpcalver --build --git-tag
# List recent operations
bumpcalver --list-history
# Undo if needed
bumpcalver --undo
CI/CD Integration¶
# Version bump with safety net
bumpcalver --build --git-tag --auto-commit
# If tests fail, undo the version bump
if [ $? -ne 0 ]; then
echo "Tests failed, undoing version bump"
bumpcalver --undo
exit 1
fi
Development Workflow¶
# Experimental version bump
bumpcalver --custom "experimental"
# Test changes...
# If experiment fails, undo
bumpcalver --undo
# If experiment succeeds, make real version bump
bumpcalver --build --git-tag
Limitations¶
- Git Repository: Git undo operations only work within git repositories
- File Permissions: Backup/restore operations respect file system permissions
- External Changes: Cannot undo changes made by external tools after the version bump
- Backup Storage: Backup files consume disk space (cleaned up automatically)
Troubleshooting¶
Common Issues¶
"No operations found in history" - No version bump operations have been performed yet - History file may have been deleted
"Backup file not found"
- Backup files may have been manually deleted
- Check .bumpcalver/backups/ directory
"Current HEAD is not the expected commit" - Git history has changed since the version bump - Manual git operations may be needed
"File may have been modified since backup" - File was edited after the version bump - Review changes before proceeding with undo
Recovery¶
If undo operations fail, you can manually:
- Restore Files: Copy backup files from
.bumpcalver/backups/ - Check History: Review
bumpcalver-history.jsonfor operation details - Git Operations: Manually delete tags or reset commits using git commands
Best Practices¶
- Regular Cleanup: Periodically clean up old backups to save disk space
- Version Control: Ensure your project is under git version control for full undo capabilities
- Testing: Test undo functionality in a development environment first
- Backup Backups: Consider backing up the
.bumpcalver/directory in critical environments - Review Changes: Always review what changes will be undone before proceeding
Version Control Integration¶
Recommended .gitignore Entries¶
Add these entries to your .gitignore file to exclude backup and history files from version control:
# BumpCalver backup and history files
.bumpcalver/
bumpcalver-history.json
This ensures that: - Backup files remain local to each developer/environment - History doesn't clutter your repository - Sensitive or large backup files aren't committed - Each environment maintains its own undo history
AI Assistant Instructions¶
BumpCalver ships app-integration guidance for AI assistants as package
data — the same guidance an assistant would otherwise have to
reverse-engineer from this documentation site, bundled directly with the
version of bumpcalver you actually installed, so it can never drift out of
sync with an externally copy-pasted snippet.
This isn't guidance for using bumpcalver's own source code — it's guidance
for an assistant helping a developer configure bumpcalver in their own
project: authoring the [tool.bumpcalver] config block, picking the right
file_type for each version-carrying file, and choosing one of the three
versioning modes.
Quick start¶
python -m bumpcalver.ai_instructions claude --write # writes ./CLAUDE.md
python -m bumpcalver.ai_instructions copilot --write # writes ./.github/copilot-instructions.md
python -m bumpcalver.ai_instructions generic > AI_INSTRUCTIONS.md
Or in-process:
from bumpcalver import (
available_instruction_profiles,
get_app_instructions,
suggested_instruction_filename,
)
print(available_instruction_profiles()) # ('claude', 'copilot', 'generic')
print(get_app_instructions("claude"))
print(suggested_instruction_filename("claude")) # "CLAUDE.md"
Aliases are accepted: github-copilot → copilot, anthropic-claude →
claude, default → generic.
See API Reference for the full
get_app_instructions/available_instruction_profiles/
suggested_instruction_filename signatures.
CLI¶
usage: python -m bumpcalver.ai_instructions [-h] [--write] [--output PATH]
[profile]
profile— one ofclaude/copilot/generic(or an alias); defaults togeneric.--write— write to the profile's suggested destination file (CLAUDE.md,.github/copilot-instructions.md, orAI_INSTRUCTIONS.md) instead of stdout.--output PATH— write to an explicit path instead.PATHis validated to stay within the current working directory (see "Security" below) — this matters because the whole point of this CLI is that an AI assistant may invoke it directly, not just a human typing a path by hand.
Full instructions by profile¶
The three sections below are the exact, literal content of the packaged
instruction files, generated into this page at build time from the same
get_app_instructions() the CLI and Python API serve — not a manually
copied snapshot that could drift out of sync with what
python -m bumpcalver.ai_instructions <profile> actually outputs.
Generic¶
# Generic AI assistant instructions for apps using bumpcalver
Goal: correctly configure `bumpcalver` in an application repository —
authoring its `[tool.bumpcalver]` config and choosing the right CLI
invocation — without reverse-engineering the library's internals.
`bumpcalver` is a CLI/config-driven tool, not a library your code imports
and calls. "Integration" here means: get the config block right, pick the
correct `file_type` for every file that carries a version string, and pick
exactly one versioning mode.
## Setup: from zero to a working config
Follow this order — skipping steps (especially the "seed an initial version"
step) is the most common way a first setup silently does nothing.
### 1. Install
```bash
pip install bumpcalver
# or add "bumpcalver" to the project's dev dependencies
```
### 2. Decide where the config lives
- **If the project already has a `pyproject.toml`** (almost always true for
a Python package): add a `[tool.bumpcalver]` table to it. This is the
default choice.
- **If there is no `pyproject.toml`**, or the project's owner wants
bumpcalver config kept separate: create a standalone `bumpcalver.toml` in
the project root instead.
- If **both** exist in the same directory, bumpcalver uses `pyproject.toml`
and ignores `bumpcalver.toml` — never create both and expect the second
one to matter.
⚠️ **The two files use different key nesting — this is a real, easy-to-miss
trap:**
| In `pyproject.toml` | In standalone `bumpcalver.toml` |
|---|---|
| `[tool.bumpcalver]` table | keys at the **top level** of the file |
| `[[tool.bumpcalver.file]]` | `[[file]]` |
Writing `[[tool.bumpcalver.file]]` inside a standalone `bumpcalver.toml`
does not error — it just silently produces an empty file list, because
`bumpcalver.toml` is parsed flat (no `tool.bumpcalver` nesting expected). If
nothing gets updated after a `--build`, check this first.
### 3. Seed an initial version string in every target file
**bumpcalver finds and replaces an existing version string — it does not
create files or insert a new key.** Before writing any config, make sure
every file you intend to list already contains a literal version value in
the right shape, e.g.:
- Python: `__version__ = "2024.01.01"`
- TOML (`pyproject.toml` itself): `version = "2024.01.01"` under `[project]`
- JSON: `"version": "2024.01.01"` as a top-level key
- Dockerfile: `ARG VERSION=2024.01.01` and/or `ENV APP_VERSION=2024.01.01`
If a file is missing the key entirely, bumpcalver's update for that file
will fail (prints a "not found" message, doesn't write, doesn't error the
whole run) — that's a config/file mismatch to fix, not something bumpcalver
will fix for you.
### 4. Identify every file that needs updating, and map each to the table below
Walk the repo (or ask the user) for every file that carries this project's
version: the package's own version attribute, `pyproject.toml`'s
`project.version`, a Dockerfile `ARG`/`ENV`, a `package.json`-style file, a
docs page, etc. For each one, look up `file_type` in the table in the next
section and write one `[[tool.bumpcalver.file]]` (or `[[file]]`) block.
### 5. Choose `version_format`, `date_format`, `timezone`
If unsure, these are sane, verified defaults:
```toml
version_format = "{current_date}.{build_count:03}"
date_format = "%Y.%m.%d"
timezone = "America/New_York"
```
(`{current_date}` uses whatever `date_format` you set; `{build_count:03}`
zero-pads to 3 digits and only applies with `--build` — see "Versioning
modes" below for the full placeholder set including hybrid semver.)
### 6. Decide `git_tag` / `auto_commit`, and set them explicitly
Default to `false` for both unless the user explicitly asked for git
automation — see "Security / side-effect contract" below for why.
### 7. Add the `.gitignore` entries (see the dedicated section below)
### 8. Verify before the first real run
Always run `bumpcalver --dry-run` (add `--build` too if using build-count or
hybrid mode) immediately after writing the config, **before** running it for
real. It prints exactly what would change without writing anything:
```
[dry-run] Would bump version to 2024.01.02.001 in:
[dry-run] src/mypkg/__init__.py
[dry-run] pyproject.toml
```
If instead it prints `No files specified in the configuration.`, the config
wasn't found or parsed — check step 2's nesting trap first. If a file you
expected is missing from the list, check step 3 (the file's current content
doesn't match `variable`/`pattern`).
### Minimal working example (single file)
```toml
[tool.bumpcalver]
version_format = "{current_date}.{build_count:03}"
date_format = "%Y.%m.%d"
timezone = "America/New_York"
git_tag = false
auto_commit = false
[[tool.bumpcalver.file]]
path = "src/mypkg/__init__.py"
file_type = "python"
variable = "__version__"
```
### Typical Python package (multiple files, the common real-world case)
```toml
[tool.bumpcalver]
version_format = "{current_date}.{build_count:03}"
date_format = "%Y.%m.%d"
timezone = "America/New_York"
git_tag = true
auto_commit = false
[[tool.bumpcalver.file]]
path = "pyproject.toml"
file_type = "toml"
variable = "project.version"
version_standard = "python"
[[tool.bumpcalver.file]]
path = "src/mypkg/__init__.py"
file_type = "python"
variable = "__version__"
version_standard = "python"
```
Run `bumpcalver --build --dry-run` against this, confirm the preview looks
right, then drop `--dry-run` to apply it for real.
## Completion contract (always deliver all items)
1. A `[tool.bumpcalver]` table in `pyproject.toml` (or a standalone
`bumpcalver.toml`) with `version_format`, `date_format`, and `timezone`.
2. One `[[tool.bumpcalver.file]]` block **per file that carries a version
string**, with the correct `file_type` and the matching
`variable`/`directive`/`pattern` for that format (see the table below —
these are not interchangeable).
3. Exactly one versioning mode, chosen deliberately (see "Versioning modes").
4. If pre-release suffixes (`--beta`/`--rc`/`--release`/`--custom`) are
needed, the corresponding `beta_format`/`rc_format`/`release_format` keys.
5. An explicit statement of whether `git_tag`/`auto_commit` are enabled, and
that enabling them causes a **real git commit and tag** — not a preview.
6. `.bumpcalver/` and `bumpcalver-history.json` added to `.gitignore`.
7. A short explanation of any non-obvious `file_type`/`variable` mapping choice.
## Supported file types (as of this bumpcalver version)
| `file_type` | `variable` means | Notes |
|---|---|---|
| `python` | Python variable name, e.g. `__version__` | Regex substitution |
| `toml` | **Dot-separated path**, e.g. `project.version` | Style-preserving (comments/order survive) |
| `yaml` | **Dot-separated path**, e.g. `configuration.version` | Style-preserving (comments/order survive) |
| `json` | **Plain top-level key**, e.g. `version` — NOT a dot path | Nested keys are not supported |
| `xml` | `ElementTree.find()` path, e.g. `version` or `metadata/version` | See XML caveat below |
| `dockerfile` | Variable name | **Requires `directive = "ARG"` or `"ENV"`** |
| `makefile` | Makefile variable name, e.g. `APP_VERSION` | |
| `properties` | `KEY` in a `KEY=value` file | |
| `env` | `KEY` in a `KEY=value` file (`.env`) | Quotes are stripped on read |
| `setup.cfg` | Dot path (`metadata.version`) or a simple key | |
| `text` | Not used — the whole file *is* the version | For a bare `VERSION` file |
| `regex` | Any key name | **Requires `pattern`**: a regex with exactly one capture group around the version |
Third-party file types can be added via the `bumpcalver.handlers` entry-point
group without forking bumpcalver — see the plugin-authoring guide if a
project needs a format not in this table.
**Do not confuse `json`'s plain top-level key with `toml`/`yaml`'s dot path**
— they look similar but are different mechanisms. Using a dot path for a
JSON file's `variable` will silently fail to find the key.
## Versioning modes — pick exactly one
These are different mechanisms, not variations of one setting. Picking the
wrong one silently produces a version scheme the developer didn't ask for.
1. **Plain calendar** (default): `version_format` uses only `{current_date}`.
Every invocation produces a fresh date-based version.
2. **Calendar + build count**: `version_format` includes `{build_count}`
(optionally `{build_count:03}` for zero-padding) and the CLI is invoked
with `--build`. The build count increments only when invoked again on
the same date; a new date resets it to 1.
3. **Hybrid semver + calendar**: `version_format` includes `{major}`,
`{minor}`, and/or `{patch}` alongside `{current_date}`/`{build_count}`,
and the config has integer `major`/`minor`/`patch` keys. Bump the
semantic prefix with `--bump major|minor|patch` (this both increments the
value in config and persists it back to the config file — a real write).
## Constraints vs. cosmetic — do not confuse these
- `version_standard = "python"` on a `[[tool.bumpcalver.file]]` block is
**enforced**: it PEP-440-normalizes the version string before writing it
(e.g. strips leading zeros, converts separators). Any other value (or
omitting the key) is a no-op passthrough.
- **`file_type` is never validated against the file's actual content.**
Nothing stops a config from setting `file_type = "python"` on a Ruby file
— if the regex happens to match `__version__ = "..."`-shaped text it will
"work" by coincidence, not because Ruby is a supported format. For a
non-Python `KEY = "value"`-style file, use `file_type = "regex"` with an
explicit `pattern` instead of borrowing an unrelated handler.
## Known limitation
`xml`'s `update_version` preserves the `<?xml ?>` declaration and comments
nested *inside* the root element, but comments in the XML **prolog** (before
the root element's opening tag) are dropped on write — a structural
`ElementTree` limitation, not a bug. Flag this if a target XML file has
prolog comments worth preserving.
## Security / side-effect contract
- `git_tag = true` and `auto_commit = true` cause `bumpcalver` to create a
**real git tag** (and, with `auto_commit`, a **real commit**) on every
successful run — not a dry-run or a suggestion. State explicitly which of
these are enabled in any configuration you produce.
- `--dry-run` computes and prints what *would* change without writing
anything or touching git — use it to preview a config before committing
to it in CI.
- `--json` emits exactly one JSON object on stdout (log lines move to
stderr) — the machine-readable way to capture the computed version, e.g.
in a CI step: `` bumpcalver --build --json 2>/dev/null | jq -r '.version' ``.
- `--config-file PATH` (or `BUMPCALVER_CONFIG` env var) points at a config
outside the current directory; file paths inside that config resolve
relative to the config file's own directory, not the invoking cwd.
- `--undo`, `--undo-id`, and `--list-history` restore previous state from
`.bumpcalver/backups/` + `bumpcalver-history.json` (both written to the
current working directory). These flags are mutually exclusive with every
version-bump option, including `--dry-run`, `--config-file`, and `--json`.
## `.gitignore` (always add this when configuring bumpcalver in a new repo)
```gitignore
# BumpCalver backup and history files
.bumpcalver/
bumpcalver-history.json
```
## Common mistakes to avoid
- Do not use a dot path for a `json` file's `variable` — it must be a plain
top-level key.
- Do not set `file_type = "dockerfile"` without a `directive` — it's
required, not optional.
- Do not set `file_type = "regex"` without a `pattern` — and the pattern
must have exactly one capture group, or bumpcalver raises an error.
- Do not enable `git_tag`/`auto_commit` in an example/demo config without
saying so explicitly — this is a real, not simulated, side effect.
- Do not combine `--dry-run`/`--config-file`/`--json` with
`--undo`/`--undo-id`/`--list-history` — bumpcalver rejects this combination.
- Do not forget `.bumpcalver/` and `bumpcalver-history.json` in `.gitignore`.
## Prompt starters
"Set up bumpcalver for this Python package: bump `__version__` in
`src/mypkg/__init__.py` and `project.version` in `pyproject.toml` together,
using calendar + build count versioning, no git tagging."
"Add hybrid semver + calendar versioning to this repo: `major`/`minor`
starting at `1.0`, calendar suffix, git tag and commit enabled, and update
both `pyproject.toml` and a Dockerfile's `ARG VERSION`."
Claude¶
# Claude instructions for apps using bumpcalver
You are configuring `bumpcalver`, a CLI/config-driven calendar-versioning
tool, in an application repository. This is not a library you import and
call from app code — the entire integration surface is a `[tool.bumpcalver]`
config block plus the `bumpcalver` CLI invocation. Do not guess the schema;
follow this contract.
## Setup procedure — follow in order
1. **Install**: `pip install bumpcalver` (or add to dev dependencies).
2. **Pick where the config lives**:
- Project already has `pyproject.toml`? Add `[tool.bumpcalver]` to it.
This is the default choice.
- No `pyproject.toml`, or the user wants bumpcalver config separate?
Create a standalone `bumpcalver.toml` in the project root.
- If both exist, bumpcalver reads `pyproject.toml` and ignores
`bumpcalver.toml` entirely — never create both.
- **Nesting differs between the two** and this is a real trap: in
`pyproject.toml` it's `[tool.bumpcalver]` + `[[tool.bumpcalver.file]]`;
in standalone `bumpcalver.toml` it's flat — keys at the top level, and
`[[file]]` (not `[[tool.bumpcalver.file]]`). Using the nested form in a
standalone file doesn't error, it just silently produces an empty file
list.
3. **Confirm every target file already has a version string to replace.**
bumpcalver finds-and-replaces an existing value; it does not create
files or insert a new key. If a file is missing the key, ask the user to
seed one first (e.g. `__version__ = "2024.01.01"`) — don't assume
bumpcalver will add it.
4. **Enumerate every file that carries a version** (package version
attribute, `pyproject.toml`'s own `project.version`, Dockerfile
`ARG`/`ENV`, etc.) and write one `[[tool.bumpcalver.file]]`/`[[file]]`
block per file using the reference table below.
5. **Set `version_format`/`date_format`/`timezone`.** If unsure, use:
`version_format = "{current_date}.{build_count:03}"`,
`date_format = "%Y.%m.%d"`, `timezone = "America/New_York"`.
6. **Set `git_tag`/`auto_commit` explicitly** — default `false` unless the
user asked for git automation (real side effect, see below).
7. **Add the `.gitignore` entries** (below).
8. **Verify with `bumpcalver --dry-run`** (add `--build` if using build
count or hybrid mode) before running for real. It prints exactly what
would change, e.g. `[dry-run] Would bump version to ... in: ...`. If it
prints `No files specified in the configuration.`, re-check step 2's
nesting. If an expected file is missing from the preview, re-check step 3.
### Minimal example
```toml
[tool.bumpcalver]
version_format = "{current_date}.{build_count:03}"
date_format = "%Y.%m.%d"
timezone = "America/New_York"
git_tag = false
auto_commit = false
[[tool.bumpcalver.file]]
path = "src/mypkg/__init__.py"
file_type = "python"
variable = "__version__"
```
### Typical Python package (the common real-world case)
```toml
[tool.bumpcalver]
version_format = "{current_date}.{build_count:03}"
date_format = "%Y.%m.%d"
timezone = "America/New_York"
git_tag = true
auto_commit = false
[[tool.bumpcalver.file]]
path = "pyproject.toml"
file_type = "toml"
variable = "project.version"
version_standard = "python"
[[tool.bumpcalver.file]]
path = "src/mypkg/__init__.py"
file_type = "python"
variable = "__version__"
version_standard = "python"
```
## Completion contract
When asked to configure bumpcalver, deliver all of the following, not a
partial subset:
1. A `[tool.bumpcalver]` table in `pyproject.toml`, or a standalone
`bumpcalver.toml` if the project doesn't want bumpcalver config mixed
into `pyproject.toml` — with `version_format`, `date_format`, `timezone`.
2. One `[[tool.bumpcalver.file]]` block per file that carries a version
string, each with the correct `file_type` for that file's real format
(table below) and the matching `variable`/`directive`/`pattern`.
3. Exactly one versioning mode, chosen deliberately and stated in your
response — see "Versioning modes."
4. `.bumpcalver/` and `bumpcalver-history.json` added to `.gitignore`.
5. If `git_tag`/`auto_commit` are set to `true`, say so explicitly in your
response — these are real git operations, not previewed ones.
## File type reference
| `file_type` | `variable` semantics | Required extra keys |
|---|---|---|
| `python` | Python variable name (`__version__`) | — |
| `toml` | dot path (`project.version`) | — |
| `yaml` | dot path (`configuration.version`) | — |
| `json` | **plain top-level key only** — not a dot path | — |
| `xml` | `ElementTree.find()` path (`version`, `metadata/version`) | — |
| `dockerfile` | variable name | `directive = "ARG"` or `"ENV"` (mandatory) |
| `makefile` | Makefile variable name | — |
| `properties` | `KEY=value` key | — |
| `env` | `.env` `KEY=value` key | — |
| `setup.cfg` | dot path or simple key | — |
| `text` | none — whole file is the version | — |
| `regex` | any name | `pattern` (mandatory, exactly one capture group) |
If a target file's format isn't in this table, do not force-fit
`file_type = "python"` or another close-enough handler onto it just because
its regex happens to match — that's coincidental, not supported, behavior
(see "Enforced vs. coincidental" below). Prefer `file_type = "regex"` with
an explicit `pattern` for `KEY = "value"`-style files (Ruby, Rust, Go,
Java, etc.), or point the user at bumpcalver's `bumpcalver.handlers`
entry-point plugin mechanism if they want a real, reusable handler for their
own tooling.
## Versioning modes — pick exactly one, and say which one you picked
1. **Plain calendar** (default) — `version_format` uses only
`{current_date}`.
2. **Calendar + build count** — `version_format` includes `{build_count}`
(e.g. `{build_count:03}`), CLI invocation uses `--build`.
3. **Hybrid semver + calendar** — `version_format` includes `{major}`/
`{minor}`/`{patch}`, config has integer `major`/`minor`/`patch` keys, and
`--bump major|minor|patch` bumps the semantic prefix (this writes the new
value back into the config file — a real, persistent change).
Do not mix these up: adding `{build_count}` to a hybrid `version_format`
without also documenting `--build` usage, or vice versa, produces a config
that silently behaves differently than the developer expects.
## Enforced vs. coincidental — the trap to avoid
`version_standard = "python"` is enforced: bumpcalver PEP-440-normalizes the
version string on write. Everything else about `file_type` matching is
**not validated** — bumpcalver will happily run a Python-file regex against
a Ruby file and "succeed" if the text shape happens to match. Do not present
that coincidence as intentional support for a format bumpcalver doesn't
actually have a handler for.
## Known, permanent limitation
XML comments in the prolog (before the root `<element>` opens) are dropped
on `update_version` — an `ElementTree` structural limitation. Comments
nested inside the root element, and the `<?xml ?>` declaration, are
preserved. Mention this if the target XML file has prolog comments.
## Side effects — state these explicitly in your response
- `git_tag = true` / `auto_commit = true` → real git tag / real git commit
on every successful bump. Not a preview.
- `--dry-run` → preview only, writes nothing, no git operations.
- `--json` → single JSON object on stdout, all log lines on stderr. Use for
CI: `` bumpcalver --build --json 2>/dev/null | jq -r '.version' ``.
- `--config-file PATH` / `BUMPCALVER_CONFIG` env var → use a config outside
the cwd; file paths inside it resolve relative to *that file's* directory.
- `--undo` / `--undo-id` / `--list-history` → reads/restores from
`.bumpcalver/backups/` + `bumpcalver-history.json` in the cwd. Mutually
exclusive with every version-bump flag, including `--dry-run`/`--json`/
`--config-file`.
## `.gitignore` — add whenever you configure bumpcalver in a repo that doesn't already have it
```gitignore
# BumpCalver backup and history files
.bumpcalver/
bumpcalver-history.json
```
## Common mistakes to avoid
- Using a dot path for `json`'s `variable` (it must be a plain top-level key).
- Omitting `directive` on a `dockerfile` entry.
- Omitting `pattern` on a `regex` entry, or writing a pattern with more/fewer
than one capture group.
- Silently enabling `git_tag`/`auto_commit` without telling the user this
produces real repository state changes.
- Suggesting `--dry-run` (or `--json`/`--config-file`) alongside
`--undo`/`--undo-id`/`--list-history` — bumpcalver rejects that combination.
- Forgetting `.gitignore` entries for `.bumpcalver/`/`bumpcalver-history.json`.
## Prompt starters
"Configure bumpcalver for this repo: bump `__version__` in
`src/mypkg/__init__.py` and `project.version` in `pyproject.toml` together,
calendar + build count, no git tagging."
"Add hybrid semver + calendar versioning: major/minor starting at 1.0,
calendar build suffix, git tag and commit enabled, updating both
`pyproject.toml` and a Dockerfile's `ARG VERSION`."
Copilot¶
# GitHub Copilot instructions for apps using bumpcalver
`bumpcalver` is a CLI/config-driven calendar-versioning tool — there is no
class or function to import and call from application code. Integration
means authoring a correct `[tool.bumpcalver]` config block and choosing the
right CLI invocation.
## Setup checklist (in order)
- [ ] **Install**: `pip install bumpcalver` (or add to dev dependencies).
- [ ] **Pick config location**: `pyproject.toml`'s `[tool.bumpcalver]` if
the project has one (default choice); otherwise a standalone
`bumpcalver.toml`. If both exist, `pyproject.toml` wins and
`bumpcalver.toml` is ignored — never create both.
- [ ] ⚠️ **Nesting differs by file**: `pyproject.toml` uses
`[tool.bumpcalver]` + `[[tool.bumpcalver.file]]`; standalone
`bumpcalver.toml` is flat — top-level keys + `[[file]]`. Using the
nested form in a standalone file silently produces an empty file list
(no error).
- [ ] **Seed an initial version string** in every target file first —
bumpcalver replaces an existing value, it does not create files or
insert new keys. Missing key → that file's update silently fails
(others still succeed).
- [ ] **List every file that carries a version** (package version
attribute, `pyproject.toml`'s own `project.version`, Dockerfile
`ARG`/`ENV`, etc.) as one `[[tool.bumpcalver.file]]`/`[[file]]` block
each, using the reference table below.
- [ ] **Set `version_format`/`date_format`/`timezone`** — if unsure:
`"{current_date}.{build_count:03}"` / `"%Y.%m.%d"` /
`"America/New_York"`.
- [ ] **Set `git_tag`/`auto_commit` explicitly** — default `false` unless
asked for git automation.
- [ ] **Add `.gitignore` entries** (below).
- [ ] **Verify with `bumpcalver --dry-run`** before a real run. Prints
`No files specified in the configuration.` → recheck the nesting
trap. Expected file missing from preview → recheck the seeded-version
step.
### Minimal example
```toml
[tool.bumpcalver]
version_format = "{current_date}.{build_count:03}"
date_format = "%Y.%m.%d"
timezone = "America/New_York"
git_tag = false
auto_commit = false
[[tool.bumpcalver.file]]
path = "src/mypkg/__init__.py"
file_type = "python"
variable = "__version__"
```
### Typical Python package
```toml
[tool.bumpcalver]
version_format = "{current_date}.{build_count:03}"
date_format = "%Y.%m.%d"
timezone = "America/New_York"
git_tag = true
auto_commit = false
[[tool.bumpcalver.file]]
path = "pyproject.toml"
file_type = "toml"
variable = "project.version"
version_standard = "python"
[[tool.bumpcalver.file]]
path = "src/mypkg/__init__.py"
file_type = "python"
variable = "__version__"
version_standard = "python"
```
## Checklist (complete every item)
- [ ] `[tool.bumpcalver]` table added to `pyproject.toml`, or a standalone
`bumpcalver.toml`, with `version_format`, `date_format`, `timezone`.
- [ ] One `[[tool.bumpcalver.file]]` block per file that carries a version
string, each with the correct `file_type` and matching
`variable`/`directive`/`pattern` (see table).
- [ ] Exactly one versioning mode chosen (plain calendar / calendar+build /
hybrid semver+calendar) — not a mix.
- [ ] If pre-release suffixes are needed: `beta_format`/`rc_format`/
`release_format` config keys added.
- [ ] `git_tag`/`auto_commit` values stated explicitly — `true` means a
**real git tag/commit** on every run, not a preview.
- [ ] `.bumpcalver/` and `bumpcalver-history.json` added to `.gitignore`.
## `file_type` → `variable` reference table
| `file_type` | `variable` is... | Extra required key |
|---|---|---|
| `python` | a Python variable name, e.g. `__version__` | — |
| `toml` | a dot path, e.g. `project.version` | — |
| `yaml` | a dot path, e.g. `configuration.version` | — |
| `json` | a **plain top-level key** — not a dot path | — |
| `xml` | an `ElementTree.find()` path, e.g. `version` | — |
| `dockerfile` | a variable name | `directive` = `"ARG"` or `"ENV"` |
| `makefile` | a Makefile variable name | — |
| `properties` | a `KEY=value` key | — |
| `env` | a `.env` `KEY=value` key | — |
| `setup.cfg` | a dot path or simple key | — |
| `text` | not used (whole file is the version) | — |
| `regex` | any name | `pattern` = regex, exactly one capture group |
⚠️ **`json` and `toml`/`yaml` look similar but differ**: JSON's `variable`
is a plain top-level key, TOML/YAML's is a dot-separated path. Using a dot
path for JSON silently fails to find the key.
## Versioning modes (pick one)
1. **Plain calendar** (default) — `version_format` uses only `{current_date}`.
2. **Calendar + build count** — add `{build_count}` to `version_format`,
invoke with `--build`.
3. **Hybrid semver + calendar** — add `{major}`/`{minor}`/`{patch}` to
`version_format`, add integer `major`/`minor`/`patch` config keys, bump
with `--bump major|minor|patch` (writes the new value back to config).
## Enforced vs. cosmetic
- `version_standard = "python"` → **enforced** PEP-440 normalization on write.
- `file_type` → **not validated** against the file's real content. A
"working" mismatched `file_type` (e.g. `python` on a Ruby file) is
coincidental regex overlap, not real support — use `file_type = "regex"`
with an explicit `pattern` for unsupported `KEY = "value"` formats instead.
## Known limitation
`xml` drops comments in the prolog (before the root element opens) on
write — preserves the `<?xml ?>` declaration and comments nested inside the
root element. `ElementTree` structural limitation, not a bug.
## Side effects to call out explicitly
- `git_tag = true` / `auto_commit = true` — real git tag / real git commit.
- `--dry-run` — preview only, no writes, no git operations.
- `--json` — one JSON object on stdout, log lines move to stderr; use for
CI: `bumpcalver --build --json 2>/dev/null | jq -r '.version'`.
- `--config-file PATH` / `BUMPCALVER_CONFIG` — config outside cwd; paths in
it resolve relative to *its own* directory.
- `--undo` / `--undo-id` / `--list-history` — mutually exclusive with every
version-bump flag (including `--dry-run`/`--json`/`--config-file`).
## `.gitignore` snippet
```gitignore
# BumpCalver backup and history files
.bumpcalver/
bumpcalver-history.json
```
## Common mistakes to avoid
- ❌ Dot path for a `json` file's `variable`.
- ❌ `dockerfile` entry missing `directive`.
- ❌ `regex` entry missing `pattern`, or a pattern without exactly one
capture group.
- ❌ Enabling `git_tag`/`auto_commit` without flagging the real side effect.
- ❌ Combining `--dry-run`/`--json`/`--config-file` with the undo flags.
- ❌ Forgetting the `.gitignore` entries.
## Prompt starters
"Set up bumpcalver: bump `__version__` in `src/mypkg/__init__.py` and
`project.version` in `pyproject.toml` together, calendar + build count, no
git tagging."
"Add hybrid semver + calendar versioning: major/minor at 1.0, calendar
suffix, git tag and commit on, updating `pyproject.toml` and a Dockerfile's
`ARG VERSION`."
What these instructions cover¶
- A step-by-step setup procedure from a blank repo: install, decide between
pyproject.tomland a standalonebumpcalver.toml(including the flat-vs- nested key trap between the two), seed an initial version string in every target file (bumpcalver replaces existing values, it does not create files or insert keys), map every file to afile_type, pick saneversion_format/date_format/timezonedefaults, and verify with--dry-runbefore a real run — plus copy-paste-ready minimal and "typical Python package" example configs, both verified against the real CLI. - All 12 built-in
file_types and whatvariablemeans for each (a plain key vs. a dot path vs. anElementTree.find()path — these are genuinely different mechanisms, not variations of one setting). - The three versioning modes (plain calendar, calendar + build count, hybrid semver + calendar) and how to pick one.
- Pre-release suffix flags and their config keys.
- Which config keys have real side effects (
git_tag/auto_commitcreate an actual git tag/commit, not a preview). --dry-run,--json, and--config-filefor previewing, scripting, and monorepo/cross-directory use.- The undo/backup system and the
.gitignoreentries a new bumpcalver integration should add. - One permanent, structural limitation (XML prolog comments) worth knowing about up front.
What these instructions do NOT cover¶
Being explicit about gaps matters more than it might seem — an AI assistant reading documentation will trust silence as "not applicable," which is worse than an honest "not covered yet":
- The
bumpcalver.handlersplugin/entry-point mechanism for registering a customfile_typefrom a third-party package is mentioned in passing but not walked through step by step — see the development guide for the full recipe if a project needs a file format with no built-in or regex-compatible handler. - Undo internals (backup file naming,
bumpcalver-history.json's exact schema) beyond "these two paths exist and should be gitignored" — see the Undo documentation for the full mechanics. - CI/CD recipes beyond the single
--json/jqexample already in the instructions — see the CLI Reference for the full--jsonpayload shape per case.
Security¶
--output is treated as untrusted input, not a trusted human-typed path —
the entire premise of this feature is that an AI assistant may invoke this
CLI directly, and a misdirected instruction, a reasoning bug, or a prompt
injection could produce an adversarial path argument. _resolve_output_path
resolves the destination (following symlinks) and rejects anything that
isn't a descendant of the current working directory, using Path.parents
containment rather than a string-prefix check (a prefix check would wrongly
treat a sibling directory like project-evil/ as being inside project/).
This is covered by dedicated regression tests
(tests/test_ai_instructions.py) that must not be weakened or removed.
Packaging¶
The three profile .md files ship as package data under
bumpcalver/assets/ai/ — verified with a real python -m build +
install-into-a-clean-venv check, not just editable-mode testing, since
packaging misconfiguration is easy to miss in dev mode and only surfaces for
someone doing a real pip install.
Keeping this in sync¶
If you're changing bumpcalver's public config schema (a new file_type, a
new CLI flag, a new config key with a real side effect), update
src/bumpcalver/assets/ai/*.md in the same change — the "Full instructions
by profile" section above regenerates from those files automatically at
mkdocs build time (via scripts/mkdocs_hooks.py), so there's no separate
docs-page edit to remember; editing the source files is the whole job.
A regression test
(test_get_app_instructions_documents_every_builtin_file_type) asserts
every file_type in _HANDLER_REGISTRY is mentioned in the generic
profile, but that only catches missing file types — it can't catch stale
prose about CLI flags or config keys, so this has to be a deliberate habit,
not something a test alone will enforce.
Mike Documentation Versioning - Quick Reference¶
Quick Commands¶
Deploy Documentation¶
# Deploy current version (auto-detected)
make create-docs # Push to remote
make create-docs-local # Local only
# Deploy development version
make create-docs-dev # Push dev version
# Deploy specific version
python3 scripts/deploy_docs.py deploy --version 2025.08.01 --aliases latest stable --push
Manage Versions¶
# List all versions
make list-docs
# Serve locally (all versions)
make serve-docs
# Delete version
make delete-version VERSION=2025.07.01
# Set default version
make set-default-version VERSION=latest
Advanced Usage¶
# Deploy with custom title
python3 scripts/deploy_docs.py deploy --version 2025.08.01 --title "August 2025 Release" --push
# Deploy dev version with custom name
python3 scripts/deploy_docs.py deploy --dev --version staging --push
# Deploy without aliases
python3 scripts/deploy_docs.py deploy --version 2025.08.01 --push
Version Strategy¶
| Version Type | Format | Example | When to Use |
|---|---|---|---|
| Release | YYYY.MM.DD | 2025.08.01 | Tagged releases |
| Development | dev | dev | Active development |
| Staging | staging | staging | Pre-release testing |
| Aliases | latest/stable | latest | User-friendly URLs |
URL Structure¶
| URL | Points To | Description |
|---|---|---|
/ |
Default version | Usually latest |
/latest/ |
Latest release | Most recent version |
/stable/ |
Stable release | Production-ready |
/dev/ |
Development | Bleeding edge |
/2025.08.01/ |
Specific version | Permanent link |
Integration Points¶
With BumpCalver¶
- Auto-detects version from
makefile,pyproject.toml,__init__.py - Consistent versioning across project and docs
- Automated workflow on version bumps
With GitHub Actions¶
devbranch →devdocumentationmainbranch →latestdocumentation- Git tags → versioned +
stabledocumentation
With MkDocs Material Theme¶
- Automatic version selector in navigation
- Responsive design across versions
- Search within specific versions
Development
Contributing to BumpCalver¶
Thank you for your interest in contributing to BumpCalver! This guide will help you get started with contributing to the project, whether you're fixing bugs, adding features, improving documentation, or writing tests.
Ways to Contribute¶
- 🐛 Report Bugs: Found something broken? Let us know!
- ✨ Add Features: Implement new functionality or file format support
- 📚 Improve Documentation: Help make our docs clearer and more comprehensive
- 🧪 Add Tests: Increase test coverage and reliability
- 🔧 Fix Issues: Pick up existing issues and solve problems
- 💡 Suggest Improvements: Share ideas for making BumpCalver better
Getting Started¶
1. Fork and Clone the Repository¶
# Fork the repository on GitHub, then clone your fork
git clone https://github.com/YOUR_USERNAME/bumpcalver.git
cd bumpcalver
# Add the original repository as upstream
git remote add upstream https://github.com/devsetgo/bumpcalver.git
2. Set Up Your Development Environment¶
Prerequisites¶
- Python 3.9 or higher
- Git
- Make (optional, for using the Makefile)
Create a Virtual Environment¶
# Create and activate a virtual environment
python -m venv _venv
source _venv/bin/activate # On Windows: _venv\Scripts\activate
# Or if you prefer using the existing one
source _venv/bin/activate
Install Dependencies¶
# Install development dependencies
pip install -r requirements.txt
# Or use the Makefile
make install
Set Up Pre-commit Hooks¶
# Install pre-commit hooks for code quality
make pre-commit
# Or manually:
pre-commit install
3. Development Workflow¶
Create a Feature Branch¶
# Create a new branch for your feature/fix
git checkout -b feature/your-feature-name
# Or for bug fixes:
git checkout -b fix/issue-description
Make Your Changes¶
Follow the project structure:
bumpcalver/
├── src/bumpcalver/ # Main package code
│ ├── cli.py # Command-line interface
│ ├── config.py # Configuration handling
│ ├── handlers.py # File format handlers
│ ├── utils.py # Utility functions
│ ├── git_utils.py # Git operations
│ ├── undo_utils.py # Undo functionality
│ └── backup_utils.py # Backup management
├── tests/ # Test suite
│ ├── test_*.py # Test modules
│ └── test_files/ # Test data
├── docs/ # Documentation
└── examples/ # Example configurations
4. Code Quality Standards¶
Code Formatting¶
Ruff is the single tool for linting, import
sorting, unused-import/variable removal, and formatting — it replaced a
previous stack of isort/black/autoflake/flake8/autopep8 that all did
overlapping parts of the same job with separate, easy-to-drift configs.
[tool.ruff.lint] in pyproject.toml selects rule
groups C/F/E/W/B/I (the I group is ruff's isort-compatible
import sorter); [tool.ruff.format] configures its Black-compatible
formatter.
# Fix lint issues (incl. import order) and reformat code
make format
# make ruff is an alias for the same thing, kept for muscle memory
make ruff
make mypy # Type-check src/bumpcalver
# Validate without changes (ruff format --check, ruff check, mypy)
make validate
Type Checking¶
src/bumpcalver is type-checked with mypy (config in pyproject.toml's
[tool.mypy]), both as a pre-commit hook and as a standalone type-check
job in CI (.github/workflows/testing.yml) — it only needs to run once,
not across the full OS/Python test matrix, since it checks against a single
pinned python_version. Only src/bumpcalver is checked, not tests/;
test code leans on unittest.mock/monkeypatch patterns that are
dynamically typed by nature, so checking it doesn't pay for itself the way
checking the library's public surface does.
Code Style Guidelines¶
- Follow PEP 8: Python code should follow PEP 8 style guidelines
- Type Hints: Use type hints for function parameters and return values
- Docstrings: Document functions and classes with clear docstrings
- Comments: Explain complex logic with inline comments
Example:
def parse_version(
version: str,
version_format: Optional[str] = None,
date_format: Optional[str] = None
) -> Optional[tuple]:
"""Parse a version string and return date and count components.
This function can parse version strings in various formats based on
the provided format specifications.
Args:
version: The version string to parse
version_format: Format template for the version
date_format: Date format specification
Returns:
Tuple of (date_string, build_count) or None if parsing fails
Example:
>>> parse_version("24.Q4.001", "{current_date}.{build_count:03}", "%y.Q%q")
('24.Q4', 1)
"""
# Implementation here...
Testing¶
Running Tests¶
# Run all tests
make test
# Run specific test files
python -m pytest tests/test_utils.py -v
# Run tests with coverage
make test-coverage
# Quick tests (no pre-commit hooks)
make quick-test
Writing Tests¶
Test Structure¶
# tests/test_your_feature.py
import pytest
from src.bumpcalver.your_module import your_function
class TestYourFeature:
"""Test suite for your feature."""
def test_basic_functionality(self):
"""Test the basic happy path."""
result = your_function("input")
assert result == "expected_output"
def test_edge_cases(self):
"""Test edge cases and error conditions."""
with pytest.raises(ValueError):
your_function("invalid_input")
@pytest.mark.parametrize("input_val,expected", [
("input1", "output1"),
("input2", "output2"),
("input3", "output3"),
])
def test_multiple_cases(self, input_val, expected):
"""Test multiple scenarios with parametrized tests."""
result = your_function(input_val)
assert result == expected
Calendar Versioning Tests¶
When adding new date format support, add comprehensive tests:
# Add to tests/test_calver_comprehensive.py
def test_your_new_format(self):
"""Test your new calendar versioning format."""
test_cases = [
("version_string", "version_format", "date_format", "expected_date", expected_count),
# Add multiple test cases
]
for version, version_format, date_format, expected_date, expected_count in test_cases:
result = parse_version(version, version_format, date_format)
assert result is not None, f"Failed to parse {version}"
date_part, build_count = result
assert date_part == expected_date
assert build_count == expected_count
Property-Based Tests¶
Hand-picked example cases (as above) are good at pinning down specific
known formats, but the format-string-to-regex translation in utils.py
(parse_version/_parse_hybrid_version/_clean_version_suffixes) is
general enough that bugs tend to hide in combinations nobody thought to
write an example for — that's exactly how the bug fixed alongside
tests/test_version_parsing_properties.py was found (the CLI's own
built-in zero-config defaults never actually round-tripped). For this kind
of "any valid input matching this shape should behave correctly" logic,
prefer a Hypothesis property test
over enumerating more examples by hand:
# tests/test_version_parsing_properties.py
from datetime import date
from hypothesis import given, settings
from hypothesis import strategies as st
from src.bumpcalver.utils import parse_version
_REASONABLE_DATES = st.dates(min_value=date(2000, 1, 1), max_value=date(2099, 12, 31))
_BUILD_COUNTS = st.integers(min_value=0, max_value=9999)
@given(the_date=_REASONABLE_DATES, build_count=_BUILD_COUNTS)
@settings(max_examples=200)
def test_dot_separated_calver_round_trips(the_date, build_count):
version_format = "{current_date}.{build_count:03}"
date_format = "%Y.%m.%d"
date_str = the_date.strftime(date_format)
version_string = version_format.format(current_date=date_str, build_count=build_count)
assert parse_version(version_string, version_format, date_format) == (date_str, build_count)
Scope the strategy to a fixed, known-supported version_format/
date_format pair and randomize the values plugged into it (dates,
counts, semver components) — don't also randomize the format strings
themselves. Some format combinations are inherently ambiguous to parse
(that's a property of the format, not a bug), so randomizing format
strings produces spurious failures unrelated to real parsing bugs. If
Hypothesis finds a failure, it shrinks to the smallest failing example and
that's usually enough to see the bug immediately; the .hypothesis/
example database it creates locally is gitignored.
Test Data and Isolation¶
Use the test utilities for isolated testing:
from tests.test_utils_isolated import isolated_test_environment, create_test_file
def test_with_temp_files():
"""Test using temporary files."""
with isolated_test_environment() as temp_dir:
test_file = create_test_file(
temp_dir,
"test_file.py",
'__version__ = "1.0.0"\n'
)
# Your test logic here
# Files are automatically cleaned up
Adding New Features¶
File Format Support¶
Every supported file_type is backed by a VersionHandler subclass in
src/bumpcalver/handlers.py. All of them implement the same two-method
contract (read_version/update_version) defined on the abstract base
class — see the API Reference for the full,
generated list of existing handlers and the base class's shared helpers.
To add support for a new file format:
-
Check whether you actually need a new handler. If your format is simple
KEY=valuelines (like.properties/.env), or the version is guarded by a directive keyword on its own line (like Dockerfile'sARG/ENV), the base class already has helpers for exactly that — see step 2 before writing a parser from scratch. -
Create a Handler, reusing base-class helpers where they fit your format. For a
KEY=valuefile,_read_key_value_file/_update_key_value_filedo the parsing/writing for you (this is a real, tested example — it's exactly howPropertiesVersionHandlerandEnvVersionHandlerare implemented):
class IniVersionHandler(VersionHandler):
"""Handler for INI-style key=value files, e.g. an app.ini VERSION= line."""
def read_version(self, file_path: str, variable: str, **kwargs) -> Optional[str]:
return self._read_key_value_file(file_path, variable)
def update_version(self, file_path: str, variable: str, new_version: str, **kwargs) -> bool:
new_version = self._format_version_with_standard(new_version, **kwargs)
return self._update_key_value_file(file_path, variable, new_version, "Setting")
If your format instead needs a regex substitution in place (like Python,
Makefile, or Dockerfile files), use _handle_regex_update the same way
PythonVersionHandler.update_version does. Either way, call
self._format_version_with_standard(new_version, **kwargs) first so your
handler respects the version_standard = "python" config option (PEP 440
normalization) the same way every other handler does.
- Register the Handler by adding it to
_HANDLER_REGISTRYinhandlers.py:
_HANDLER_REGISTRY: Dict[str, type] = {
# ... existing entries
"your_format": YourFormatHandler,
}
- Add Tests in
tests/test_handlers.py. Prefer a real temporary file over mockingopen/the underlying parser where practical — that's what actually catches formatting-fidelity bugs (see the YAML/TOML/XML handler tests for examples: they round-trip a real file and assert comments/key order survive, which mocked tests can't verify):
def test_your_format_handler_round_trip(tmp_path):
handler = YourFormatHandler()
config_file = tmp_path / "app.your_format"
config_file.write_text("VERSION=1.0.0\n", encoding="utf-8")
assert handler.read_version(str(config_file), "VERSION") == "1.0.0"
assert handler.update_version(str(config_file), "VERSION", "2.0.0") is True
assert "VERSION=2.0.0" in config_file.read_text(encoding="utf-8")
- Update Documentation:
- Add the new
file_typevalue to the list in README.md/docs/index.md. - Add a
[[tool.bumpcalver.file]]example todocs/examples/configuration.md. - No changes needed to
docs/modules.md/cli-reference.md— those are generated from the code, so your new handler's docstring (and the_HANDLER_REGISTRYentry) will show up automatically next time the docs are built. - Update
src/bumpcalver/assets/ai/*.md(all three profiles) with the newfile_type's row in the reference table — these ship as package data for AI assistants configuring bumpcalver in other repos (see AI Assistant Instructions) and, unlikedocs/modules.md, are not generated from the code, so they drift silently if forgotten. A regression test (test_get_app_instructions_documents_every_builtin_file_type) catches a missingfile_typerow, but not stale prose about existing ones — review the three files by hand for any change to CLI flags or config keys with real side effects, not just new file types.
Distributing Your Handler as a Plugin¶
Steps 1-2 above (writing the VersionHandler subclass) are identical whether
you're contributing it back to bumpcalver or shipping it in your own
package. If it's proprietary, niche, or you'd just rather not wait on a PR,
skip step 3 (editing _HANDLER_REGISTRY) — register it via the
bumpcalver.handlers entry-point group instead, from your own package's
pyproject.toml:
[project.entry-points."bumpcalver.handlers"]
myformat = "my_package.handlers:MyFormatHandler"
Once your package is installed in the same environment as bumpcalver
(pip install your-package), file_type = "myformat" becomes usable in
[[tool.bumpcalver.file]] entries — no fork, no PR, no changes to
bumpcalver itself. bumpcalver discovers it via
importlib.metadata.entry_points()
the first time a file_type lookup misses the built-in registry, and caches
the result for the rest of the process.
A complete, installable example lives in
examples/bumpcalver-plugin-example/ —
it registers an ini file_type that doesn't exist anywhere in bumpcalver's
own source, and its README walks through installing it and running
bumpcalver --build against it.
A few things worth knowing about how discovery behaves:
- Built-in file_types always win. If your plugin registers a name that
collides with a built-in (
"toml","json", etc.),bumpcalveruses the built-in and prints a warning to stderr — a plugin can add new file types, not silently override existing ones. Two plugins registering the same new name is resolved the same way: first one found wins, with a warning. - A broken plugin doesn't break your build. If your entry point fails to
import, or doesn't point at a
VersionHandlersubclass,bumpcalverprints a warning and skips it — commands that don't touch your file_type still work. available_file_types()(inbumpcalver.handlers) returns every usablefile_type, built-in and plugin alike — useful if you want to assert your plugin registered correctly, e.g. in your own package's tests.
Date Format Support¶
To add new date format patterns:
- Update Utils in
src/bumpcalver/utils.py:
def get_current_datetime_version(timezone: str, date_format: str) -> str:
"""Add handling for your new date format tokens."""
# Add custom format handling if needed
- Add Comprehensive Tests in
tests/test_calver_comprehensive.py:
def test_your_date_format(self):
"""Test your new date format pattern."""
# Add test cases for your format
- Update Documentation:
- Add to calendar versioning guide
- Include real-world examples
Documentation¶
Writing Documentation¶
- Use Clear Examples: Include practical, working examples
- Follow Markdown Standards: Use consistent formatting
- Test Code Examples: Ensure all code examples actually work
- Cross-Reference: Link to related documentation
Building Documentation Locally¶
# Build and serve documentation locally
make serve-docs
# Build documentation for deployment
make create-docs-local
Documentation Structure¶
docs/
├── index.md # Main documentation
├── quickstart.md # Getting started guide
├── calendar-versioning-guide.md # CalVer patterns (new!)
├── contribute.md # This file
├── examples/ # Configuration examples
└── ...
Pull Request Process¶
Before Submitting¶
- Ensure Tests Pass:
make test - Check Code Quality:
make format && make validate - Update Documentation: If you added features
- Add Changelog Entry: Update relevant sections
- Test Locally: Verify your changes work as expected
Pull Request Guidelines¶
-
Create from Feature Branch:
git push origin feature/your-feature-name -
Write a Clear Title and Description:
Title: Add support for custom quarterly date formats Description: - Adds support for custom quarter formats like %y.Q%q - Includes comprehensive tests for quarter parsing - Updates documentation with examples - Fixes issue #93 -
Reference Issues: Link to relevant issues using keywords:
Fixes #93 Closes #45 Resolves #12 -
Add Screenshots/Examples if relevant
Review Process¶
- Automated Checks: CI/CD will run tests automatically
- Code Review: Maintainers will review your code
- Address Feedback: Make requested changes
- Merge: Once approved, your PR will be merged
Issue Reporting¶
Bug Reports¶
When reporting bugs, include:
## Bug Description
Brief description of the issue
## Steps to Reproduce
1. Step 1
2. Step 2
3. Step 3
## Expected Behavior
What should have happened
## Actual Behavior
What actually happened
## Environment
- OS:
- Python Version:
- BumpCalver Version:
- Configuration: (paste your pyproject.toml section)
## Additional Context
Any other relevant information
Feature Requests¶
For feature requests, include:
## Feature Description
Clear description of the proposed feature
## Use Case
Why is this feature needed?
## Proposed Implementation
How might this be implemented?
## Examples
Show what the feature would look like in practice
## Additional Context
Any other relevant information
Development Environment Details¶
Makefile Targets¶
The project includes a comprehensive Makefile:
# Development workflow
make all # Complete workflow: install, format, test, build
make dev-setup # Set up development environment
# Code quality
make format # Run all formatters
make validate # Validate code style
make clean # Clean up generated files
# Testing
make test # Full test suite
make quick-test # Fast tests only
make test-coverage # Tests with coverage report
# Building
make build # Build the package
make bump # Bump version using bumpcalver
# Documentation
make create-docs # Build and deploy docs
make serve-docs # Serve docs locally
make list-docs # List doc versions
Directory Structure¶
bumpcalver/
├── .bumpcalver/ # BumpCalver data
│ └── backups/ # Version backup files
├── _venv/ # Virtual environment
├── docs/ # Documentation source
├── examples/ # Example configurations
├── htmlcov/ # Coverage reports
├── scripts/ # Utility scripts
├── src/ # Source code
│ └── bumpcalver/ # Main package
├── tests/ # Test suite
├── bumpcalver-history.json # Version history
├── makefile # Build automation
├── pyproject.toml # Project configuration
└── requirements.txt # Dependencies
Git Workflow¶
# Stay updated with upstream
git fetch upstream
git checkout dev
git merge upstream/dev
# Create feature branch
git checkout -b feature/amazing-feature
# Make changes, commit often
git add .
git commit -m "Add amazing feature"
# Push and create PR
git push origin feature/amazing-feature
Getting Help¶
- GitHub Issues: Create an issue
- Discussions: GitHub Discussions
- Documentation: Official Docs
Recognition¶
Contributors are recognized in: - CHANGELOG.md: All contributions are acknowledged - GitHub Contributors: Automatic recognition - Release Notes: Major contributions are highlighted
Thank you for contributing to BumpCalver! Your efforts help make calendar versioning better for everyone. 🚀
About
About¶
BumpCalver Library is a library to help manage "calendar version" (CalVer) strings. You can update the version string in TOML, YAML, XML, JSON, Makefile, Dockerfile, and Python files. It follows PEP440 for Python packages, but is not intended to only be for Python packages. It supports git tags like beta, release, release-candidate, and custom tags of your own choosing. It has support for Timezones and build counts. It is a simple library that can be used in any project that needs to manage versioning.
The library is written in Python and is available on PyPi. It is open source and available on GitHub. Feel free to use it in your projects and contribute to the library.
About Me¶
I am a software engineering manager with an eclectic background in various industries (finance, manufacturing, and metrology). I am passionate about software development and love to learn new things.
Contributing¶
Please feel to contribute to this project. Adding common functions is the intent and if you have one to add or improve an existing it is greatly appreciated.
Ways to Contribute!¶
- Add or improve a function
- Add or improve documentation
- Add or improve Tests
- Report or fix a bug
Changelog¶
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog
Latest Changes¶
Refactoring, Improvements, and AI (v2026.7.25.1)¶
What's Changed¶
- Hybrid Versioning and Code Cleanup (#154) @devsetgo
- pip(deps): bump pre-commit from 4.5.1 to 4.6.0 (#145) @dependabot[bot]
- pip(deps): bump mkdocstrings from 1.0.3 to 1.0.4 (#146) @dependabot[bot]
- github actions(deps): bump SonarSource/sonarqube-scan-action from 8.1.0 to 8.2.0 (#147) @dependabot[bot]
- github actions(deps): bump actions/checkout from 6 to 7 (#148) @dependabot[bot]
- pip(deps): bump pylint from 4.0.5 to 4.0.6 (#150) @dependabot[bot]
- pip(deps): bump hatchling from 1.29.0 to 1.30.1 (#149) @dependabot[bot]
- pip(deps): bump black from 26.3.1 to 26.5.1 (#151) @dependabot[bot]
- github actions(deps): bump release-drafter/release-drafter from 7.3.1 to 7.5.1 (#152) @dependabot[bot]
- github actions(deps): bump SonarSource/sonarqube-scan-action from 8.0.0 to 8.1.0 (#140) @dependabot[bot]
- github actions(deps): bump actions/configure-pages from 5 to 6 (#141) @dependabot[bot]
- github actions(deps): bump release-drafter/release-drafter from 7.2.1 to 7.3.1 (#142) @dependabot[bot]
- github actions(deps): bump actions/deploy-pages from 4 to 5 (#143) @dependabot[bot]
- pip(deps): bump ruff from 0.15.12 to 0.15.15 (#144) @dependabot[bot]
New¶
- Add --json output mode and consolidate dev tooling onto ruff (#161) @devsetgo
- Migrate YamlVersionHandler to ruamel.yaml and add plugin support for file-type handlers (#160) @devsetgo
- Add generic file handlers, --dry-run, --config-file; fix build-count bug (#159) @devsetgo
- Add mypy gate, property-based tests, and fix zero-config build-count bug (#158) @devsetgo
Bug Fixes¶
- Add AI-assistant integration docs and fix config and code smell issues (#162) @devsetgo
- Add generic file handlers, --dry-run, --config-file; fix build-count bug (#159) @devsetgo
- Add mypy gate, property-based tests, and fix zero-config build-count bug (#158) @devsetgo
- Fix data loss in YAML/TOML/XML and refactor CLI handler code (#156) @devsetgo
Maintenance¶
- Bump version to 2026.7.25.1 (#164) @devsetgo
- Clean up orphaned files, stale config, and unused dependencies (#163) @devsetgo
- Add --json output mode and consolidate dev tooling onto ruff (#161) @devsetgo
- Migrate YamlVersionHandler to ruamel.yaml and add plugin support for file-type handlers (#160) @devsetgo
- Fix data loss in YAML/TOML/XML and refactor CLI handler code (#156) @devsetgo
- Enhance pull request workflow (#155) @devsetgo
Documentation¶
- Add AI-assistant integration docs and fix config and code smell issues (#162) @devsetgo
- Regenerate API docs and add CLI reference with drift test (#157) @devsetgo
Dependency Updates¶
- Clean up orphaned files, stale config, and unused dependencies (#163) @devsetgo
Published Date: 2026 July 25, 21:37
Hybrid Versioning and Code Cleanup (v2026.05.24.001)¶
What's Changed¶
- Cleanup and Improvements (#139) @devsetgo
- 133 documentation is not deploying to GitHub pages (#138) @devsetgo
- 134 potential bug in beta format (#137) @devsetgo
- 135 feature request support hybrid semantic calendar versioning formats (#136) @devsetgo
- github actions(deps): bump release-drafter/release-drafter from 6.2.0 to 7.2.1 (#126) @dependabot[bot]
- github actions(deps): bump SonarSource/sonarqube-scan-action from 6.0.0 to 8.0.0 (#127) @dependabot[bot]
- pip(deps): bump packaging from 26.0 to 26.2 (#128) @dependabot[bot]
- pip(deps): bump build from 1.4.2 to 1.4.4 (#129) @dependabot[bot]
- pip(deps): bump wheel from 0.46.3 to 0.47.0 (#130) @dependabot[bot]
- pip(deps): bump mike from 2.1.4 to 2.2.0 (#131) @dependabot[bot]
- pip(deps): bump ruff from 0.15.9 to 0.15.12 (#132) @dependabot[bot]
- Next Work (#119) @devsetgo
Published Date: 2026 May 24, 19:17
Bug fix on Increment (v2026.3.8.1)¶
What's Changed¶
- bump of version (#118) @devsetgo
- Fix of issue (#117) @devsetgo
- pip(deps): bump ruff from 0.15.0 to 0.15.4 (#114) @dependabot[bot]
- pip(deps): bump mkdocs-material from 9.7.1 to 9.7.3 (#115) @dependabot[bot]
- github actions(deps): bump release-drafter/release-drafter from 6.1.0 to 6.2.0 (#107) @dependabot[bot]
- Dependency Update - Data Format fix (#113) @devsetgo
- pip(deps): bump wheel from 0.45.1 to 0.46.3 (#109) @dependabot[bot]
- pip(deps): bump packaging from 25.0 to 26.0 (#111) @dependabot[bot]
- pip(deps): bump ruff from 0.14.10 to 0.14.14 (#112) @dependabot[bot]
- Dependencies Update (#106) @devsetgo
Published Date: 2026 March 08, 18:28
Adding --Version to the CLI (v2025.12.30.1)¶
What's Changed¶
- Adding --version to CLI (#100) @devsetgo
- pip(deps): bump mkdocs-material from 9.6.23 to 9.7.0 (#95) @dependabot[bot]
- pip(deps): bump genbadge[all] from 1.1.2 to 1.1.3 (#96) @dependabot[bot]
- pip(deps): bump ruff from 0.14.4 to 0.14.7 (#97) @dependabot[bot]
- pip(deps): bump black from 25.9.0 to 25.11.0 (#98) @dependabot[bot]
- github actions(deps): bump actions/checkout from 5 to 6 (#99) @dependabot[bot]
Published Date: 2025 December 30, 22:13
Improved Date Formatting Functionality (v2025-11-14-001)¶
What's Changed¶
- 93 using quarter in date formatting not updating (#94) @devsetgo
- update of requirements versions (#92) @devsetgo
Published Date: 2025 November 14, 21:31
Undo functionality and History (v2025.10.11.2)¶
What's Changed¶
- 67 undue command (#86) @devsetgo
- pip(deps): bump pytest from 8.4.1 to 8.4.2 (#80) @dependabot[bot]
- pip(deps): bump pytest-mock from 3.14.1 to 3.15.1 (#79) @dependabot[bot]
- pip(deps): bump tox from 4.29.0 to 4.30.2 (#81) @dependabot[bot]
- pip(deps): bump mkdocstrings[python,shell] from 0.30.0 to 0.30.1 (#82) @dependabot[bot]
- pip(deps): bump pytest-cov from 6.2.1 to 7.0.0 (#83) @dependabot[bot]
- github actions(deps): bump SonarSource/sonarqube-scan-action from 5.3.1 to 6.0.0 (#84) @dependabot[bot]
- github actions(deps): bump actions/setup-python from 5 to 6 (#85) @dependabot[bot]
- Improving Makefile (#78) @devsetgo
- github actions(deps): bump actions/checkout from 4 to 5 (#72) @dependabot[bot]
- pip(deps): bump ruff from 0.12.7 to 0.12.11 (#73) @dependabot[bot]
- pip(deps): bump build from 1.2.2.post1 to 1.3.0 (#74) @dependabot[bot]
- pip(deps): bump mkdocs-print-site-plugin from 2.7.3 to 2.8 (#75) @dependabot[bot]
- pip(deps): bump pre-commit from 4.2.0 to 4.3.0 (#76) @dependabot[bot]
- pip(deps): bump tox from 4.28.4 to 4.29.0 (#77) @dependabot[bot]
Published Date: 2025 October 11, 22:23
Error Message Improvements (2025.8.31.3)¶
What's Changed¶
- bump of version (#71) @devsetgo
- Improving Error Messages (#70) @devsetgo
- Fixing Tests Updating Existing Documents (#69) @devsetgo
Published Date: 2025 August 31, 14:35
Fix of release (v2025.8.2.3)¶
What's Changed¶
- Verion bump to 2025.8.2.3 (#66) @devsetgo
- Test Cleanup (#65) @devsetgo
- Fix of Publishing CICD (#64) @devsetgo
Published Date: 2025 August 02, 20:00
New File Handlers .ENV, setup.cfg, & sonar-project. Properties (v2025.8.2.1)¶
What's Changed¶
- CICD fix and new Handlers (#63) @devsetgo
- pip(deps): bump tox from 4.27.0 to 4.28.4 (#59) @dependabot[bot]
- pip(deps): bump mkdocstrings[python,shell] from 0.29.1 to 0.30.0 (#60) @dependabot[bot]
- pip(deps): bump mkdocs-material from 9.6.15 to 9.6.16 (#61) @dependabot[bot]
- pip(deps): bump ruff from 0.12.2 to 0.12.7 (#62) @dependabot[bot]
- update of requirements (#58) @devsetgo
- pip(deps): bump ruff from 0.11.11 to 0.11.12 (#52) @dependabot[bot]
- Updating Requirements (#51) @devsetgo
Published Date: 2025 August 02, 19:14
Improved documentation and update of dependencies (v2025.4.12.1)¶
What's Changed¶
- Improving Documentation (#47) @devsetgo
- pip(deps): bump pytest from 8.3.4 to 8.3.5 (#42) @dependabot[bot]
- pip(deps): bump mkdocs-print-site-plugin from 2.6.0 to 2.7.2 (#44) @dependabot[bot]
- pip(deps): bump pylint from 3.3.4 to 3.3.6 (#43) @dependabot[bot]
- pip(deps): bump mkdocs-material from 9.6.6 to 9.6.11 (#45) @dependabot[bot]
- pip(deps): bump genbadge[all] from 1.1.1 to 1.1.2 (#46) @dependabot[bot]
- pip(deps): bump mkdocstrings[python,shell] from 0.27.0 to 0.28.2 (#37) @dependabot[bot]
- pip(deps): bump twine from 6.0.1 to 6.1.0 (#38) @dependabot[bot]
- pip(deps): bump pylint from 3.3.3 to 3.3.4 (#39) @dependabot[bot]
- pip(deps): bump mkdocs-material from 9.5.49 to 9.6.6 (#40) @dependabot[bot]
- pip(deps): bump ruff from 0.9.4 to 0.9.9 (#41) @dependabot[bot]
- run of tests (#36) @devsetgo
- pip(deps): bump black from 24.10.0 to 25.1.0 (#31) @dependabot[bot]
- pip(deps): bump ruff from 0.8.4 to 0.9.4 (#32) @dependabot[bot]
- pip(deps): bump tox from 4.23.2 to 4.24.1 (#33) @dependabot[bot]
- pip(deps): bump pre-commit from 4.0.1 to 4.1.0 (#34) @dependabot[bot]
- pip(deps): bump autopep8 from 2.3.1 to 2.3.2 (#35) @dependabot[bot]
- pip(deps): bump ruff from 0.8.2 to 0.8.4 (#26) @dependabot[bot]
- pip(deps): bump hatchling from 1.26.3 to 1.27.0 (#27) @dependabot[bot]
- pip(deps): bump mkdocs-material from 9.5.47 to 9.5.49 (#28) @dependabot[bot]
- pip(deps): bump pylint from 3.3.2 to 3.3.3 (#29) @dependabot[bot]
- pip(deps): bump click from 8.1.7 to 8.1.8 (#30) @dependabot[bot]
Published Date: 2025 April 12, 16:34
Fix of Python Version (2024.12.14.1)¶
What's Changed¶
- bump version (#25) @devsetgo
- working on trusted publishing (#24) @devsetgo
- Bump of Version 24.12.06-001 (#23) @devsetgo
- Enhancing Date Formatting Capability (#22) @devsetgo
- Adding BumpCalver.toml option (#16) @devsetgo
- pip(deps): bump ruff from 0.7.1 to 0.7.2 (#15) @dependabot
- pip(deps): bump mkdocs-material from 9.5.40 to 9.5.43 (#11) @dependabot
- pip(deps): bump ruff from 0.6.9 to 0.7.1 (#12) @dependabot
- pip(deps): bump tox from 4.21.2 to 4.23.2 (#13) @dependabot
- pip(deps): bump pytest-cov from 5.0.0 to 6.0.0 (#14) @dependabot
Published Date: 2024 December 14, 20:10
Enhancing Date Formatting Capabilities (24.12.06-001-x)¶
What's Changed¶
- working on trusted publishing (#24) @devsetgo
Published Date: 2024 December 14, 20:03
Enhancing Date Formatting Capabilites (24.12.06-001)¶
What's Changed¶
- Changing version to xx.xx.xx-build.
- Bump of Version 24.12.06-001 (#23) @devsetgo
- Enhancing Date Formatting Capability (#22) @devsetgo
Published Date: 2024 December 06, 23:11
BumpCalver.toml Option (2024-11-08)¶
What's Changed¶
- Adding BumpCalver.toml option (#16) @devsetgo
- pip(deps): bump ruff from 0.7.1 to 0.7.2 (#15) @dependabot
- pip(deps): bump mkdocs-material from 9.5.40 to 9.5.43 (#11) @dependabot
- pip(deps): bump ruff from 0.6.9 to 0.7.1 (#12) @dependabot
- pip(deps): bump tox from 4.21.2 to 4.23.2 (#13) @dependabot
- pip(deps): bump pytest-cov from 5.0.0 to 6.0.0 (#14) @dependabot
Published Date: 2024 November 08, 21:41
Fix of OS classifiers (2024.10.20.4)¶
What's Changed¶
- Fixing Classifier Gaps (#10) @devsetgo
Published Date: 2024 October 20, 16:14
Fix of classifiers (2024.10.20.3)¶
What's Changed¶
- Updating classifiers (#9) @devsetgo
Published Date: 2024 October 20, 16:00
Adding Python 3.9 Support (2024.10.20)¶
What's Changed¶
- Fix to support Python 3.9 and higher (#8) @devsetgo
- Release Ready (#7) @devsetgo
Published Date: 2024 October 20, 15:35
Initial Release (2024.10.18)¶
What's Changed¶
- Initial Work by @devsetgo in https://github.com/devsetgo/bumpcalver/pull/1
- Pre-Release Work by @devsetgo in https://github.com/devsetgo/bumpcalver/pull/4
Full Changelog: https://github.com/devsetgo/bumpcalver/commits/2024.10.18
Published Date: 2024 October 18, 18:42