79 lines
2.6 KiB
Python
79 lines
2.6 KiB
Python
#!/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())
|