From cadeb4a3b59eef518b97c8f51f0d175cab9b16ac Mon Sep 17 00:00:00 2001 From: tegwick Date: Sun, 26 Apr 2026 13:27:09 +0200 Subject: [PATCH] fix(sbom): resolve repo path from hub host_paths when --repo-path omitted Previously defaulted to CWD ("."), causing ingest to silently scan the state-hub directory instead of the target repo when called without --repo-path. Now queries GET /repos/{slug}/ for host_paths[hostname] and exits with a clear error if neither flag nor hub lookup succeeds. Also deleted the incorrect SBOM snapshot for repo-registry (420 entries that were actually state-hub packages). Co-Authored-By: Claude Sonnet 4.6 --- scripts/ingest_sbom.py | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/scripts/ingest_sbom.py b/scripts/ingest_sbom.py index 738b5e1..4e8851a 100644 --- a/scripts/ingest_sbom.py +++ b/scripts/ingest_sbom.py @@ -22,6 +22,7 @@ import argparse import json import os import re +import socket import sys import urllib.error import urllib.request @@ -505,6 +506,23 @@ def post_ingest(api_base: str, repo_slug: str, entries: list[dict]) -> dict: # Entry point # --------------------------------------------------------------------------- +def _resolve_repo_path_from_hub(api_base: str, repo_slug: str) -> Path | None: + """Query the hub for this host's registered path for repo_slug.""" + try: + url = f"{api_base}/repos/{repo_slug}/" + with urllib.request.urlopen(url) as resp: + data = json.loads(resp.read()) + hostname = socket.gethostname() + host_paths = data.get("host_paths", {}) + if hostname in host_paths: + p = Path(host_paths[hostname]) + if p.exists(): + return p + except Exception: + pass + return None + + def main() -> None: parser = argparse.ArgumentParser( description="Ingest a repo's lockfiles and tool manifests into the State Hub SBOM store." @@ -512,14 +530,28 @@ def main() -> None: parser.add_argument("--repo", required=True, help="Managed-repo slug (e.g. 'the-custodian')") parser.add_argument("--lockfile", action="append", dest="lockfiles", metavar="PATH", help="Path to a specific lockfile (repeatable)") - parser.add_argument("--repo-path", default=".", help="Repo root for auto-detection/scan (default: cwd)") + parser.add_argument("--repo-path", default=None, + help="Repo root for auto-detection/scan (default: resolved from hub host_paths)") parser.add_argument("--scan", action="store_true", help="Recursively find ALL lockfiles under --repo-path (deprecated; now default behaviour)") parser.add_argument("--api-base", default=API_BASE, help="State Hub API base URL") parser.add_argument("--dry-run", action="store_true", help="Parse only — do not submit") args = parser.parse_args() - repo_root = Path(args.repo_path).resolve() + if args.repo_path is not None: + repo_root = Path(args.repo_path).resolve() + else: + resolved = _resolve_repo_path_from_hub(args.api_base, args.repo) + if resolved: + repo_root = resolved + print(f" Repo path resolved from hub: {repo_root}") + else: + print( + f"ERROR: --repo-path not given and hub lookup failed for '{args.repo}'.\n" + f" Register the repo first or pass --repo-path explicitly.", + file=sys.stderr, + ) + sys.exit(1) all_entries: list[dict] = [] if args.lockfiles: