CupOFMoCA / CupOFMoCA-PROTAC /scripts /verify_release.py
OkayBoboLi's picture
Add the PROTAC release
f12d3b3 verified
Raw History Blame Contribute Delete
1.98 kB
#!/usr/bin/env python3
"""Verify bundled PROTAC artifacts and portability-sensitive source files."""
from __future__ import annotations
import hashlib
import json
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
MANIFEST = ROOT / "docs" / "artifacts.json"
def sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as handle:
for block in iter(lambda: handle.read(8 * 1024 * 1024), b""):
digest.update(block)
return digest.hexdigest()
def main() -> int:
entries = json.loads(MANIFEST.read_text())
failures = 0
for entry in entries:
path = ROOT / entry["path"]
if not path.is_file():
print(f"MISSING {entry['path']}")
failures += 1
continue
size_ok = path.stat().st_size == entry["bytes"]
hash_ok = sha256(path) == entry["sha256"]
state = "OK" if size_ok and hash_ok else "FAILED"
print(f"{state:7} {entry['path']}")
failures += int(not (size_ok and hash_ok))
private_roots = tuple("/" + stem for stem in ("scratch/", "Users/", "home/"))
for sub in ("src", "scripts", "md"):
for path in (ROOT / sub).rglob("*.py"):
text = path.read_text(errors="replace")
if any(root in text for root in private_roots):
print(f"PRIVATE {path.relative_to(ROOT)}")
failures += 1
# Optional components are fetched, not redistributed; flag only if partially present.
for name, probe in (("degrademaster", "src/degrademaster/model.py"),
("propk", "src/propk/maplight.py")):
if not (ROOT / probe).is_file():
print(f"ABSENT {name} (optional; run scripts/fetch_third_party.py)")
print("Release verification passed." if not failures else f"Verification found {failures} problem(s).")
return 1 if failures else 0
if __name__ == "__main__":
raise SystemExit(main())