diff --git a/sync_version.py b/sync_version.py new file mode 100644 index 0000000..f5f425f --- /dev/null +++ b/sync_version.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python3 +""" +Version synchronization script for vultr-dns-mcp. + +This script ensures that the version number in pyproject.toml +and src/vultr_dns_mcp/_version.py are kept in sync. + +Usage: + python sync_version.py # Check if versions are in sync + python sync_version.py --update # Update _version.py to match pyproject.toml + python sync_version.py --set 1.0.2 # Set both versions to 1.0.2 +""" + +import argparse +import re +import sys +from pathlib import Path + +try: + import tomllib +except ImportError: + try: + import tomli as tomllib + except ImportError: + print("Error: tomllib or tomli not available. Install with: pip install tomli") + sys.exit(1) + + +def get_version_from_pyproject() -> str: + """Get version from pyproject.toml.""" + pyproject_path = Path("pyproject.toml") + if not pyproject_path.exists(): + raise FileNotFoundError("pyproject.toml not found") + + with open(pyproject_path, "rb") as f: + data = tomllib.load(f) + + return data["project"]["version"] + + +def get_version_from_version_py() -> str: + """Get version from _version.py.""" + version_path = Path("src/vultr_dns_mcp/_version.py") + if not version_path.exists(): + raise FileNotFoundError("src/vultr_dns_mcp/_version.py not found") + + with open(version_path, "r") as f: + content = f.read() + + match = re.search(r'__version__\s*=\s*["\']([^"\']+)["\']', content) + if not match: + raise ValueError("Could not find __version__ in _version.py") + + return match.group(1) + + +def update_version_py(new_version: str) -> None: + """Update version in _version.py.""" + version_path = Path("src/vultr_dns_mcp/_version.py") + + content = f'''"""Version information for vultr-dns-mcp package.""" + +__version__ = "{new_version}" +__version_info__ = tuple(int(i) for i in __version__.split(".") if i.isdigit()) +''' + + with open(version_path, "w") as f: + f.write(content) + + print(f"✅ Updated _version.py to {new_version}") + + +def update_pyproject_toml(new_version: str) -> None: + """Update version in pyproject.toml.""" + pyproject_path = Path("pyproject.toml") + + with open(pyproject_path, "r") as f: + content = f.read() + + # Replace version line + pattern = r'(version\s*=\s*)["\'][^"\']+["\']' + replacement = f'\\1"{new_version}"' + new_content = re.sub(pattern, replacement, content) + + with open(pyproject_path, "w") as f: + f.write(new_content) + + print(f"✅ Updated pyproject.toml to {new_version}") + + +def check_versions() -> tuple[str, str, bool]: + """Check if versions are in sync.""" + try: + pyproject_version = get_version_from_pyproject() + version_py_version = get_version_from_version_py() + + in_sync = pyproject_version == version_py_version + + return pyproject_version, version_py_version, in_sync + + except Exception as e: + print(f"❌ Error reading versions: {e}") + sys.exit(1) + + +def validate_version(version: str) -> bool: + """Validate version format (basic semver check).""" + pattern = r'^\d+\.\d+\.\d+(?:-[a-zA-Z0-9]+(?:\.\d+)?)?$' + return bool(re.match(pattern, version)) + + +def main(): + parser = argparse.ArgumentParser(description="Sync version numbers between files") + group = parser.add_mutually_exclusive_group() + group.add_argument("--update", action="store_true", + help="Update _version.py to match pyproject.toml") + group.add_argument("--set", metavar="VERSION", + help="Set both files to the specified version") + + args = parser.parse_args() + + if args.set: + if not validate_version(args.set): + print(f"❌ Invalid version format: {args.set}") + print("Expected format: X.Y.Z or X.Y.Z-suffix") + sys.exit(1) + + update_pyproject_toml(args.set) + update_version_py(args.set) + print(f"✅ Set both versions to {args.set}") + + elif args.update: + pyproject_version, version_py_version, in_sync = check_versions() + + if in_sync: + print(f"✅ Versions already in sync: {pyproject_version}") + else: + update_version_py(pyproject_version) + print(f"✅ Updated _version.py from {version_py_version} to {pyproject_version}") + + else: + # Default: check status + pyproject_version, version_py_version, in_sync = check_versions() + + print("📋 Version Status:") + print(f" pyproject.toml: {pyproject_version}") + print(f" _version.py: {version_py_version}") + + if in_sync: + print("✅ Versions are in sync!") + else: + print("❌ Versions are out of sync!") + print("\nTo fix:") + print(" python sync_version.py --update # Update _version.py to match pyproject.toml") + print(" python sync_version.py --set X.Y.Z # Set both to version X.Y.Z") + sys.exit(1) + + +if __name__ == "__main__": + main()