#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-3.0-or-later """Generate a deterministic manifest for a locally built, unexecuted artifact.""" from __future__ import annotations import argparse import hashlib import json from pathlib import Path SDK_COMMIT = "d2e2e585740362976a39fdd5ccf390f199a7bc37" SDL_COMMIT = "0baf4ac49382b537ba449901b5b6d0d189bb1fbb" def sha256(path: Path) -> str: digest = hashlib.sha256() with path.open("rb") as stream: for chunk in iter(lambda: stream.read(1024 * 1024), b""): digest.update(chunk) return digest.hexdigest() def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--artifact", type=Path, required=True) parser.add_argument("--output", type=Path, required=True) parser.add_argument("--id", required=True) parser.add_argument("--version", required=True) parser.add_argument("--source-repository", required=True) parser.add_argument("--source-commit", required=True) parser.add_argument("--target", required=True) parser.add_argument("--firmware", default="NONE") parser.add_argument("--profile", required=True) parser.add_argument("--execution-eligible", action="store_true") parser.add_argument("--with-sdl", action="store_true") parser.add_argument("--note", action="append", default=[]) args = parser.parse_args() artifact = args.artifact.resolve(strict=True) if not artifact.is_file() or artifact.stat().st_size == 0: raise SystemExit("artifact must be a non-empty regular file") if len(args.source_commit) != 40 or any( character not in "0123456789abcdef" for character in args.source_commit ): raise SystemExit("source commit must be a lowercase 40-character SHA-1") toolchain = { "ps5_payload_sdk_release": "v0.41", "ps5_payload_sdk_commit": SDK_COMMIT, } if args.with_sdl: toolchain["sdl_commit"] = SDL_COMMIT document = { "schema_version": 1, "artifact": { "id": args.id, "version": args.version, "filename": artifact.name, "size": artifact.stat().st_size, "sha256": sha256(artifact), "target": args.target, }, "source": { "repository": args.source_repository, "commit": args.source_commit, "dirty": False, }, "toolchain": toolchain, "firmware_gate": { "embedded_identifier": args.firmware, "allowlisted": args.firmware != "NONE", }, "execution": { "execution_eligible": args.execution_eligible, "authorized": False, "transferred": False, "executed": False, }, "safety": { "profile": args.profile, "direct_gnm_imports": 0, "notes": args.note, }, } args.output.parent.mkdir(parents=True, exist_ok=True) args.output.write_text( json.dumps(document, indent=2, sort_keys=True) + "\n", encoding="utf-8" ) return 0 if __name__ == "__main__": raise SystemExit(main())