# 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
