77 lines
2.4 KiB
Python
77 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Create deterministic evidence for a reviewed GuestOps image archive."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import re
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
def project_versions() -> tuple[str, str]:
|
|
props = (ROOT / "Directory.Build.props").read_text(encoding="utf-8")
|
|
match = re.search(r"<Version>([^<]+)</Version>", props)
|
|
if match is None:
|
|
raise ValueError("Directory.Build.props does not contain a Version element")
|
|
package = json.loads((ROOT / "web" / "package.json").read_text(encoding="utf-8"))
|
|
return match.group(1), str(package["version"])
|
|
|
|
|
|
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() -> None:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--artifact", required=True, type=Path)
|
|
parser.add_argument("--commit", required=True)
|
|
parser.add_argument("--api-image", required=True)
|
|
parser.add_argument("--api-id", required=True)
|
|
parser.add_argument("--worker-image", required=True)
|
|
parser.add_argument("--worker-id", required=True)
|
|
parser.add_argument("--output", required=True, type=Path)
|
|
args = parser.parse_args()
|
|
|
|
commit = args.commit.lower()
|
|
if re.fullmatch(r"[0-9a-f]{40}", commit) is None:
|
|
parser.error("--commit must be a full 40-character Git SHA")
|
|
if not args.artifact.is_file():
|
|
parser.error("--artifact must name an existing file")
|
|
|
|
dotnet_version, web_version = project_versions()
|
|
if dotnet_version != web_version:
|
|
parser.error(
|
|
f"release versions differ: .NET={dotnet_version}, web={web_version}"
|
|
)
|
|
|
|
record = {
|
|
"artifact": {
|
|
"name": args.artifact.name,
|
|
"sha256": sha256(args.artifact),
|
|
"size": args.artifact.stat().st_size,
|
|
},
|
|
"commit": commit,
|
|
"images": {
|
|
"api": {"id": args.api_id, "reference": args.api_image},
|
|
"worker": {"id": args.worker_id, "reference": args.worker_image},
|
|
},
|
|
"schemaVersion": 1,
|
|
"version": dotnet_version,
|
|
}
|
|
args.output.write_text(
|
|
json.dumps(record, indent=2, sort_keys=True) + "\n", encoding="utf-8"
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|