Dynamic version generation from version control system tags supporting multiple VCS and versioning standards.
—
Command-line tool for version generation and validation that works with any programming language project.
The CLI is available after installing the dunamai package:
pip install dunamaiThe dunamai command becomes available system-wide via the entry point in pyproject.toml.
Generate version strings from version control system information.
# Auto-detect VCS and generate version
dunamai from any
# Use specific VCS
dunamai from git
dunamai from mercurial
dunamai from darcs
dunamai from subversion
dunamai from bazaar
dunamai from fossil
dunamai from pijulExample Outputs:
$ dunamai from any
1.2.3.post7.dev0+g29045e8
$ dunamai from git
1.2.3.post7.dev0+g29045e8Validate version strings against versioning standards.
# Validate against PEP 440 (default)
dunamai check "1.2.3"
# Validate against Semantic Versioning
dunamai check "1.2.3-alpha.1" --style semver
# Validate against Haskell PVP
dunamai check "1.2.3-test" --style pvpExample Outputs:
$ dunamai check "1.2.3"
# No output means valid
$ dunamai check "v1.2.3" --style pep440
Version 'v1.2.3' does not conform to the PEP 440 styleOptions available for all commands:
dunamai --help # Show help
dunamai --version # Show dunamai versionCommon options for dunamai from <vcs> commands:
# Metadata control
dunamai from any --metadata # Always include metadata
dunamai from any --no-metadata # Never include metadata
# Dirty state
dunamai from any --dirty # Include dirty flag
# Git-specific: ignore untracked files
dunamai from git --ignore-untracked
# Tagged metadata
dunamai from any --tagged-metadata
# Custom tag pattern
dunamai from any --pattern "custom-(?P<base>\d+\.\d+\.\d+)"
# Tag selection
dunamai from any --latest-tag # Use latest tag by dateControl the output format and style:
# Built-in styles
dunamai from any --style pep440 # PEP 440 (default)
dunamai from any --style semver # Semantic Versioning
dunamai from any --style pvp # Haskell PVP
# Custom format strings
dunamai from any --format "v{base}+{distance}.{commit}"
dunamai from any --format "{base}-{branch}"
dunamai from any --format "{major}.{minor}.{patch}.{distance}"Automatically increment version components:
# Bump version for next release
dunamai from any --bump
# Combined with custom format
dunamai from any --bump --format "v{base}"# Get clean version for releases
VERSION=$(dunamai from any --style semver --no-metadata)
echo "Release version: $VERSION"
# Get development version with commit info
DEV_VERSION=$(dunamai from git --dirty)
echo "Development version: $DEV_VERSION"
# Docker tag-friendly format
DOCKER_TAG=$(dunamai from any --format "{base}-{commit}")
docker build -t myapp:$DOCKER_TAG .# Generate version for any project type
cd /path/to/cpp-project
dunamai from any --format "{major}.{minor}.{patch}"
cd /path/to/nodejs-project
dunamai from any --style semver
cd /path/to/python-project
dunamai from any --style pep440# Include branch in development builds
dunamai from git --format "{base}-{branch_escaped}+{commit}"
# Main branch vs feature branch handling
if [[ $(git branch --show-current) == "main" ]]; then
VERSION=$(dunamai from git --style semver)
else
VERSION=$(dunamai from git --format "{base}-dev.{distance}+{commit}")
fi# For tags like "release-1.2.3"
dunamai from git --pattern "^release-(?P<base>\d+\.\d+\.\d+)$"
# For tags like "v1.2.3-rc1"
dunamai from any --pattern "^v(?P<base>\d+\.\d+\.\d+)(-(?P<stage>\w+)(?P<revision>\d+))?$"
# For Subversion with custom tag directory
dunamai from subversion --tag-dir "releases"# Validate current version
CURRENT_VERSION=$(dunamai from any)
dunamai check "$CURRENT_VERSION" --style pep440
# Validate custom version strings
dunamai check "1.2.3-rc.1" --style semver || echo "Invalid SemVer"
dunamai check "2!1.2.3.post1" --style pep440 || echo "Invalid PEP 440"# Extract version components
VERSION=$(dunamai from any --format "{base}")
MAJOR=$(dunamai from any --format "{major}")
MINOR=$(dunamai from any --format "{minor}")
PATCH=$(dunamai from any --format "{patch}")
echo "Version: $VERSION (Major: $MAJOR, Minor: $MINOR, Patch: $PATCH)"
# Generate multiple formats
PEP440=$(dunamai from any --style pep440)
SEMVER=$(dunamai from any --style semver)
PVP=$(dunamai from any --style pvp)
echo "PEP 440: $PEP440"
echo "SemVer: $SEMVER"
echo "PVP: $PVP"The CLI provides meaningful error messages and exit codes:
# Exit code 0 for success
dunamai from git && echo "Success"
# Non-zero exit code for errors
dunamai from git --strict || echo "No tags found"
# Validation errors
dunamai check "invalid-version" || echo "Validation failed"VERSION := $(shell dunamai from any --style semver)
DEV_VERSION := $(shell dunamai from any --bump --format "{base}-dev.{distance}")
version:
@echo "Current version: $(VERSION)"
dev-version:
@echo "Development version: $(DEV_VERSION)"
build:
go build -ldflags "-X main.version=$(VERSION)" .- name: Get version
id: version
run: |
VERSION=$(dunamai from git --style semver)
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Build with version
run: |
echo "Building version ${{ steps.version.outputs.version }}"
# Build commands hereARG VERSION
LABEL version=${VERSION}
RUN echo "Building version ${VERSION}"# Build with dynamic version
VERSION=$(dunamai from any --format "{base}")
docker build --build-arg VERSION=$VERSION .# Specify repository path
dunamai from any --path /path/to/repo
# Work with multiple repositories
for repo in repo1 repo2 repo3; do
VERSION=$(dunamai from any --path $repo)
echo "$repo: $VERSION"
done# Test custom patterns
dunamai from any --pattern "(?P<base>\d+\.\d+\.\d+)" --debug
# Validate pattern against existing tags
git tag -l | while read tag; do
echo "Testing tag: $tag"
dunamai from git --pattern "your-pattern" || echo "Pattern doesn't match $tag"
doneThe CLI tool provides a complete interface for version management in any software project, supporting all the same capabilities as the Python API with convenient command-line syntax.
Install with Tessl CLI
npx tessl i tessl/pypi-dunamai