140 lines
3.8 KiB
Markdown
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.
|