Files
maze32/scripts/verify_web_assets.py
T

60 lines
2.2 KiB
Python
Executable File

#!/usr/bin/env python3
"""Verify deterministic web generation and the checked-in generated assets."""
from __future__ import annotations
import gzip
import hashlib
import tempfile
from pathlib import Path
from generate_web_assets import generate_assets
PROJECT_DIRECTORY = Path(__file__).resolve().parent.parent
def tree_digest(directory: Path) -> str:
digest = hashlib.sha256()
for path in sorted(item for item in directory.rglob("*") if item.is_file()):
digest.update(path.relative_to(directory).as_posix().encode("utf-8"))
digest.update(b"\0")
digest.update(path.read_bytes())
return digest.hexdigest()
def main() -> int:
source_directory = PROJECT_DIRECTORY / "web"
checked_in_directory = PROJECT_DIRECTORY / "data"
with tempfile.TemporaryDirectory(prefix="maze32-assets-") as temporary:
temporary_directory = Path(temporary)
first = temporary_directory / "first"
second = temporary_directory / "second"
generate_assets(source_directory, first)
generate_assets(source_directory, second)
first_digest = tree_digest(first)
second_digest = tree_digest(second)
checked_in_digest = tree_digest(checked_in_directory)
if first_digest != second_digest:
raise AssertionError("Repeated web-asset generation produced different output")
if first_digest != checked_in_digest:
raise AssertionError("Generated web assets are stale; regenerate the data directory")
index_source = (source_directory / "index.html").read_bytes()
index_compressed = (first / "index.html.gz").read_bytes()
if gzip.decompress(index_compressed) != index_source:
raise AssertionError("Compressed index does not reproduce its source")
provision_source = (source_directory / "provision.html").read_bytes()
provision_compressed = (first / "provision.html.gz").read_bytes()
if gzip.decompress(provision_compressed) != provision_source:
raise AssertionError("Compressed provisioning page does not reproduce its source")
print(f"web asset reproducibility: PASS ({first_digest})")
return 0
if __name__ == "__main__":
raise SystemExit(main())