Harden SBOM retries and align hub evidence
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Container Image / build-and-push (push) Successful in 21s

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a028de-e2c8-7732-8521-46a7fc5db82f
This commit is contained in:
tegwick 2026-08-22 22:51:13 +02:00
parent 0f573c4378
commit 3b3e1a1ff0
17 changed files with 941 additions and 140 deletions

View file

@ -199,6 +199,81 @@ async def resolve_context(
return snapshot
def _sbom_heartbeat_state(run_id: str) -> dict[str, Any]:
try:
details = activity.info().heartbeat_details
except RuntimeError:
return {"run_id": run_id, "outcomes_by_bind": {}}
if not details or not isinstance(details[0], dict):
return {"run_id": run_id, "outcomes_by_bind": {}}
state = dict(details[0])
if state.get("run_id") != run_id:
return {"run_id": run_id, "outcomes_by_bind": {}}
if not isinstance(state.get("outcomes_by_bind"), dict):
state["outcomes_by_bind"] = {}
return state
def _heartbeat_sbom_state(state: dict[str, Any]) -> None:
try:
activity.heartbeat(state)
except RuntimeError:
# Direct unit invocation has no Temporal activity context.
pass
@activity.defn
async def apply_sbom_catchup(payload: dict[str, Any]) -> dict[str, dict[str, Any]]:
"""Apply declared SBOM writes to the fixed selection in workflow history."""
from activity_core.context_resolvers.sbom_nexus import apply_bounded_ingest
run_id = str(payload["run_id"])
context_sources = payload.get("context_sources") or []
context = payload.get("context") or {}
heartbeat_state = _sbom_heartbeat_state(run_id)
outcomes_by_bind = heartbeat_state["outcomes_by_bind"]
patches: dict[str, dict[str, Any]] = {}
for source in context_sources:
if not isinstance(source, dict):
continue
params = source.get("params") or {}
if not (
source.get("type") == "sbom-nexus"
and source.get("query") == "catch_up"
and params.get("apply") is True
):
continue
raw_bind = source.get("bind_to") or source.get("name") or "sbom-nexus"
bind_key = str(raw_bind).removeprefix("context.")
selection = context.get(bind_key)
if not isinstance(selection, dict):
continue
repos = selection.get("repos")
if not isinstance(repos, list):
continue
try:
limit = int(selection.get("limit", params.get("limit", 3)))
except (TypeError, ValueError):
limit = 3
limit = max(1, min(25, limit))
fixed_repos = [repo for repo in repos[:limit] if isinstance(repo, dict)]
def record_progress(outcomes: list[dict[str, Any]]) -> None:
outcomes_by_bind[bind_key] = outcomes
_heartbeat_sbom_state(heartbeat_state)
patches[bind_key] = apply_bounded_ingest(
fixed_repos,
operation_id=run_id,
completed=outcomes_by_bind.get(bind_key),
on_progress=record_progress,
)
return patches
@activity.defn
async def log_run(run_payload: dict) -> str:
"""Persist an ActivityRun record to Postgres and return its run_id.