Files
aios/scripts/verify_v2r1c6_release_source.py
T

70 lines
2.6 KiB
Python

from __future__ import annotations
import argparse
import hashlib
import io
import json
import subprocess
import tarfile
from pathlib import Path
from aios_release_controller.manifest import validate_source_manifest
def sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def archive_names(path: Path) -> set[str]:
raw = subprocess.check_output(["zstd", "-dc", str(path)])
with tarfile.open(fileobj=io.BytesIO(raw), mode="r:") as archive:
return {member.name for member in archive.getmembers()}
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--repo-root", type=Path, required=True)
parser.add_argument("--target-oid", required=True)
parser.add_argument("--base-oid", required=True)
parser.add_argument("--artifact", type=Path, required=True)
args = parser.parse_args()
repo = args.repo_root
head = subprocess.check_output(["git", "-C", str(repo), "rev-parse", "HEAD"], text=True).strip()
if head != args.target_oid:
raise SystemExit("target_oid_does_not_match_HEAD")
source = validate_source_manifest(repo / "release-manifests" / "V2R1C6.json", args.base_oid)
receipt = json.loads(next(args.artifact.parent.glob("*.manifest.json")).read_text(encoding="utf-8"))
if receipt["target_oid"] != args.target_oid or receipt["base_oid"] != args.base_oid:
raise SystemExit("receipt_binding_mismatch")
if receipt["artifact_sha256"] != sha256(args.artifact) or receipt["artifact_size"] != args.artifact.stat().st_size:
raise SystemExit("receipt_artifact_mismatch")
required = {
"payload/VERSION",
"payload/active-runtime/app/v2r1c6_privacy_tools.py",
"payload/deploy/aios-v2/systemd/aios-v2r1c6-production.service",
"payload/release-manifests/V2R1C6.json",
"payload/services/aios-release-controller/aios_release_controller/manifest.py",
"payload/BUILD-METADATA.json",
"payload/ARTIFACT-MANIFEST.json",
"payload/ROLLBACK-METADATA.json",
}
names = archive_names(args.artifact)
missing = sorted(required - names)
if missing:
raise SystemExit("artifact_members_missing:" + ",".join(missing))
print(json.dumps({
"status": "PASS",
"version": source["version"],
"target_oid": args.target_oid,
"base_oid": args.base_oid,
"artifact_sha256": sha256(args.artifact),
"production_deployed": False,
"tag_created": False,
"baseline_changed": False,
}, sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())