"""Build the source-owned static release and deterministic extension ZIP.""" from pathlib import Path import json import shutil import zipfile ROOT = Path(__file__).resolve().parent REPO = ROOT.parent WEB = ROOT / 'web' EXTENSION = REPO / 'extension' ASSETS = REPO / 'assets' ASSETS.mkdir(exist_ok=True) for name in ('app.js', 'signin.js', 'signin.html', 'install.html', 'update.html', 'update-extension.py'): shutil.copyfile(WEB / name, ASSETS / name) shutil.copyfile(WEB / 'app.js', REPO / 'app.js') shutil.copyfile(WEB / 'signin.html', REPO / 'signin') version = json.loads((EXTENSION / 'manifest.json').read_text())['version'] (ASSETS / 'version.json').write_text(json.dumps({'version': version}, separators=(',', ':')) + '\n') shutil.copyfile(EXTENSION / 'version.mjs', ASSETS / 'version.mjs') with zipfile.ZipFile(ASSETS / 'extension.zip', 'w', compression=zipfile.ZIP_DEFLATED) as archive: for path in sorted(EXTENSION.rglob('*')): if 'tests' not in path.relative_to(EXTENSION).parts and path.is_file() and path.suffix in {'.mjs', '.json', '.html', '.css', '.png'}: entry = zipfile.ZipInfo('persimmons-extension/' + path.relative_to(EXTENSION).as_posix(), (2026, 1, 1, 0, 0, 0)) entry.compress_type = zipfile.ZIP_DEFLATED entry.external_attr = 0o644 << 16 archive.writestr(entry, path.read_bytes())