From 631bca792373c30bfc45990f8ec4acc03163c4da Mon Sep 17 00:00:00 2001 From: mi Date: Sat, 15 Nov 2025 20:53:31 +1000 Subject: [PATCH] :memo: initial release docs --- CHANGELOG.md | 29 ++++++++ CLAUDE.md | 27 +++++++ scripts/bump_version.py | 154 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 210 insertions(+) create mode 100644 CHANGELOG.md create mode 100755 scripts/bump_version.py diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..3bfbbe5 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,29 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project uses date-based versioning (YYYY.MM.DD). + +## [Unreleased] + +### Added +### Changed +### Deprecated +### Removed +### Fixed +### Security + +## [2025.11.15] - 2025-11-15 + +### Added +- Initial version tracking system +- `version.py` module for source code version reference +- `VERSION` file at project root for easy access +- HTML meta tag (`generator`) displaying version in page source +- Version number injected into all template contexts +- This CHANGELOG.md file to track version history +- Version bump script (`scripts/bump_version.py`) to automate releases + +[Unreleased]: https://git.puercito.net/mi/sunday/compare/v2025.11.15...HEAD +[2025.11.15]: https://git.puercito.net/mi/sunday/releases/tag/v2025.11.15 diff --git a/CLAUDE.md b/CLAUDE.md index 6ca16ed..b9df0c9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -56,6 +56,33 @@ python scripts/rebuild_cache.py ``` Force rebuild the comics cache from YAML files. Normally not needed (cache auto-invalidates). +**Bump version:** +```bash +python scripts/bump_version.py +``` +Updates the project version to today's date (YYYY.MM.DD format) in both `version.py` and `VERSION` files. Optionally opens CHANGELOG.md for editing. + +**Bump version to specific date:** +```bash +python scripts/bump_version.py 2025.12.25 +``` +Sets version to a specific date instead of using today's date. + +## Versioning + +The project uses date-based versioning (YYYY.MM.DD format): +- **`version.py`**: Python module containing `__version__` variable (import with `from version import __version__`) +- **`VERSION`**: Plain text file at project root for easy access by scripts and CI/CD +- **`CHANGELOG.md`**: Tracks version history and changes following [Keep a Changelog](https://keepachangelog.com/) format +- **HTML meta tag**: Version appears in page source as `` + +When releasing a new version: +1. Run `python scripts/bump_version.py` to update version files +2. Edit `CHANGELOG.md` to document changes under the new version +3. Commit changes: `git commit -m "Release version YYYY.MM.DD"` +4. Tag the release: `git tag -a vYYYY.MM.DD -m "Version YYYY.MM.DD"` +5. Push with tags: `git push && git push --tags` + ## Architecture ### Data Layer: YAML Files in data/comics/ diff --git a/scripts/bump_version.py b/scripts/bump_version.py new file mode 100755 index 0000000..5ed4b1f --- /dev/null +++ b/scripts/bump_version.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python3 +# Sunday Comics - Version bump script +# Copyright (c) 2025 Tomasita Cabrera +# Licensed under the MIT License - see LICENSE file for details + +""" +Script to bump the project version number + +Usage: + python scripts/bump_version.py # Use today's date + python scripts/bump_version.py 2025.12.25 # Use specific date +""" +import sys +import os +import re +from datetime import datetime +import argparse + + +def validate_version(version_str): + """Validate version format (YYYY.MM.DD)""" + pattern = r'^\d{4}\.\d{2}\.\d{2}$' + if not re.match(pattern, version_str): + return False + + # Try to parse as a date to ensure it's valid + try: + parts = version_str.split('.') + year, month, day = int(parts[0]), int(parts[1]), int(parts[2]) + datetime(year, month, day) + return True + except ValueError: + return False + + +def get_current_version(parent_dir): + """Read current version from version.py""" + version_file = os.path.join(parent_dir, 'version.py') + try: + with open(version_file, 'r', encoding='utf-8') as f: + content = f.read() + match = re.search(r'__version__\s*=\s*["\']([^"\']+)["\']', content) + if match: + return match.group(1) + except FileNotFoundError: + pass + return None + + +def update_version_py(parent_dir, new_version): + """Update version.py with new version""" + version_file = os.path.join(parent_dir, 'version.py') + + content = f"""# Sunday Comics Version +# This file contains the version number for the project +# Format: YYYY.MM.DD (date-based versioning) + +__version__ = "{new_version}" +""" + + with open(version_file, 'w', encoding='utf-8') as f: + f.write(content) + + print(f"āœ“ Updated {version_file}") + + +def update_version_file(parent_dir, new_version): + """Update VERSION file with new version""" + version_file = os.path.join(parent_dir, 'VERSION') + + with open(version_file, 'w', encoding='utf-8') as f: + f.write(f"{new_version}\n") + + print(f"āœ“ Updated {version_file}") + + +def remind_changelog(parent_dir, new_version, current_version): + """Remind user to update CHANGELOG.md""" + changelog_file = os.path.join(parent_dir, 'CHANGELOG.md') + + print(f"\nšŸ“ Don't forget to update {changelog_file}!") + print(f"\nAdd your changes under the new version section:") + print(f"\n## [{new_version}] - {datetime.now().strftime('%Y-%m-%d')}") + print(f"\n### Added") + print(f"### Changed") + print(f"### Fixed") + + if os.path.exists(changelog_file): + print(f"\nšŸ’” Tip: Edit the file now with: nano {changelog_file}") + + +def main(): + parser = argparse.ArgumentParser( + description='Bump project version number', + epilog='Examples:\n %(prog)s\n %(prog)s 2025.12.25', + formatter_class=argparse.RawDescriptionHelpFormatter + ) + parser.add_argument( + 'version', + nargs='?', + help='Version number in YYYY.MM.DD format (defaults to today\'s date)' + ) + parser.add_argument( + '--no-changelog-reminder', + action='store_true', + help='Skip the changelog reminder' + ) + + args = parser.parse_args() + + # Determine new version + if args.version: + new_version = args.version + if not validate_version(new_version): + print(f"Error: Invalid version format '{new_version}'") + print(f"Expected format: YYYY.MM.DD (e.g., 2025.12.25)") + sys.exit(1) + else: + # Use today's date + new_version = datetime.now().strftime('%Y.%m.%d') + + # Get parent directory (project root) + parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + # Get current version + current_version = get_current_version(parent_dir) + + if current_version: + print(f"Current version: {current_version}") + + print(f"New version: {new_version}") + + # Check if version is the same + if current_version == new_version: + print(f"\nāš ļø Version is already {new_version}") + response = input("Continue anyway? [y/N]: ").lower().strip() + if response != 'y': + print("Aborted.") + sys.exit(0) + + # Update files + print(f"\nUpdating version files...") + update_version_py(parent_dir, new_version) + update_version_file(parent_dir, new_version) + + print(f"\nāœ… Version bumped to {new_version}") + + # Remind about changelog + if not args.no_changelog_reminder: + remind_changelog(parent_dir, new_version, current_version) + + +if __name__ == '__main__': + main()