feat: Implement configuration bundling for customer-specific builds and enhance build scripts
This commit is contained in:
parent
4e5deab7e9
commit
a355c13c82
5 changed files with 750 additions and 22 deletions
|
|
@ -9,13 +9,21 @@ Requirements:
|
|||
- For MSI: WiX Toolset (optional, requires separate installation)
|
||||
|
||||
Usage:
|
||||
python build_windows.py [--msi] [--code-sign]
|
||||
python build_windows.py [--msi] [--code-sign] [--env-file PATH]
|
||||
|
||||
Options:
|
||||
--msi Create MSI installer (requires WiX Toolset)
|
||||
--code-sign Sign executable (requires certificate)
|
||||
--env-file PATH Use custom .env file (default: project root .env)
|
||||
If not provided, uses .env from project root
|
||||
Build fails if .env doesn't exist
|
||||
"""
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
import os
|
||||
import shutil
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
|
|
@ -33,14 +41,35 @@ if sys.platform == "win32":
|
|||
class WindowsBuilder:
|
||||
"""Build Windows installer using PyInstaller."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize builder paths."""
|
||||
def __init__(self, env_file: Path | None = None):
|
||||
"""Initialize builder paths.
|
||||
|
||||
Args:
|
||||
env_file: Path to .env file to bundle. If None, uses project root .env.
|
||||
If that doesn't exist, raises error.
|
||||
"""
|
||||
self.project_root = Path(__file__).parent.parent.parent
|
||||
self.build_dir = self.project_root / "build"
|
||||
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 = get_current_version()
|
||||
|
||||
# Validate and set env file
|
||||
if env_file is None:
|
||||
env_file = self.project_root / ".env"
|
||||
else:
|
||||
env_file = Path(env_file).resolve()
|
||||
|
||||
if not env_file.exists():
|
||||
raise FileNotFoundError(
|
||||
f"Configuration file not found: {env_file}\n"
|
||||
f"Please provide a .env file using --env-file parameter\n"
|
||||
f"or ensure .env exists in project root"
|
||||
)
|
||||
|
||||
self.env_file = env_file
|
||||
print(f"📋 Using configuration: {self.env_file}")
|
||||
|
||||
def _get_version(self) -> str:
|
||||
"""Get version from __init__.py.
|
||||
|
|
@ -66,6 +95,7 @@ class WindowsBuilder:
|
|||
self.temp_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# PyInstaller command using spec file
|
||||
# Pass env_file path as environment variable for spec to pick up
|
||||
cmd = [
|
||||
sys.executable,
|
||||
"-m",
|
||||
|
|
@ -78,11 +108,17 @@ class WindowsBuilder:
|
|||
]
|
||||
|
||||
print(f" Command: {' '.join(cmd)}")
|
||||
|
||||
# Set environment variable for spec file to use
|
||||
env = os.environ.copy()
|
||||
env["WEBDROP_ENV_FILE"] = str(self.env_file)
|
||||
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
cwd=str(self.project_root),
|
||||
encoding="utf-8",
|
||||
errors="replace"
|
||||
errors="replace",
|
||||
env=env
|
||||
)
|
||||
|
||||
if result.returncode != 0:
|
||||
|
|
@ -341,28 +377,40 @@ class WindowsBuilder:
|
|||
return True
|
||||
|
||||
|
||||
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,
|
||||
encoding="utf-8",
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print(f"❌ Version sync failed: {result.stderr}")
|
||||
sys.exit(1)
|
||||
print(result.stdout)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
"""Build Windows MSI installer."""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Build WebDrop Bridge Windows installer"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--msi",
|
||||
action="store_true",
|
||||
help="Create MSI installer (requires WiX Toolset)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--code-sign",
|
||||
action="store_true",
|
||||
help="Sign executable (requires certificate in CODE_SIGN_CERT env var)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--env-file",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Path to .env file to bundle (default: project root .env)",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
print("🔄 Syncing version...")
|
||||
sync_version()
|
||||
|
||||
builder = WindowsBuilder()
|
||||
success = builder.build(create_msi=True, sign=False)
|
||||
try:
|
||||
builder = WindowsBuilder(env_file=args.env_file)
|
||||
except FileNotFoundError as e:
|
||||
print(f"❌ Build failed: {e}")
|
||||
return 1
|
||||
|
||||
success = builder.build(create_msi=args.msi, sign=args.code_sign)
|
||||
|
||||
return 0 if success else 1
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue