#!/usr/bin/env python3 """Install or verify the canonical package-release workflow in module repos.""" from __future__ import annotations import argparse import json from pathlib import Path import sys META_ROOT = Path(__file__).resolve().parents[2] TEMPLATE = META_ROOT / "tools" / "repo" / "templates" / "module-package-release.yml" DESTINATION = Path(".gitea/workflows/module-package-release.yml") def build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(description=__doc__) mode = parser.add_mutually_exclusive_group(required=True) mode.add_argument("--check", action="store_true") mode.add_argument("--write", action="store_true") parser.add_argument( "--parent", type=Path, default=META_ROOT.parent, help="Parent directory containing the repositories.", ) return parser def package_repositories(parent: Path) -> tuple[Path, ...]: inventory = json.loads((META_ROOT / "repositories.json").read_text(encoding="utf-8")) repositories: list[Path] = [] for item in inventory["repositories"]: name = str(item["name"]) if not name.startswith("govoplan-"): continue repository = parent / str(item["path"]) if (repository / "pyproject.toml").is_file(): repositories.append(repository) return tuple(sorted(repositories)) def synchronize(*, parent: Path, write: bool) -> tuple[str, ...]: expected = TEMPLATE.read_bytes() mismatches: list[str] = [] for repository in package_repositories(parent): destination = repository / DESTINATION current = destination.read_bytes() if destination.is_file() else None if current == expected: continue mismatches.append(repository.name) if write: destination.parent.mkdir(parents=True, exist_ok=True) temporary = destination.with_suffix(destination.suffix + ".tmp") temporary.write_bytes(expected) temporary.chmod(0o644) temporary.replace(destination) return tuple(mismatches) def main() -> int: args = build_parser().parse_args() mismatches = synchronize(parent=args.parent.expanduser().resolve(), write=args.write) if args.write: print(f"Installed package-release workflow in {len(mismatches)} repositories.") return 0 if mismatches: print("Package-release workflow is missing or stale in:", file=sys.stderr) for repository in mismatches: print(f"- {repository}", file=sys.stderr) return 1 print("Package-release workflows are synchronized.") return 0 if __name__ == "__main__": raise SystemExit(main())