diff --git a/Makefile b/Makefile index e5b49291..660cc50a 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,7 @@ help: @echo " test-new - Create new test file template" @echo " test-coverage - Analyze test coverage" @echo " build - Build the package" + @echo " package - Build distribution packages (wheel + sdist)" @echo " lint - Run code linting" @echo " format - Format code" @echo "" @@ -485,6 +486,22 @@ build: $(VENV)/bin/activate $(VENV_PYTHON) -m build 2>/dev/null || \ $(VENV_PIP) install build && $(VENV_PYTHON) -m build +# Build distribution packages with version info +package: $(VENV)/bin/activate + @echo "๐Ÿ“ฆ Building distribution packages..." + @echo "" + @echo "๐Ÿ“ Current version (setuptools-scm):" + @$(VENV_PYTHON) -m setuptools_scm 2>/dev/null || echo " setuptools-scm not available" + @echo "" + @echo "๐Ÿงน Cleaning previous builds..." + @rm -rf build/ dist/ *.egg-info/ 2>/dev/null || true + @echo "๐Ÿ—๏ธ Building wheel and source distribution..." + @$(VENV_PIP) install build setuptools-scm >/dev/null 2>&1 || true + $(VENV_PYTHON) -m build --wheel --sdist + @echo "" + @echo "โœ… Packages built successfully:" + @ls -lah dist/ 2>/dev/null || echo " No packages found" + # Release management (setuptools-scm) release-status: @echo "๐Ÿ” Checking release status (setuptools-scm)..." diff --git a/PACKAGE_PUBLISHING.md b/PACKAGE_PUBLISHING.md index ba5f710b..f6163414 100644 --- a/PACKAGE_PUBLISHING.md +++ b/PACKAGE_PUBLISHING.md @@ -1,6 +1,6 @@ -# Package Publishing to Gitea +# Package Publishing Guide -This document explains how to publish MarkiTect packages to the Gitea package registry. +This guide covers building, publishing, and distributing MarkiTect packages using our Gitea package registry and setuptools-scm version management. ## Prerequisites @@ -17,40 +17,110 @@ export GITEA_API_TOKEN="your_gitea_api_token_here" echo "export GITEA_API_TOKEN=your_token" >> ~/.bashrc ``` -## Usage +## Package Building + +### Quick Package Building + +```bash +# Build distribution packages (recommended) +make package + +# This will: +# 1. Show current version (setuptools-scm) +# 2. Clean previous builds +# 3. Build both wheel and source distribution +# 4. Show package details +``` + +### Manual Building + +```bash +# Standard build +make build + +# Using release script +make release-build +python release.py build + +# Manual Python build +python -m build +``` + +## Publishing Workflow + +### Complete Release + Publishing + +```bash +# ๐Ÿš€ ONE-COMMAND RELEASE (recommended) +make release-publish-gitea VERSION=0.8.0 + +# This complete workflow: +# 1. Creates git tag v0.8.0 +# 2. Builds packages (setuptools-scm uses tag for version 0.8.0) +# 3. Uploads both wheel and source distribution to Gitea +``` + +### Step-by-Step Release + +```bash +# 1. Check current status +make release-status + +# 2. Validate release readiness +make release-validate + +# 3. Create git tag +make release-tag VERSION=0.8.0 + +# 4. Build packages (version auto-detected from tag) +make release-build + +# 5. Upload to Gitea registry +make release-upload-gitea +``` + +### Development Package Testing + +```bash +# Build current development version +make package + +# Upload development packages for testing +python release.py upload --dry-run # Test first +python release.py upload # Upload development version +``` + +## Registry Management ### Check Registry Status ```bash -# Check registry configuration and authentication +# Comprehensive registry information make release-registry -# or -python release.py registry + +# Shows: +# - Authentication status +# - Registry URLs +# - Existing packages +# - Configuration details ``` -### Build and Upload Packages +### Upload Existing Packages ```bash -# Complete release workflow with Gitea upload -make release-publish-gitea VERSION=0.8.0 -# or -python release.py publish --version 0.8.0 --to-gitea - -# Upload existing packages +# Upload packages in dist/ folder make release-upload-gitea -# or -python release.py upload -# Dry run (test without uploading) +# With dry-run testing python release.py upload --dry-run +python release.py upload ``` -### Traditional Release (without Gitea) +### Traditional Release (Git tags only) ```bash # Standard release without Gitea upload make release-publish VERSION=0.8.0 -python release.py publish --version 0.8.0 ``` ## Available Commands diff --git a/VERSION_MANAGEMENT.md b/VERSION_MANAGEMENT.md new file mode 100644 index 00000000..4b362725 --- /dev/null +++ b/VERSION_MANAGEMENT.md @@ -0,0 +1,309 @@ +# 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. \ No newline at end of file