#!/usr/bin/env python3 """repoint.py drill|live|status — (release 2026-10-26 copy: TARGET=9202, Homepage family_gate expected) point the box's controller at the drill catalog, or put the saved controller.yaml back byte for byte. The drill repo on Gitea is PRIVATE (R-992) and the box holds no catalog credential, so the drill is MIRRORED onto the box: a bare git repository in the controller's own data volume, loaded from a git bundle, and `git.repo_url: file:///opt/docker/felhom-controller/drill-catalog.git` — the method of `audits/burndown-3-2026-10-17/tools/repoint.py`. The first version of this file set repo_url to the Gitea URL and believed the repo public; the box's clone then failed („could not read Username", 21:18:11) and the controller ran on the templates it already had — the first drill pass proved nothing (README, „Drill fixes"). `drill` ends with a POSITIVE check, not the absence of an error: the box's catalog cache must be at the drill's main commit, and every `EXPECT` line must be in the box's copy of that template. Prints repo_url, never a token.""" import os, subprocess, sys, time sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../catalog-sweep-2026-10-24/tools")) os.environ.setdefault("TARGET", "9202") import box_walk as w DRILL = "/mnt/5_hdd/felhom.eu/drill/app-catalog-drill" VOL = "/var/lib/docker/volumes/felhom-controller-data/_data" # guest path of the controller's data volume CVOL = "/opt/docker/felhom-controller" # the same, inside the controller container SAVE = f"{VOL}/controller.yaml.pre-release1026-drill" MIRROR_URL = f"file://{CVOL}/drill-catalog.git" EXPECT = [("n8n/docker-compose.yml", "N8N_DIAGNOSTICS_ENABLED=false"), ("opengist/docker-compose.yml", "256M"), ("homepage/.felhom.yml", "family_gate: true")] def status(): print(w.guest(f"""grep -n 'repo_url' {VOL}/controller.yaml; ls -l {SAVE} 2>&1 | tail -1 docker exec felhom-controller sh -c 'git -C {CVOL}/drill-catalog.git log -1 --format="mirror main %h" main 2>&1; git -C {CVOL}/data/catalog-cache log -1 --format="cache HEAD %h" 2>&1; git -C {CVOL}/data/catalog-cache remote get-url origin'""")) def mirror(): b = f"/tmp/drill-rel1026-{os.getpid()}.bundle" subprocess.run(["git", "-C", DRILL, "bundle", "create", b, "main"], check=True, capture_output=True) subprocess.run(["scp", "-q", "-o", "StrictHostKeyChecking=accept-new", b, f"{w._T['ssh']}:{b}"], check=True) subprocess.run(w.ssh_args() + [f"pct push {w.GUEST} {b} {VOL}/{os.path.basename(b)} && rm -f {b}"], check=True) print(w.guest(f"""set -e docker exec felhom-controller sh -c 'test -d {CVOL}/drill-catalog.git || git init -q --bare -b main {CVOL}/drill-catalog.git git -C {CVOL}/drill-catalog.git fetch -q {CVOL}/{os.path.basename(b)} +main:main && rm -f {CVOL}/{os.path.basename(b)} git -C {CVOL}/drill-catalog.git log -1 --format="mirror main %h" main'""")) os.remove(b) def restart_sync(): w.guest("docker restart felhom-controller >/dev/null") for _ in range(60): time.sleep(3) try: w.login() break except SystemExit: continue w.sync_rescan() time.sleep(5) print(w.guest("docker logs --since 3m felhom-controller 2>&1 | grep -E '\\[sync\\]' | grep -v DEBUG | tail -6 | cut -c1-200")) def drill(): head = subprocess.run(["git", "-C", DRILL, "rev-parse", "--short=7", "main"], capture_output=True, text=True).stdout.strip() mirror() print(w.guest(f"""set -e test -f {SAVE} || cp -p {VOL}/controller.yaml {SAVE} sed -i -E 's#^(\\s+repo_url: ).*$#\\1{MIRROR_URL}#' {VOL}/controller.yaml grep -n 'repo_url' {VOL}/controller.yaml""")) restart_sync() cache = w.guest(f"docker exec felhom-controller git -C {CVOL}/data/catalog-cache log -1 --format=%h").strip() ok = cache.startswith(head) for f, want in EXPECT: got = w.guest(f"docker exec felhom-controller grep -c -- '{want}' {CVOL}/data/catalog-cache/templates/{f} || true").strip() print(f" expect {f} ∋ {want}: {got}") ok = ok and got not in ("", "0") print(f"drill main {head}, box cache {cache}: " + ("DRILL-CONFIRMED" if ok else "DRILL-NOT-CONFIRMED")) sys.exit(0 if ok else 1) def live(): print(w.guest(f"""set -e cp -p {SAVE} {VOL}/controller.yaml cmp {SAVE} {VOL}/controller.yaml && echo RESTORED-IDENTICAL; grep -n 'repo_url' {VOL}/controller.yaml""")) restart_sync() status() {"drill": drill, "live": live, "status": status}[sys.argv[1]]()