"""Package an explicit allowlist, never the working tree/.env/user assets wholesale.""" import argparse import hashlib import json import re import shutil import tarfile from pathlib import Path ROOT = Path(__file__).resolve().parents[2] def main(): parser = argparse.ArgumentParser() parser.add_argument("release") args = parser.parse_args() if not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9_.-]{0,63}", args.release): parser.error("invalid release") output = ROOT / "build/website-deployment/bundles" / args.release output.mkdir(parents=True, exist_ok=False) def copy(source, target): if source.is_symlink(): raise RuntimeError("symlinks not allowed in publish inputs") target.parent.mkdir(parents=True, exist_ok=True) shutil.copyfile(source, target) for source in (ROOT / "decision_server").rglob("*"): relative = source.relative_to(ROOT) if ( source.is_file() and "tests" not in relative.parts and "__pycache__" not in relative.parts and source.suffix in (".py", ".json", ".txt", ".md") ): copy(source, output / "app" / relative) for name in ( "lekiwi-agent-v1.schema.json", "lekiwi-language-task-v2.schema.json", "lekiwi-language-scene-v2.json", ): copy(ROOT / "contracts" / name, output / "app/contracts" / name) for source in (ROOT / "deploy/cadworld").iterdir(): if source.is_file(): copy(source, output / "deploy" / source.name) copy(ROOT / "deploy/cadworld/Dockerfile", output / "app/Dockerfile") copy(ROOT / "deploy/cadworld/.dockerignore", output / "app/.dockerignore") copy( ROOT / "deploy/cadworld/requirements.lock.txt", output / "app/deploy/cadworld/requirements.lock.txt", ) vendor = ROOT / "build/website-deployment/vendor" for source in [ vendor / "codex", vendor / "codex-origin.json", *sorted((vendor / "wheels").glob("*.whl")), ]: copy(source, output / "app/vendor" / source.relative_to(vendor)) for source in (ROOT / "website-dist").rglob("*"): if source.is_file(): copy(source, output / "static" / source.relative_to(ROOT / "website-dist")) if not (output / "static/index.html").exists() or (output / "static/tuning.html").exists(): raise RuntimeError("website production build required") manifest = { str(p.relative_to(output)): hashlib.sha256(p.read_bytes()).hexdigest() for p in sorted(output.rglob("*")) if p.is_file() } (output / "manifest.json").write_text( json.dumps({"release": args.release, "files": manifest}, indent=2) ) archive = output.with_suffix(".tar.gz") with tarfile.open(archive, "w:gz") as tar: for path in sorted(output.iterdir()): tar.add(path, arcname=path.name) print(str(archive)) print("sha256", hashlib.sha256(archive.read_bytes()).hexdigest()) if __name__ == "__main__": main()