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

@ -20,6 +20,7 @@ from temporalio.common import RetryPolicy, SearchAttributeKey, TypedSearchAttrib
with workflow.unsafe.imports_passed_through():
from activity_core.activities import (
apply_sbom_catchup,
emit_tasks,
evaluate_rules,
evaluate_instructions,
@ -57,10 +58,10 @@ class RunActivityWorkflow:
Sequence:
1. load_activity_definition(activity_id) → defn dict
2. resolve_context(defn.context_sources) → context snapshot
3. evaluate_rules(rules, event, context) → matching rules → TaskSpec dicts
4. emit_tasks(task_specs) → TaskRef list via IssueSink
5. log_run(...) → activity_runs row
2. resolve_context(defn.context_sources) → read-only context snapshot
3. apply_sbom_catchup(fixed selection) → bounded outcome patch
4. evaluate rules/instructions → TaskSpec dicts and reports
5. log run, then emit tasks
"""
@workflow.run
@ -99,7 +100,13 @@ class RunActivityWorkflow:
])
)
# ── 2. Resolve context ────────────────────────────────────────────────
if trigger_key == SCHEDULED_TRIGGER_KEY:
dedup_source = workflow.info().workflow_id
else:
dedup_source = f"{activity_id}:{trigger_key}"
run_id = str(uuid.uuid5(uuid.NAMESPACE_URL, dedup_source))
# ── 2. Resolve context (read-only) ────────────────────────────────────
context_snapshot: dict = await workflow.execute_activity(
resolve_context,
args=[defn["context_sources"], event_envelope_json],
@ -107,11 +114,29 @@ class RunActivityWorkflow:
retry_policy=_RETRY_POLICY,
)
if trigger_key == SCHEDULED_TRIGGER_KEY:
dedup_source = workflow.info().workflow_id
else:
dedup_source = f"{activity_id}:{trigger_key}"
run_id = str(uuid.uuid5(uuid.NAMESPACE_URL, dedup_source))
# ── 3. Apply declared bounded side-effects to the fixed selection ────
if any(
isinstance(source, dict)
and source.get("type") == "sbom-nexus"
and source.get("query") == "catch_up"
and (source.get("params") or {}).get("apply") is True
for source in defn.get("context_sources", [])
) and workflow.patched("activity-wp-0033-sbom-retry-boundary"):
context_patches: dict = await workflow.execute_activity(
apply_sbom_catchup,
{
"context_sources": defn.get("context_sources", []),
"context": context_snapshot,
"run_id": run_id,
},
start_to_close_timeout=_ACTIVITY_TIMEOUT,
heartbeat_timeout=timedelta(seconds=60),
retry_policy=_RETRY_POLICY,
)
for bind_key, patch in context_patches.items():
current = context_snapshot.get(bind_key)
if isinstance(current, dict) and isinstance(patch, dict):
current.update(patch)
await workflow.execute_activity(
persist_ops_evidence,
@ -127,7 +152,7 @@ class RunActivityWorkflow:
retry_policy=_RETRY_POLICY,
)
# ── 3. Evaluate rules ─────────────────────────────────────────────────
# ── 4. Evaluate rules ─────────────────────────────────────────────────
import json as _json
event_attrs: dict = {}
if event_envelope_json:
@ -162,7 +187,7 @@ class RunActivityWorkflow:
task_spec_dicts.extend(instruction_result.get("task_specs", []))
report_dicts.extend(instruction_result.get("reports", []))
# ── 4. Persist reports ────────────────────────────────────────────────
# ── 5. Persist reports ────────────────────────────────────────────────
if report_dicts:
await workflow.execute_activity(
persist_instruction_reports,
@ -177,7 +202,7 @@ class RunActivityWorkflow:
retry_policy=_RETRY_POLICY,
)
# ── 5. Log the run BEFORE emit ────────────────────────────────────────
# ── 6. Log the run BEFORE emit ────────────────────────────────────────
# ACTIVITY-WP-0021: emit_tasks sink failures used to abort the workflow
# before log_run, so failed Binky/SBOM fires left no activity_runs row
# and automation-status could not observe them. Always record the run;
@ -196,7 +221,7 @@ class RunActivityWorkflow:
retry_policy=_RETRY_POLICY,
)
# ── 6. Emit tasks (may fail independently of run audit) ───────────────
# ── 7. Emit tasks (may fail independently of run audit) ───────────────
if task_spec_dicts:
# Cron schedules pass trigger_key="scheduled" for *every* fire.
# ops_run idempotency is {def}:{source}:{triggering_event_id}, so