| title | Environment Version Source |
| description | Retrieve project versions from environment variables for CI/CD integration. Covers configuration, CI/CD workflows (GitHub, GitLab, Jenkins), Docker/Kubernetes integration, and best practices for external version management. |
Environment Version Source
The environment version source plugin retrieves project versions from environment variables. This approach is particularly useful for CI/CD pipelines, containerized deployments, and build systems where versions are determined externally.
Basic Configuration
Configure the env source in your pyproject.toml:
[project]
name = "my-package"
dynamic = ["version"]
[tool.hatch.version]
source = "env"
variable = "MY_PROJECT_VERSION"
Configuration Options
Required Options
| Option | Type | Description |
|---|
variable | string | Name of the environment variable containing the version |
Optional Options
| Option | Type | Default | Description |
|---|
default | string | None | Default version if variable is not set |
Usage Patterns
Simple Environment Variable
Basic usage with a single environment variable:
[tool.hatch.version]
source = "env"
variable = "VERSION"
export VERSION="1.2.3"
hatch build
With Default Value
Provide a fallback when the variable isn't set:
[tool.hatch.version]
source = "env"
variable = "PACKAGE_VERSION"
default = "0.0.0+dev"
CI/CD Specific Variables
Use CI/CD system variables directly:
[tool.hatch.version]
source = "env"
variable = "GITHUB_REF_NAME"
[tool.hatch.version]
source = "env"
variable = "CI_COMMIT_TAG"
[tool.hatch.version]
source = "env"
variable = "BUILD_VERSION"
CI/CD Integration Examples
GitHub Actions
name: Release
on:
push:
tags:
- "v*"
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set version from tag
run: |
# Remove 'v' prefix from tag
echo "PACKAGE_VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
- name: Build package
run: |
pip install hatch
hatch build
- name: Publish to PyPI
run: |
hatch publish
[tool.hatch.version]
source = "env"
variable = "PACKAGE_VERSION"
default = "0.0.0+dev"
GitLab CI
stages:
- build
- deploy
variables:
PROJECT_VERSION: ${CI_COMMIT_TAG}
build:
stage: build
script:
- pip install hatch
- hatch build
only:
- tags
deploy:
stage: deploy
script:
- hatch publish
only:
- tags
[tool.hatch.version]
source = "env"
variable = "PROJECT_VERSION"
Jenkins
// Jenkinsfile
pipeline {
agent any
environment {
BUILD_VERSION = "${env.TAG_NAME ?: '0.0.0+ci.' + env.BUILD_NUMBER}"
}
stages {
stage('Build') {
steps {
sh '''
pip install hatch
hatch build
'''
}
}
stage('Publish') {
when {
tag pattern: "v\\d+\\.\\d+\\.\\d+", comparator: "REGEXP"
}
steps {
sh 'hatch publish'
}
}
}
}
[tool.hatch.version]
source = "env"
variable = "BUILD_VERSION"
Docker Integration
Dockerfile with Build Args
# Dockerfile
FROM python:3.11-slim
# Accept version as build argument
ARG VERSION=0.0.0+docker
ENV PACKAGE_VERSION=$VERSION
WORKDIR /app
COPY . .
# Install and build
RUN pip install hatch && \
hatch build && \
pip install dist/*.whl
CMD ["python", "-m", "my_package"]
docker build --build-arg VERSION=1.2.3 -t my-app:1.2.3 .
Docker Compose
version: "3.8"
services:
app:
build:
context: .
args:
VERSION: ${VERSION:-0.0.0+dev}
environment:
- PACKAGE_VERSION=${VERSION:-0.0.0+dev}
VERSION=1.2.3 docker-compose up
Development Workflows
Local Development
Set up development environment with custom version:
export PACKAGE_VERSION="0.0.0+dev.$(git rev-parse --short HEAD)"
source .env.local
hatch run python -c "import my_package; print(my_package.__version__)"
Multiple Environments
Use different variables for different environments:
[tool.hatch.version]
source = "env"
variable = "VERSION"
default = "0.0.0+unknown"
VERSION="0.0.0+dev" hatch build
VERSION="1.2.3-rc1" hatch build
VERSION="1.2.3" hatch build
Version Formatting
Cleaning Version Strings
Sometimes environment variables need processing:
[tool.hatch.version]
source = "env"
variable = "GIT_TAG"
Use a wrapper script to clean:
#!/bin/bash
export CLEAN_VERSION="${GIT_TAG#v}"
export PACKAGE_VERSION="$CLEAN_VERSION"
hatch build
Version Validation
The env source validates versions against PEP 440:
export VERSION="1.2.3"
export VERSION="1.0.0a1"
export VERSION="2023.12.1"
export VERSION="1.0.0+build.123"
export VERSION="v1.2.3"
export VERSION="1.2"
export VERSION="latest"
Automation Examples
Automatic Versioning Script
#!/bin/bash
if git describe --exact-match --tags HEAD 2>/dev/null; then
VERSION=$(git describe --exact-match --tags HEAD | sed 's/^v//')
elif [ -n "$CI_COMMIT_SHA" ]; then
VERSION="0.0.0+ci.$(echo $CI_COMMIT_SHA | cut -c1-8)"
else
VERSION="0.0.0+dev.$(git rev-parse --short HEAD)"
fi
export PACKAGE_VERSION="$VERSION"
echo "Building version: $VERSION"
hatch build
Pre-commit Hook
Ensure version is set before commits:
repos:
- repo: local
hooks:
- id: check-version-env
name: Check VERSION environment variable
entry: sh -c 'test -n "$VERSION" || (echo "VERSION not set" && exit 1)'
language: system
pass_filenames: false
Multi-Version Builds
Build multiple versions in CI:
name: Multi-Version Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
version: ["1.0.0", "1.1.0", "2.0.0-beta"]
steps:
- uses: actions/checkout@v3
- name: Build version ${{ matrix.version }}
env:
PACKAGE_VERSION: ${{ matrix.version }}
run: |
pip install hatch
hatch build
mkdir -p artifacts/${{ matrix.version }}
mv dist/* artifacts/${{ matrix.version }}/
- uses: actions/upload-artifact@v3
with:
name: packages
path: artifacts/
Kubernetes Integration
ConfigMap Version
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
VERSION: "1.2.3"
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
envFrom:
- configMapRef:
name: app-config
Helm Chart
version: "1.2.3"
apiVersion: apps/v1
kind: Deployment
metadata:
name: { { .Release.Name } }
spec:
template:
spec:
containers:
- name: app
env:
- name: PACKAGE_VERSION
value: { { .Values.version | quote } }
Limitations
Read-Only Source
The env source doesn't support setting versions:
$ hatch version patch
Error: The environment version source does not support setting the version
Workaround: Update the environment variable externally:
export VERSION="1.2.4"
hatch version
No Version Bumping
Unlike file-based sources, env source can't bump versions:
$ hatch version minor
Error: Cannot bump version with environment source
Solution: Implement version bumping in your CI/CD:
#!/bin/bash
current_version="${VERSION:-0.0.0}"
IFS='.' read -ra parts <<< "$current_version"
parts[2]=$((parts[2] + 1))
new_version="${parts[0]}.${parts[1]}.${parts[2]}"
export VERSION="$new_version"
Best Practices
1. Always Provide Default Values
Prevent build failures by configuring sensible defaults:
[tool.hatch.version]
source = "env"
variable = "VERSION"
default = "0.0.0+unknown"
2. Document Required Variable Names
Clearly specify which environment variables are needed:
[tool.hatch.version]
source = "env"
variable = "PACKAGE_VERSION"
default = "0.0.0+dev"
3. Implement CI Validation
Add CI/CD checks to ensure version format compliance:
- name: Validate version
run: |
python -c "
import os
from packaging.version import Version, InvalidVersion
try:
v = Version(os.environ['VERSION'])
print(f'Valid version: {v}')
except InvalidVersion:
print(f'Invalid version: {os.environ.get('VERSION', 'not set')}')
exit(1)
"
4. Use Descriptive and Project-Specific Variable Names
Choose clear names that identify the project:
variable = "MY_PACKAGE_VERSION"
variable = "WIDGET_LIB_VERSION"
variable = "VERSION"
variable = "V"
Troubleshooting
Variable Not Set
$ hatch version
Error: Environment variable 'VERSION' is not set
Solutions:
- Set the variable:
export VERSION="1.2.3"
- Add a default:
default = "0.0.0+dev"
- Check variable name spelling
Invalid Version Format
$ export VERSION="v1.2.3"
$ hatch version
Error: Invalid version 'v1.2.3'
Fix: Remove invalid characters:
export VERSION="1.2.3"
Variable Not Updating
$ VERSION=1.2.3
$ hatch version
Error: Environment variable 'VERSION' is not set
Fix: Export the variable:
export VERSION=1.2.3
Integration with Other Tools
Poetry Migration
[tool.poetry-dynamic-versioning]
enable = true
[tool.hatch.version]
source = "env"
variable = "VERSION"
Setuptools-scm Migration
[tool.setuptools_scm]
write_to = "src/_version.py"
[tool.hatch.version]
source = "env"
variable = "SETUPTOOLS_SCM_PRETEND_VERSION"
See Also