# Versioning and Release Workflow

## Overview

This project uses **setuptools-scm** for automatic version management based on git tags and commits. This eliminates manual version patching and simplifies the release workflow.

## How It Works

### Version Generation

setuptools-scm automatically generates versions based on:

1. **Tagged releases**: `v2.0.7` → version `2.0.7`
2. **Commits after tag**: `v2.0.7` + 3 commits → version `2.0.8.dev3+gabc1234`
3. **Dirty working tree**: Appends `.dirty` suffix for uncommitted changes

### Configuration

The version is configured in `pyproject.toml`:

```toml
[build-system]
requires = ["setuptools>=61", "wheel", "setuptools-scm>=8"]
build-backend = "setuptools.build_meta"

[tool.setuptools_scm]
version_scheme = "post-release"
local_scheme = "no-local-version"
write_to = "src/broadie/_version.py"
write_to_template = "__version__ = '{version}'\n"
```

## Release Workflow

### 1. Development Workflow (No Develop Branch)

```bash
# Work on feature branches
git checkout -b feature/my-feature
# ... make changes ...
git commit -m "Add new feature"
git push origin feature/my-feature

# Create PR to main
# Tests run automatically via GitHub Actions
```

### 2. Merging to Main

When a PR is merged to `main`:

1. **Tests run** automatically (test-lint.yml)
2. **If tests pass**, package is built with setuptools-scm
3. **Auto-publishes** to TestPyPI with version like `2.0.8.dev5+gabc1234`

### 3. Creating a Production Release

To publish to production PyPI:

```bash
# On main branch, create and push a version tag
git tag v2.1.0
git push origin v2.1.0

# This will:
# 1. Trigger tests
# 2. Build package with version 2.1.0
# 3. Publish to TestPyPI (for verification)
```

### 4. Manual PyPI Publishing (Optional)

For production PyPI releases, manually publish after verifying TestPyPI:

```bash
# Build the package locally
python -m build

# Publish to PyPI using twine
python -m twine upload dist/*
```

## Version Numbering

setuptools-scm follows PEP 440:

- **Release**: `2.0.7` (from tag `v2.0.7`)
- **Dev release**: `2.0.8.dev3` (3 commits after v2.0.7)
- **Pre-release**: `2.1.0a1` (from tag `v2.1.0-alpha.1`)
- **Release candidate**: `2.1.0rc1` (from tag `v2.1.0-rc.1`)

## GitHub Actions Workflows

### Test and Lint (`test-lint.yml`)

Triggers on:
- Push to `main`
- Pull requests to `main`

Runs tests on Python 3.10, 3.11, 3.12, and 3.13.

### Publish Package (`publish-package.yml`)

Triggers when:
- Test and Lint workflow completes successfully on `main`

Automatically:
1. Checks out code with full git history (`fetch-depth: 0`)
2. Installs setuptools-scm
3. Builds package (version auto-generated)
4. Publishes to TestPyPI with `skip-existing: true`

## Benefits

1. ✅ **No manual version patching** - versions are automatic
2. ✅ **Unique versions per commit** - every build is traceable
3. ✅ **Simplified workflow** - no develop branch needed
4. ✅ **PEP 440 compliant** - standard Python versioning
5. ✅ **Git-based source of truth** - tags control releases

## Testing Locally

Check what version would be generated:

```bash
# Install setuptools-scm
pip install setuptools-scm

# Check version
python -m setuptools_scm

# Build package
python -m build

# Check built package version
ls dist/
```

## Migration Notes

- Removed manual version from `pyproject.toml`
- Added `dynamic = ["version"]` to project metadata
- Removed develop branch from workflows
- All commits to main now auto-publish to TestPyPI
- Production releases require manual git tag

## Troubleshooting

### "No version found"

Ensure you have at least one git tag:

```bash
git tag v2.0.7
```

### "fetch-depth: 0" Required

GitHub Actions must use `fetch-depth: 0` to get full git history for version calculation.

### Version Not Updating

Ensure you've committed your changes - setuptools-scm uses git history, not working directory.
