## Summary - merge successful same-repository PR CI through a trusted workflow-run verifier - dispatch exact main SHA validation after direct/final-train merges while keeping task-to-train free of duplicate CI - bind merge tickets, candidate proofs, replay recovery, Release proof v3, and ruleset validation to trusted run provenance - fail control-plane changes closed to trusted manual squash so PR-authored CI cannot prove itself ## Validation - 78 focused Python/workflow contract tests - build and GitHub Release static safety contracts - source syntax and Release shell contracts - actionlint for CI, Release, and protected merge workflows - git diff --check - independent specification and security/reliability reviews Co-authored-by: gd-ops <gd-ops@xmfunny.com>
139 lines
5.3 KiB
Python
Executable File
139 lines
5.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Select the trusted main validation run and source-proof artifact for a release."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import pathlib
|
|
import re
|
|
import stat
|
|
import sys
|
|
from typing import Any
|
|
|
|
|
|
COMMIT_PATTERN = re.compile(r"[0-9a-f]{40}")
|
|
REPOSITORY_PATTERN = re.compile(r"[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+")
|
|
WORKFLOW_PATH = ".github/workflows/ci.yml"
|
|
MAIN_WORKFLOW_EVENTS = {"push", "workflow_dispatch"}
|
|
|
|
|
|
def read_json_regular(path: pathlib.Path) -> dict[str, Any]:
|
|
descriptor = os.open(path, os.O_RDONLY | os.O_CLOEXEC | os.O_NOFOLLOW)
|
|
try:
|
|
metadata = os.fstat(descriptor)
|
|
if not stat.S_ISREG(metadata.st_mode) or metadata.st_size > 8 * 1024 * 1024:
|
|
raise ValueError("GitHub API input must be a bounded regular file")
|
|
with os.fdopen(descriptor, encoding="utf-8") as handle:
|
|
descriptor = -1
|
|
payload = json.load(handle)
|
|
finally:
|
|
if descriptor >= 0:
|
|
os.close(descriptor)
|
|
if not isinstance(payload, dict):
|
|
raise ValueError("GitHub API input must contain one JSON object")
|
|
return payload
|
|
|
|
|
|
def validate_identity(repository: str, commit: str) -> None:
|
|
if REPOSITORY_PATTERN.fullmatch(repository) is None:
|
|
raise ValueError("repository must be owner/name")
|
|
if COMMIT_PATTERN.fullmatch(commit) is None:
|
|
raise ValueError("commit must be a full lowercase Git commit")
|
|
|
|
|
|
def select_run(payload: dict[str, Any], repository: str, commit: str) -> dict[str, int]:
|
|
runs = payload.get("workflow_runs")
|
|
if not isinstance(runs, list):
|
|
raise ValueError("workflow run response is missing workflow_runs")
|
|
matches = []
|
|
for run in runs:
|
|
if not isinstance(run, dict):
|
|
continue
|
|
head_repository = run.get("head_repository")
|
|
head_name = head_repository.get("full_name") if isinstance(head_repository, dict) else None
|
|
if (
|
|
run.get("head_sha") == commit
|
|
and run.get("event") in MAIN_WORKFLOW_EVENTS
|
|
and run.get("head_branch") == "main"
|
|
and run.get("conclusion") == "success"
|
|
and run.get("path") == WORKFLOW_PATH
|
|
and head_name == repository
|
|
and isinstance(run.get("id"), int)
|
|
and isinstance(run.get("run_attempt"), int)
|
|
):
|
|
matches.append(run)
|
|
if not matches:
|
|
raise ValueError("no successful trusted main CI run exists for the release commit")
|
|
selected = max(matches, key=lambda value: (value["id"], value["run_attempt"]))
|
|
return {
|
|
"run_id": selected["id"],
|
|
"run_attempt": selected["run_attempt"],
|
|
"workflow_event": selected["event"],
|
|
}
|
|
|
|
|
|
def select_artifact(payload: dict[str, Any], run_id: int, artifact_name: str) -> dict[str, int | str]:
|
|
artifacts = payload.get("artifacts")
|
|
if not isinstance(artifacts, list):
|
|
raise ValueError("artifact response is missing artifacts")
|
|
matches = []
|
|
for artifact in artifacts:
|
|
if not isinstance(artifact, dict):
|
|
continue
|
|
workflow_run = artifact.get("workflow_run")
|
|
artifact_run_id = workflow_run.get("id") if isinstance(workflow_run, dict) else run_id
|
|
if (
|
|
artifact.get("name") == artifact_name
|
|
and artifact.get("expired") is False
|
|
and artifact_run_id == run_id
|
|
and isinstance(artifact.get("id"), int)
|
|
and isinstance(artifact.get("size_in_bytes"), int)
|
|
and 0 < artifact["size_in_bytes"] <= 1024 * 1024
|
|
):
|
|
matches.append(artifact)
|
|
if len(matches) != 1:
|
|
raise ValueError("trusted CI run must contain exactly one bounded source-proof artifact")
|
|
selected = matches[0]
|
|
return {
|
|
"artifact_id": selected["id"],
|
|
"artifact_name": artifact_name,
|
|
"size_in_bytes": selected["size_in_bytes"],
|
|
}
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser()
|
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
run_parser = subparsers.add_parser("run")
|
|
run_parser.add_argument("--runs-json", required=True, type=pathlib.Path)
|
|
run_parser.add_argument("--repository", required=True)
|
|
run_parser.add_argument("--commit", required=True)
|
|
artifact_parser = subparsers.add_parser("artifact")
|
|
artifact_parser.add_argument("--artifacts-json", required=True, type=pathlib.Path)
|
|
artifact_parser.add_argument("--run-id", required=True, type=int)
|
|
artifact_parser.add_argument("--artifact-name", required=True)
|
|
args = parser.parse_args()
|
|
try:
|
|
if args.command == "run":
|
|
validate_identity(args.repository, args.commit)
|
|
result = select_run(
|
|
read_json_regular(args.runs_json), args.repository, args.commit
|
|
)
|
|
else:
|
|
if args.run_id <= 0 or not args.artifact_name:
|
|
raise ValueError("run id and artifact name must be valid")
|
|
result = select_artifact(
|
|
read_json_regular(args.artifacts_json), args.run_id, args.artifact_name
|
|
)
|
|
print(json.dumps(result, sort_keys=True, separators=(",", ":")))
|
|
except (OSError, ValueError, json.JSONDecodeError) as error:
|
|
print(f"release source proof resolution error: {error}", file=sys.stderr)
|
|
return 1
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|