# Version Management Guide MarkiTect uses **setuptools-scm** for automatic version management based on git tags. This eliminates manual version bumping and ensures versions are always in sync with git history. ## How It Works ### Version Calculation setuptools-scm automatically determines the version based on: 1. **Git Tags**: The latest tag matching `v*` pattern (e.g., `v0.7.0`) 2. **Commits Since Tag**: Number of commits since the latest tag 3. **Current Commit**: Short commit hash 4. **Dirty State**: Whether there are uncommitted changes ### Version Examples | Git State | Version Output | |-----------|----------------| | `v0.7.0` tag (clean) | `0.7.0` | | `v0.7.0` + 3 commits | `0.7.1.dev3+g1a2b3c4d` | | `v0.7.0` + 3 commits + dirty | `0.7.1.dev3+g1a2b3c4d.d20251108` | | No tags + 10 commits | `0.1.dev10+g5e6f7g8h` | ## Version Commands ### Check Current Version ```bash # Quick version check python -m setuptools_scm # Detailed version information make release-status python release.py status ``` ### Access Version in Code ```python from markitect.__version__ import __version__ print(f"MarkiTect version: {__version__}") ``` ## Creating Releases ### Release Workflow 1. **Ensure Clean State**: ```bash git status # Should be clean git pull # Latest changes ``` 2. **Validate Release Readiness**: ```bash make release-validate ``` 3. **Create Release**: ```bash # Standard release make release-publish VERSION=0.8.0 # Release with Gitea publishing make release-publish-gitea VERSION=0.8.0 ``` ### Version Naming Conventions Follow [Semantic Versioning](https://semver.org/): - **Major Version** (`1.0.0`): Breaking changes - **Minor Version** (`0.8.0`): New features (backward compatible) - **Patch Version** (`0.7.1`): Bug fixes (backward compatible) - **Pre-release** (`0.8.0-rc1`): Release candidates - **Development** (`0.8.1.dev3+hash`): Automatic between releases ### Git Tag Format Always use the format `vX.Y.Z`: ```bash # Correct git tag v0.8.0 git tag v1.0.0-rc1 # Incorrect git tag 0.8.0 # Missing 'v' prefix git tag version-0.8.0 # Wrong format ``` ## Development Versions ### Understanding Development Versions Between releases, setuptools-scm generates development versions: ``` 0.7.1.dev3+g1a2b3c4d.d20251108 │ │ │ │ │ │ │ │ │ │ │ └── Date (dirty state) │ │ │ │ └─────────── Commit hash │ │ │ └───────────── Commits since tag │ │ └──────────────── Dev marker │ └─────────────────── Next version └─────────────────────── Base version ``` ### Working with Development Versions Development versions are automatically: - **Sorted correctly** by pip (dev versions < release versions) - **Excluded from releases** (only tagged versions are released) - **Unique** (each commit has a different version) ## Configuration ### setuptools-scm Configuration Configuration in `pyproject.toml`: ```toml [tool.setuptools_scm] write_to = "markitect/_version.py" ``` ### Version File Generation setuptools-scm automatically generates `markitect/_version.py`: ```python # Auto-generated - do not edit __version__ = "0.7.1.dev3+g1a2b3c4d" __version_tuple__ = (0, 7, 1, 'dev3', 'g1a2b3c4d') ``` This file is: - ✅ **Auto-generated** during package builds - ✅ **Added to .gitignore** (never committed) - ✅ **Available at runtime** for version checks ## Release Branches ### Main Branch Strategy MarkiTect uses a simple branching strategy: - **`main`**: Primary development branch - **Tags**: Mark release points (`v0.7.0`, `v0.8.0`) - **Feature branches**: Merged via pull requests ### Release Process 1. **Development** happens on `main` 2. **Release tags** created on `main` when ready 3. **Hotfix tags** can be created on older commits if needed ```bash # Standard release from main git checkout main git pull make release-publish-gitea VERSION=0.8.0 # Hotfix release from older commit git checkout v0.7.0 git cherry-pick git tag v0.7.1 git push origin v0.7.1 ``` ## Package Building ### Build Commands ```bash # Build packages with version info make package # Build using release script make release-build python release.py build # Manual build python -m build ``` ### Build Output Packages are built to `dist/` directory: - **Wheel** (`.whl`): Binary distribution - **Source Distribution** (`.tar.gz`): Source code ### Version in Package Names setuptools-scm ensures package names include correct versions: ``` dist/ ├── markitect-0.8.0-py3-none-any.whl # Release ├── markitect-0.8.0.tar.gz # Release ├── markitect-0.8.1.dev3+hash-py3-none-any.whl # Development └── markitect-0.8.1.dev3+hash.tar.gz # Development ``` ## Troubleshooting ### Common Issues 1. **"No tags found"**: ```bash # Create initial tag git tag v0.1.0 git push origin v0.1.0 ``` 2. **"Dirty working tree"**: ```bash # Commit or stash changes git add . && git commit -m "Changes" # Or git stash ``` 3. **"Version not updating"**: ```bash # Clear setuptools-scm cache rm -rf build/ *.egg-info/ python -m setuptools_scm ``` 4. **"Import error in __version__.py"**: ```bash # Rebuild package to generate _version.py make package ``` ### Debug Version Issues ```bash # Verbose setuptools-scm output python -m setuptools_scm --debug # Check git state git describe --tags --dirty --always # Verify tag format git tag --list | grep "^v" ``` ## Best Practices ### Do's ✅ - **Always use `vX.Y.Z` tag format** - **Create annotated tags**: `git tag -a v0.8.0 -m "Release 0.8.0"` - **Push tags to origin**: `git push origin v0.8.0` - **Keep clean working tree** for releases - **Follow semantic versioning** - **Test version detection** before releasing ### Don'ts ❌ - **Don't edit `_version.py`** manually (auto-generated) - **Don't commit version numbers** to source files - **Don't use non-standard tag formats** - **Don't create releases from dirty tree** - **Don't delete old tags** (breaks version history) ### Version Strategy 1. **Development**: Let setuptools-scm handle automatically 2. **Pre-releases**: Use `-rc1`, `-alpha1`, `-beta1` suffixes 3. **Releases**: Create tags only for stable releases 4. **Hotfixes**: Tag from appropriate commit, not necessarily `main` ## Integration with CI/CD ### GitHub Actions Example ```yaml name: Release on: push: tags: ['v*'] jobs: release: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 # Important for setuptools-scm - name: Build packages run: make package - name: Upload to Gitea env: GITEA_API_TOKEN: ${{ secrets.GITEA_API_TOKEN }} run: python release.py upload ``` ### Key Points - **`fetch-depth: 0`**: Required for setuptools-scm to access git history - **Environment variables**: Use secrets for API tokens - **Tag-based triggers**: Only build releases for version tags This version management system provides automatic, reliable, and traceable versioning that scales with your development workflow.