webdrop-bridge/VERSIONING_SIMPLIFIED.md

140 lines
3.8 KiB
Markdown

# Simplified Versioning System
## Problem Solved
Previously, the application version had to be manually updated in **multiple places**:
1. `src/webdrop_bridge/__init__.py` - source of truth
2. `pyproject.toml` - package version
3. `.env.example` - environment example
4. Run `scripts/sync_version.py` - manual sync step
This was error-prone and tedious.
## Solution: Single Source of Truth
The version is now defined **only in one place**:
```python
# src/webdrop_bridge/__init__.py
__version__ = "1.0.0"
```
All other components automatically read from this single source.
## How It Works
### 1. **pyproject.toml** (Automatic)
```toml
[tool.setuptools.dynamic]
version = {attr = "webdrop_bridge.__version__"}
[project]
name = "webdrop-bridge"
dynamic = ["version"] # Reads from __init__.py
```
When you build the package, setuptools automatically extracts the version from `__init__.py`.
### 2. **config.py** (Automatic - with ENV override)
```python
# Lazy import to avoid circular imports
if not os.getenv("APP_VERSION"):
from webdrop_bridge import __version__
app_version = __version__
else:
app_version = os.getenv("APP_VERSION")
```
The config automatically reads from `__init__.py`, but can be overridden with the `APP_VERSION` environment variable if needed.
### 3. **sync_version.py** (Simplified)
The script now only handles:
- Updating `__init__.py` with a new version
- Updating `CHANGELOG.md` with a new version header
- Optional: updating `.env.example` if it explicitly sets `APP_VERSION`
It **no longer** needs to manually sync pyproject.toml or config defaults.
## Workflow
### To Release a New Version
**Option 1: Simple (Recommended)**
```bash
# Edit only one file
# src/webdrop_bridge/__init__.py:
__version__ = "1.1.0" # Change this
# Then run sync script to update changelog
python scripts/sync_version.py
```
**Option 2: Using the Sync Script**
```bash
python scripts/sync_version.py --version 1.1.0
```
The script will:
- ✅ Update `__init__.py`
- ✅ Update `CHANGELOG.md`
- ✅ (Optional) Update `.env.example` if it has `APP_VERSION=`
### What Happens Automatically
When you run your application:
1. Config loads and checks environment for `APP_VERSION`
2. If not set, it imports `__version__` from `__init__.py`
3. The version is displayed in the UI
4. Update checks use the correct version
When you build with `pip install`:
1. setuptools reads `__version__` from `__init__.py`
2. Package metadata is set automatically
3. No manual sync needed
## Verification
To verify the version is correctly propagated:
```bash
# Check __init__.py
python -c "from webdrop_bridge import __version__; print(__version__)"
# Check config loading
python -c "from webdrop_bridge.config import Config; c = Config.from_env(); print(c.app_version)"
# Check package metadata (after building)
pip show webdrop-bridge
```
All should show the same version.
## Best Practices
1. **Always edit `__init__.py` first** - it's the single source of truth
2. **Run `sync_version.py` to update changelog** - keeps release notes organized
3. **Use environment variables only for testing** - don't hardcode overrides
4. **Run tests after version changes** - config tests verify version loading
## Migration Notes
If you had other places where version was defined:
- ❌ Remove version from `pyproject.toml` `[project]` section
- ✅ Add `dynamic = ["version"]` instead
- ❌ Don't manually edit `.env.example` for version
- ✅ Let `sync_version.py` handle it
- ❌ Don't hardcode version in config.py defaults
- ✅ Use lazy import from `__init__.py`
## Testing the System
Run the config tests to verify everything works:
```bash
pytest tests/unit/test_config.py -v
```
All tests should pass, confirming version loading works correctly.
---
**Result**: One place to change, multiple places automatically updated. Simple, clean, professional.