fix(classification): harden registration updates
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Multi-Context Image / build-and-push (push) Successful in 26s

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a02b22-9638-76d2-bbff-b7ea1770b118
This commit is contained in:
tegwick 2026-08-23 11:30:36 +02:00
parent fb79d0d68d
commit 57c3e08103
7 changed files with 152 additions and 14 deletions

View file

@ -136,6 +136,21 @@ def _git_root(path: Path) -> Path:
return Path(root) if root else path.resolve()
def _git_fingerprint(repo_path: Path) -> str | None:
"""Return the same single-root fingerprint used by token attribution.
A repository can contain multiple unrelated root commits. ``git rev-list``
emits one SHA per line in that case, while ``managed_repos.git_fingerprint``
stores one 40-character SHA. Token attribution already uses the first root,
so registration must use the same projection rather than sending a multiline
value to the API/database.
"""
roots = _git_value(repo_path, ["rev-list", "--max-parents=0", "HEAD"])
if not roots:
return None
return roots.splitlines()[0].strip() or None
def _resolve_repo_path_for_host(repo: ManagedRepo) -> str | None:
hostname = socket.gethostname()
host_paths = repo.host_paths or {}
@ -226,7 +241,7 @@ async def _upsert_via_db(
) -> None:
git_root = _git_root(repo_path)
remote_url = _git_value(git_root, ["remote", "get-url", "origin"])
git_fingerprint = _git_value(git_root, ["rev-list", "--max-parents=0", "HEAD"])
git_fingerprint = _git_fingerprint(git_root)
hostname = socket.gethostname()
display_name = git_root.name.replace("-", " ").replace("_", " ").title()
@ -345,7 +360,7 @@ async def _upsert_via_api(
) -> None:
git_root = _git_root(repo_path)
remote_url = _git_value(git_root, ["remote", "get-url", "origin"])
git_fingerprint = _git_value(git_root, ["rev-list", "--max-parents=0", "HEAD"])
git_fingerprint = _git_fingerprint(git_root)
hostname = socket.gethostname()
display_name = git_root.name.replace("-", " ").replace("_", " ").title()
@ -363,7 +378,7 @@ async def _upsert_via_api(
)
return
patch_body = {
classification_body = {
"category": data.category,
"secondary_domains": data.secondary_domains,
"capability_tags": data.capability_tags,
@ -373,9 +388,6 @@ async def _upsert_via_api(
"classified_by": data.classified_by,
"standard_version": data.standard_version,
"domain_slug": data.domain,
"local_path": str(git_root),
"remote_url": remote_url,
"git_fingerprint": git_fingerprint,
}
if existing is None:
@ -404,7 +416,7 @@ async def _upsert_via_api(
report.add(RowResult(slug, str(git_root), "invalid", f"POST failed: {detail}"))
return
code, updated = _api_request(
"PATCH", f"/repos/{slug}", api_base=api_base, body=patch_body
"PATCH", f"/repos/{slug}", api_base=api_base, body=classification_body
)
if code != 200:
detail = updated.get("detail", updated) if isinstance(updated, dict) else updated
@ -432,7 +444,7 @@ async def _upsert_via_api(
return
code, updated = _api_request(
"PATCH", f"/repos/{slug}", api_base=api_base, body=patch_body
"PATCH", f"/repos/{slug}", api_base=api_base, body=classification_body
)
if code != 200:
detail = updated.get("detail", updated) if isinstance(updated, dict) else updated
@ -632,4 +644,4 @@ def main(argv: list[str] | None = None) -> int:
if __name__ == "__main__":
raise SystemExit(main())
raise SystemExit(main())