feat: Implement centralized version management and sync process

This commit is contained in:
claudi 2026-01-30 09:16:12 +01:00
parent c1133ae8e9
commit 0d9464854d
7 changed files with 523 additions and 45 deletions

View file

@ -19,6 +19,9 @@ import shutil
from pathlib import Path
from datetime import datetime
# Import shared version utilities
from version_utils import get_current_version
# Fix Unicode output on Windows
if sys.platform == "win32":
import io
@ -37,16 +40,15 @@ class WindowsBuilder:
self.dist_dir = self.build_dir / "dist" / "windows"
self.temp_dir = self.build_dir / "temp" / "windows"
self.spec_file = self.build_dir / "webdrop_bridge.spec"
self.version = self._get_version()
self.version = get_current_version()
def _get_version(self) -> str:
"""Get version from config.py."""
config_file = self.project_root / "src" / "webdrop_bridge" / "config.py"
for line in config_file.read_text().split("\n"):
if "app_version" in line and "1.0.0" in line:
# Extract default version from config
return "1.0.0"
return "1.0.0"
"""Get version from __init__.py.
Note: This method is deprecated. Use get_current_version() from
version_utils.py instead.
"""
return get_current_version()
def clean(self):
"""Clean previous builds."""
@ -322,28 +324,27 @@ class WindowsBuilder:
return True
def main():
"""Main entry point."""
import argparse
def sync_version() -> None:
"""Sync version from __init__.py to all dependent files."""
script_path = Path(__file__).parent.parent.parent / "scripts" / "sync_version.py"
result = subprocess.run(
[sys.executable, str(script_path)],
capture_output=True,
text=True,
)
if result.returncode != 0:
print(f"❌ Version sync failed: {result.stderr}")
sys.exit(1)
print(result.stdout)
parser = argparse.ArgumentParser(
description="Build WebDrop Bridge for Windows"
)
parser.add_argument(
"--msi",
action="store_true",
help="Create MSI installer (requires WiX Toolset)",
)
parser.add_argument(
"--sign",
action="store_true",
help="Sign executable (requires CODE_SIGN_CERT environment variable)",
)
args = parser.parse_args()
def main() -> int:
"""Build Windows MSI installer."""
print("🔄 Syncing version...")
sync_version()
builder = WindowsBuilder()
success = builder.build(create_msi=args.msi, sign=args.sign)
success = builder.build(create_msi=True, sign=False)
return 0 if success else 1

View file

@ -0,0 +1,49 @@
"""Shared version management utilities for build scripts.
This module provides a single source of truth for version reading
to avoid duplication between different build scripts.
"""
import re
from pathlib import Path
def get_project_root() -> Path:
"""Get the project root directory.
Returns:
Path to project root (parent of build/scripts)
"""
return Path(__file__).parent.parent.parent
def get_current_version() -> str:
"""Read version from __init__.py.
This is the single source of truth for version information.
All build scripts and version management tools use this function.
Returns:
Current version string from __init__.py
Raises:
ValueError: If __version__ cannot be found in __init__.py
"""
project_root = get_project_root()
init_file = project_root / "src" / "webdrop_bridge" / "__init__.py"
if not init_file.exists():
raise FileNotFoundError(
f"Cannot find __init__.py at {init_file}"
)
content = init_file.read_text(encoding="utf-8")
match = re.search(r'__version__\s*=\s*["\']([^"\']+)["\']', content)
if not match:
raise ValueError(
f"Could not find __version__ in {init_file}. "
"Expected: __version__ = \"X.Y.Z\""
)
return match.group(1)