#!/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()