elytra_client/update_version.py

126 lines
3.4 KiB
Python

#!/usr/bin/env python
"""Update version across Elytra PIM Client project files.
This script updates the version in:
- pyproject.toml
- elytra_client/__init__.py
Usage:
python update_version.py <version>
python update_version.py 0.2.0
python update_version.py 1.0.0
The version must follow semantic versioning (major.minor.patch).
"""
import re
import sys
from pathlib import Path
def validate_version(version: str) -> bool:
"""Validate semantic version format.
Args:
version: Version string to validate
Returns:
True if valid, False otherwise
"""
pattern = r"^\d+\.\d+\.\d+(?:-[a-zA-Z0-9]+)?$"
return bool(re.match(pattern, version))
def update_file(
file_path: Path, old_pattern: str, new_version: str, multiline: bool = False
) -> bool:
"""Update version in a file.
Args:
file_path: Path to file to update
old_pattern: Regex pattern to find version
new_version: New version string
multiline: Whether to use multiline mode for regex
Returns:
True if successful, False otherwise
"""
try:
content = file_path.read_text()
flags = re.MULTILINE if multiline else 0
updated_content = re.sub(old_pattern, new_version, content, flags=flags)
if content == updated_content:
print(f"{file_path.name} already up-to-date")
return True
file_path.write_text(updated_content)
print(f"✓ Updated {file_path.name}")
return True
except Exception as e:
print(f"✗ Error updating {file_path.name}: {e}")
return False
def main() -> int:
"""Update version in project files.
Returns:
Exit code (0 for success, 1 for failure)
"""
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} <version>")
print(f"Example: {sys.argv[0]} 0.2.0")
return 1
new_version = sys.argv[1]
if not validate_version(new_version):
print(f"✗ Invalid version format: {new_version}")
print("Version must follow semantic versioning (major.minor.patch)")
print("Examples: 1.0.0, 0.2.0, 1.0.0-beta")
return 1
project_root = Path(__file__).parent
pyproject_path = project_root / "pyproject.toml"
init_path = project_root / "elytra_client" / "__init__.py"
print("=" * 70)
print(f"Updating Elytra PIM Client to version {new_version}")
print("=" * 70)
success = True
# Update pyproject.toml
if pyproject_path.exists():
# Use word boundary to match 'version' but not 'python_version'
pattern = r'^version = "[^"]+"'
success &= update_file(
pyproject_path, pattern, f'version = "{new_version}"', multiline=True
)
else:
print(f"{pyproject_path} not found")
success = False
# Update __init__.py
if init_path.exists():
pattern = r'__version__ = "[^"]+"'
success &= update_file(init_path, pattern, f'__version__ = "{new_version}"')
else:
print(f"{init_path} not found")
success = False
if success:
print("=" * 70)
print(f"✓ Version successfully updated to {new_version}")
print("=" * 70)
return 0
else:
print("=" * 70)
print("✗ Version update completed with errors")
print("=" * 70)
return 1
if __name__ == "__main__":
sys.exit(main())