# 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