This repository has been archived on 2026-11-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
platform-ci/platform_ci/reporting.py
forge-recoveryandClaude Sonnet 5.5 70eb3ee0ab
KofTwentyTwo/ci-policy: ci / fork-guard (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / go-0 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / go-nix-1 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / gradle-2 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / gradle-3 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / java-docker-4 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / java-maven-5 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / manifests-6 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / nix-7 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / node-8 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / python-9 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / rust-10 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / rust-11 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / rust-12 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / source-config-13 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / source-config-14 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / image-build-0 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / image-build-1 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / image-build-2 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / image-build-3 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / image-build-4 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / image-build-5 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / image-build-6 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / image-build-7 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / not-enrolled (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / content-validate-0 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / standards-0 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / node-matrix-0 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / source-config-15 (pull_request) Blocked by required conditions
KofTwentyTwo/ci-policy: Shared source and config CI / verify (pull_request) Blocked by required conditions
KofTwentyTwo/ci-policy: Shared source and config CI / secrets (pull_request) Blocked by required conditions
KofTwentyTwo/ci-policy: Shared source and config CI / gate (pull_request) Waiting for needed jobs
KofTwentyTwo/ci-policy: ci / ci-result (pull_request) Waiting for needed jobs
KofTwentyTwo/ci-policy: native / fork-deny (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-macos-0 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-macos-1 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-macos-2 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-macos-3 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-windows-4 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-windows-5 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-windows-6 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-windows-7 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / dotnet-8 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / dotnet-9 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / dotnet-10 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / dotnet-11 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-12 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-13 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-14 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-15 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-16 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-17 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-18 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-19 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / native-result (pull_request) Canceled after 4s
feat(ci): advance shared pipeline capabilities
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-05 04:36:22 +00:00

94 lines
6.2 KiB
Python

"""Render the final result: expected work against actual results, with reuse and delivery stated honestly."""
from dataclasses import dataclass
from platform_ci.build_tools import CONTAINER_EXECUTION, DOCKER_POOL_EXECUTION, HOST_EXECUTION, POOL_EXECUTION
from platform_ci.plan import Plan, has_execution
from platform_ci.reuse_evidence import validate_reuse_evidence
@dataclass(frozen=True)
class ReuseReport:
"""What the reuse step reported: the evidence JSON (empty when nothing was reused) and its one-line note."""
evidence: str = ""
note: str = ""
def render_report(plan: Plan, verification_result: str, secrets_result: str, native_verification_result: str = "skipped", reuse: ReuseReport = ReuseReport(), pool_verification_result: str = "skipped", docker_pool_verification_result: str = "skipped") -> tuple[str, bool]: # noqa: B008, PLR0913, PLR0917 - a frozen default
"""Return the report text and whether the run as a whole passed.
Requested verification and the once-per-run secret scan must both end `success`; a skipped, failed or cancelled job
fails the run, so a missing security success can never pass. Verification has one job per execution kind: the
container job must succeed when the plan has standard container targets, the pool job when it has profile-pool targets, and the
native host job when it has host targets. A kind with no targets must have been skipped. Unrequested work must leave every job `skipped`: the run
then passes only as "not verified", never as tests passed or secrets scanned, and any other result is inconsistent and fails.
When the run reused tested bytes instead of building, both verification jobs must have skipped AND the reuse evidence must be
valid for exactly this plan; otherwise the run fails. Reuse replaces only the redundant rebuild: the secret scan and preparation
are new required validation of this exact revision and must still succeed.
"""
verification = plan["verification"]
expected = [target["name"] for target in plan["targets"]]
required = verification["required"]
reused = bool(reuse.evidence)
evidence_problems = validate_reuse_evidence(plan, reuse.evidence) if reused else []
container_wanted = "success" if required and not reused and has_execution(plan, CONTAINER_EXECUTION) else "skipped"
pool_wanted = "success" if required and not reused and has_execution(plan, POOL_EXECUTION) else "skipped"
native_wanted = "success" if required and not reused and has_execution(plan, HOST_EXECUTION) else "skipped"
wanted = "success" if required else "skipped"
verified = verification_result == container_wanted
native_verified = native_verification_result == native_wanted
docker_pool_wanted = "success" if required and not reused and has_execution(plan, DOCKER_POOL_EXECUTION) else "skipped"
pool_verified = pool_verification_result == pool_wanted and docker_pool_verification_result == docker_pool_wanted
scanned = secrets_result == wanted
passed = verified and native_verified and pool_verified and scanned and not evidence_problems
delivery = plan["delivery"]
eligible = ", ".join(delivery["eligible_channels"]) or "none"
publications_requested = ", ".join(f"{publication['name']} ({publication['format']} to {publication['destination']} on {', '.join(publication['channels'])})" for publication in delivery["publications"]) or "none"
if reused:
requested = f"REUSED, not rebuilt ({verification['reason']})"
checks = f"Reused targets: {', '.join(expected)}; secret scan of the exact source history ran as new required validation"
outcome = "passed (tested bytes reused after independent verification; no compile, test or package ran)" if passed else f"FAILED ({_failed_reuse(verified and pool_verified, native_verified, scanned, evidence_problems)})"
elif required:
requested = f"required once ({verification['reason']})"
checks = f"Expected checks: {', '.join(expected) or 'none'}; secret scan of the exact source history"
outcome = "passed" if passed else f"FAILED ({_failed_checks(verified, native_verified, pool_verified, scanned)} did not succeed)"
else:
requested = f"NOT REQUESTED by configuration ({verification['reason']})"
checks = "Expected checks: none requested; no build, tests or secret scan ran and nothing was verified"
outcome = "NOT VERIFIED (work not requested by configuration; this is not a test pass or a secret scan pass)" if passed else "FAILED (verification or the secret scan ran or ended unexpectedly although it was not requested)"
lines = [
f"Source revision: {plan['source_revision']}",
f"Platform revision: {plan['platform_revision']}",
f"Event: {plan['event']}",
f"Verification: {requested}",
checks,
f"Verification result: {verification_result}",
f"Pool verification result: {pool_verification_result}",
f"Docker pool verification result: {docker_pool_verification_result}",
f"Native host verification result: {native_verification_result}",
f"Secret scan result: {secrets_result}",
]
if reuse.note:
lines.append(f"Reuse: {reuse.note}")
lines += [
f"Delivery: NOT PERFORMED BY THIS WORKFLOW. Channels eligible by configuration: {eligible}. Publications requested of the trusted publisher: {publications_requested}. {delivery['note']}",
f"Result: {outcome}",
]
return "\n".join(lines) + "\n", passed
def _failed_checks(verified: bool, native_verified: bool, pool_verified: bool, scanned: bool) -> str:
"""Name which required results were not as expected."""
return " and ".join(name for name, ok in (("verification", verified), ("native verification", native_verified), ("pool verification", pool_verified), ("secret scan", scanned)) if not ok)
def _failed_reuse(verified: bool, native_verified: bool, scanned: bool, evidence_problems: list[str]) -> str:
"""Name what made a reuse run fail: a verification job that ran anyway, a failed new validation, or evidence that does not hold."""
reasons = [f"{name} was expected to skip but did not" for name, ok in (("verification", verified), ("native verification", native_verified)) if not ok]
if not scanned:
reasons.append("the secret scan did not succeed")
reasons += [f"reuse evidence: {problem}" for problem in evidence_problems]
return "; ".join(reasons)