"""Print services (`services//`) changed by the pushed commit, one per line. Falls back to every service when the parent commit is unavailable (first commit or shallow clone), so a deploy never silently skips a service. """ import re import subprocess import sys from pathlib import Path NAME = re.compile(r"^[a-z][a-z0-9-]{1,30}$") def git(*args: str) -> str: return subprocess.run(["git", *args], check=True, capture_output=True, text=True).stdout def all_services() -> list[str]: root = Path("services") return sorted(p.name for p in root.iterdir() if p.is_dir() and NAME.match(p.name)) if root.is_dir() else [] def changed_paths() -> list[str] | None: try: git("rev-parse", "--verify", "HEAD~1") except subprocess.CalledProcessError: try: git("fetch", "--deepen=1", "-q") git("rev-parse", "--verify", "HEAD~1") except subprocess.CalledProcessError: return None return git("diff", "--name-only", "HEAD~1", "HEAD").splitlines() def main() -> None: paths = changed_paths() if paths is None: print("no parent commit — deploying all services", file=sys.stderr) services = all_services() else: existing = set(all_services()) services = sorted({p.split("/")[1] for p in paths if p.startswith("services/") and p.count("/") >= 2} & existing) print("\n".join(services)) if __name__ == "__main__": main()