# 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 <hotfix-commit>
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.