60 lines
2.2 KiB
Python
Executable File
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())
|