from __future__ import annotations import argparse import asyncio import logging from pathlib import Path from .pipeline import run_profile_from_file def package_project_root() -> Path: return Path(__file__).resolve().parents[1] def resolve_config_path(raw_path: str, *, project_root: Path) -> Path: path = Path(raw_path) if not path.is_absolute(): path = project_root / path return path.resolve() async def _main() -> int: project_root = package_project_root() parser = argparse.ArgumentParser(description="Run sync pipeline from config override file") parser.add_argument( "--config_path", required=True, help="Path to a JSON/YAML run profile. Relative paths are resolved from the repository root.", ) args = parser.parse_args() cfg_path = resolve_config_path(args.config_path, project_root=project_root) if not cfg_path.exists() or not cfg_path.is_file(): raise FileNotFoundError(f"Config file not found: {cfg_path}") print(f"🧩 Loaded config file: {cfg_path}") await run_profile_from_file( project_root=project_root, config_path=cfg_path, print_summary=True, ) return 0 def main() -> int: try: return asyncio.run(_main()) except KeyboardInterrupt: print("\n⚠️ Interrupted by user") return 130 except Exception as exc: print(f"\n❌ Pipeline failed: {type(exc).__name__}: {exc}") return 1 finally: logging.shutdown() if __name__ == "__main__": raise SystemExit(main())