Files
StarPunk/docs/standards/version-implementation-guide.md
2025-11-18 19:21:31 -07:00

604 lines
13 KiB
Markdown

# Version Implementation Guide
## Quick Reference
This guide shows exactly where and how version information is stored in StarPunk.
**See Also**: [versioning-strategy.md](versioning-strategy.md) for complete strategy documentation.
## Version Storage Locations
### 1. Primary Source: `starpunk/__init__.py`
**Status**: ✅ Already implemented
**Location**: `/home/phil/Projects/starpunk/starpunk/__init__.py`
**Content**:
```python
# Package version (Semantic Versioning 2.0.0)
# See docs/standards/versioning-strategy.md for details
__version__ = "0.1.0"
__version_info__ = (0, 1, 0)
```
**Usage**:
```python
from starpunk import __version__, __version_info__
print(f"StarPunk version {__version__}")
print(f"Version info: {__version_info__}") # (0, 1, 0)
```
**Format**:
- `__version__`: String in PEP 440 format (e.g., `"1.0.0"`, `"1.0.0a1"`, `"1.0.0rc1"`)
- `__version_info__`: Tuple of integers (major, minor, patch) for programmatic comparison
---
### 2. README.md
**Status**: ✅ Already implemented
**Location**: `/home/phil/Projects/starpunk/README.md`
**Content**: Shows current version at the top of the file:
```markdown
# StarPunk
A minimal, self-hosted IndieWeb CMS for publishing notes with RSS syndication.
**Current Version**: 0.1.0 (development)
## Versioning
StarPunk follows [Semantic Versioning 2.0.0](https://semver.org/):
- Version format: `MAJOR.MINOR.PATCH`
- Current: `0.1.0` (pre-release development)
- First stable release will be `1.0.0`
```
**Update when**: Version changes (manually)
---
### 3. CHANGELOG.md
**Status**: ✅ Created
**Location**: `/home/phil/Projects/starpunk/CHANGELOG.md`
**Format**: Based on [Keep a Changelog](https://keepachangelog.com/)
**Structure**:
```markdown
# Changelog
## [Unreleased]
### Added
- Features being developed
## [1.0.0] - 2024-11-18
### Added
- New features
### Changed
- Changes to existing features
### Fixed
- Bug fixes
### Security
- Security patches
```
**Update when**: Every change (add to `[Unreleased]`), then move to versioned section on release
---
### 4. Git Tags
**Status**: ⏳ To be created when releasing
**Format**: `vMAJOR.MINOR.PATCH[-PRERELEASE]`
**Examples**:
```bash
v0.1.0 # Development version
v0.2.0 # Next development version
v1.0.0-alpha.1 # Alpha pre-release
v1.0.0-beta.1 # Beta pre-release
v1.0.0-rc.1 # Release candidate
v1.0.0 # Stable release
```
**How to Create**:
```bash
# Annotated tag (recommended)
git tag -a v0.1.0 -m "Development version 0.1.0: Phase 1.1 complete
- Core utilities implemented
- Slug generation
- File operations
- Content hashing
See CHANGELOG.md for full details."
# Push tag
git push origin v0.1.0
```
**Current Tags**: None yet (will create when Phase 1.1 is complete)
---
### 5. pyproject.toml (Optional, Future)
**Status**: ⚠️ Not currently used
**Location**: `/home/phil/Projects/starpunk/pyproject.toml` (if created)
**Content** (if we create this file):
```toml
[project]
name = "starpunk"
version = "0.1.0"
description = "Minimal IndieWeb CMS"
authors = [
{name = "Your Name", email = "your@email.com"}
]
dependencies = [
"flask>=3.0.0",
"python-markdown>=3.5.0",
"feedgen>=1.0.0",
"httpx>=0.25.0",
]
[project.urls]
Homepage = "https://github.com/YOUR_USERNAME/starpunk"
Repository = "https://github.com/YOUR_USERNAME/starpunk"
Changelog = "https://github.com/YOUR_USERNAME/starpunk/blob/main/CHANGELOG.md"
```
**Decision**: Not needed for V1 (keeping it simple)
---
## How to Update Version
### Step-by-Step Process
When you're ready to release a new version:
#### 1. Decide on Version Number
Use the decision tree from `versioning-strategy.md`:
- **Breaking changes?** → Increment MAJOR (e.g., 1.0.0 → 2.0.0)
- **New features?** → Increment MINOR (e.g., 1.0.0 → 1.1.0)
- **Bug fixes only?** → Increment PATCH (e.g., 1.0.0 → 1.0.1)
**During 0.x development**:
- **Phase complete?** → Increment MINOR (e.g., 0.1.0 → 0.2.0)
- **Bug fix?** → Increment PATCH (e.g., 0.1.0 → 0.1.1)
#### 2. Update `starpunk/__init__.py`
```python
# Change version strings
__version__ = "0.2.0" # New version
__version_info__ = (0, 2, 0) # New version tuple
```
#### 3. Update `CHANGELOG.md`
Move `[Unreleased]` items to new version section:
```markdown
## [Unreleased]
### Added
### Changed
### Fixed
## [0.2.0] - 2024-11-19
### Added
- Data models implementation
- Database schema
- Note class with validation
### Changed
- Improved error handling in utilities
[Unreleased]: https://github.com/YOUR_USERNAME/starpunk/compare/v0.2.0...HEAD
[0.2.0]: https://github.com/YOUR_USERNAME/starpunk/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/YOUR_USERNAME/starpunk/releases/tag/v0.1.0
```
#### 4. Update `README.md`
Change current version:
```markdown
**Current Version**: 0.2.0 (development)
```
#### 5. Commit Changes
```bash
git add starpunk/__init__.py CHANGELOG.md README.md
git commit -m "Bump version to 0.2.0"
```
#### 6. Create Git Tag
```bash
git tag -a v0.2.0 -m "Development version 0.2.0: Phase 1.2 complete
- Data models implementation
- Database schema defined
- Note class with full validation
- Session and token models
See CHANGELOG.md for full details."
```
#### 7. Push to Repository
```bash
git push origin main
git push origin v0.2.0
```
#### 8. Create GitHub Release (Optional)
If using GitHub:
1. Go to repository → Releases
2. Click "Draft a new release"
3. Choose tag: `v0.2.0`
4. Release title: `Version 0.2.0`
5. Description: Copy from CHANGELOG.md
6. Publish release
---
## How to Check Version
### From Python Code
```python
# Method 1: Import from package
from starpunk import __version__
print(f"Version: {__version__}")
# Method 2: Use version_info for comparisons
from starpunk import __version_info__
if __version_info__ >= (1, 0, 0):
print("Stable release")
else:
print("Development version")
```
### From Command Line
```bash
# Method 1: Python one-liner
python -c "from starpunk import __version__; print(__version__)"
# Method 2: Check Git tags
git tag -l
# Method 3: Check current HEAD tag
git describe --tags --abbrev=0
# Method 4: Show all version info
git describe --tags
```
### From Web Interface (Future)
When implemented, will show in:
- Footer of all pages
- `/api/info` endpoint
- Admin dashboard
---
## Version Comparison Examples
### Using `__version_info__`
```python
from starpunk import __version_info__
# Check minimum version
def require_version(major, minor, patch):
return __version_info__ >= (major, minor, patch)
# Examples
if require_version(1, 0, 0):
print("Running stable version")
if require_version(0, 2, 0):
print("Has data models")
```
### Parsing `__version__` String
```python
from starpunk import __version__
from packaging.version import Version
current = Version(__version__)
required = Version("1.0.0")
if current >= required:
print("Version requirement met")
```
---
## Release Checklist
Use this checklist when releasing a new version:
### Pre-Release
- [ ] All tests pass: `pytest`
- [ ] Code formatted: `black starpunk/ tests/`
- [ ] Code linted: `flake8 starpunk/ tests/`
- [ ] Documentation updated
- [ ] All features working
- [ ] Manual testing completed
### Version Bump
- [ ] Decide version number (MAJOR.MINOR.PATCH)
- [ ] Update `starpunk/__init__.py``__version__`
- [ ] Update `starpunk/__init__.py``__version_info__`
- [ ] Update `CHANGELOG.md` with changes and date
- [ ] Update `README.md` with current version
- [ ] Review changes: `git diff`
### Commit and Tag
- [ ] Stage files: `git add starpunk/__init__.py CHANGELOG.md README.md`
- [ ] Commit: `git commit -m "Bump version to X.Y.Z"`
- [ ] Create annotated tag: `git tag -a vX.Y.Z -m "Release X.Y.Z: [description]"`
- [ ] Push commits: `git push origin main`
- [ ] Push tag: `git push origin vX.Y.Z`
### Post-Release
- [ ] Verify tag exists: `git tag -l`
- [ ] Create GitHub release (if applicable)
- [ ] Test installation from tag
- [ ] Announce release (if applicable)
- [ ] Create `[Unreleased]` section in CHANGELOG.md for next development
---
## Common Scenarios
### Scenario 1: Completing a Development Phase
**Situation**: Phase 1.2 is complete (data models implemented)
**Action**:
1. Version: 0.1.0 → 0.2.0 (increment MINOR during 0.x)
2. Update `__init__.py`: `__version__ = "0.2.0"`, `__version_info__ = (0, 2, 0)`
3. Update CHANGELOG: Add `[0.2.0]` section with date
4. Commit: `"Bump version to 0.2.0"`
5. Tag: `v0.2.0`
6. Push
### Scenario 2: Fixing a Bug
**Situation**: Found bug in slug generation, fixed it
**Action**:
1. Version: 0.2.0 → 0.2.1 (increment PATCH)
2. Update `__init__.py`: `__version__ = "0.2.1"`, `__version_info__ = (0, 2, 1)`
3. Update CHANGELOG: Add `[0.2.1]` section with bug fix
4. Commit: `"Bump version to 0.2.1"`
5. Tag: `v0.2.1`
6. Push
### Scenario 3: First Stable Release
**Situation**: All V1 features complete, ready for production
**Action**:
1. Version: 0.9.0 → 1.0.0 (first stable release!)
2. Update `__init__.py`: `__version__ = "1.0.0"`, `__version_info__ = (1, 0, 0)`
3. Update CHANGELOG: Comprehensive `[1.0.0]` section
4. Update README: Change "0.x.0 (development)" to "1.0.0 (stable)"
5. Commit: `"Bump version to 1.0.0 - First stable release"`
6. Tag: `v1.0.0` with detailed release notes
7. Push
8. Create GitHub release with announcement
### Scenario 4: Adding New Feature (Post-1.0)
**Situation**: Added tags feature in version 1.0.0, want to release it
**Action**:
1. Version: 1.0.0 → 1.1.0 (increment MINOR for new feature)
2. Update `__init__.py`: `__version__ = "1.1.0"`, `__version_info__ = (1, 1, 0)`
3. Update CHANGELOG: Add `[1.1.0]` section with "Added: Tags support"
4. Commit and tag
5. Push
### Scenario 5: Breaking Change (Post-1.0)
**Situation**: Changed Micropub API response format (breaking change)
**Action**:
1. Version: 1.5.0 → 2.0.0 (increment MAJOR for breaking change)
2. Update `__init__.py`: `__version__ = "2.0.0"`, `__version_info__ = (2, 0, 0)`
3. Update CHANGELOG: Clear "Breaking Changes" section
4. Create upgrade guide: `docs/upgrade/1.x-to-2.0.md`
5. Commit and tag
6. Push
7. Prominently announce breaking changes
---
## Troubleshooting
### Version Mismatch
**Problem**: `__version__` and `__version_info__` don't match
**Solution**: They must always match:
```python
# Correct
__version__ = "1.2.3"
__version_info__ = (1, 2, 3)
# Wrong
__version__ = "1.2.3"
__version_info__ = (1, 2, 0) # Mismatch!
```
### Forgot to Update CHANGELOG
**Problem**: Released version without updating CHANGELOG
**Solution**:
1. Update CHANGELOG now
2. Commit: `"Update CHANGELOG for version X.Y.Z"`
3. Don't change version number or tag
4. Consider creating patch release with corrected changelog
### Wrong Version Number
**Problem**: Tagged v1.1.0 but should have been v2.0.0
**Solution**:
```bash
# Delete local tag
git tag -d v1.1.0
# Delete remote tag
git push origin :refs/tags/v1.1.0
# Create correct tag
git tag -a v2.0.0 -m "Release 2.0.0"
git push origin v2.0.0
```
**Warning**: Only do this immediately after release, before anyone uses the tag!
### Git Tag vs Python Version Mismatch
**Problem**: Git tag says `v1.0.0` but `__version__` says `"0.9.0"`
**Solution**: These must always match:
1. Check Git tag: `git describe --tags`
2. Check Python version: `python -c "from starpunk import __version__; print(__version__)"`
3. They should match (ignoring `v` prefix)
4. If mismatch, fix `__init__.py` and create new tag
---
## Pre-Release Versions
### Alpha Releases
**When**: Early development, unstable, missing features
**Format**:
- Git tag: `v1.0.0-alpha.1`
- Python `__version__`: `"1.0.0a1"` (PEP 440 format)
- `__version_info__`: `(1, 0, 0, "alpha", 1)` (extended tuple)
**Example**:
```python
__version__ = "1.0.0a1"
__version_info__ = (1, 0, 0) # Simplified, or extended: (1, 0, 0, "alpha", 1)
```
### Beta Releases
**When**: Feature complete, testing phase
**Format**:
- Git tag: `v1.0.0-beta.1`
- Python `__version__`: `"1.0.0b1"`
- `__version_info__`: `(1, 0, 0)`
### Release Candidates
**When**: Final testing before stable release
**Format**:
- Git tag: `v1.0.0-rc.1`
- Python `__version__`: `"1.0.0rc1"`
- `__version_info__`: `(1, 0, 0)`
**Note**: For V1, we may skip pre-releases entirely and go straight to 1.0.0 if 0.x testing is sufficient.
---
## Integration with Other Systems
### Flask Application
```python
# In Flask app
from starpunk import __version__
@app.route('/api/info')
def api_info():
return {
"name": "StarPunk",
"version": __version__,
"micropub_endpoint": "/api/micropub"
}
```
### CLI Tool (Future)
```python
import click
from starpunk import __version__
@click.group()
@click.version_option(version=__version__, prog_name="StarPunk")
def cli():
"""StarPunk CMS"""
pass
```
### User-Agent String
```python
from starpunk import __version__
USER_AGENT = f"StarPunk/{__version__} (https://github.com/YOUR_USERNAME/starpunk)"
# Use in HTTP requests
headers = {"User-Agent": USER_AGENT}
```
---
## References
- [Versioning Strategy (complete spec)](versioning-strategy.md)
- [ADR-008: Versioning Strategy](../decisions/ADR-008-versioning-strategy.md)
- [Semantic Versioning 2.0.0](https://semver.org/)
- [PEP 440 - Version Identification](https://peps.python.org/pep-0440/)
- [Keep a Changelog](https://keepachangelog.com/)
---
**Document Version**: 1.0
**Last Updated**: 2024-11-18
**Status**: Active