"""Offline artifact/provenance tests independent of generated repository output.""" import importlib.util import json from pathlib import Path import tempfile import unittest import zipfile SPEC = importlib.util.spec_from_file_location("package_release", Path(__file__).with_name("package_release.py")) PACKER = importlib.util.module_from_spec(SPEC) SPEC.loader.exec_module(PACKER) class PackagingTests(unittest.TestCase): def setUp(self): self.temp = tempfile.TemporaryDirectory() self.addCleanup(self.temp.cleanup) self.root = Path(self.temp.name) self.tag = "v28.0.0" self.commit = "a" * 40 theme = json.dumps({"name": "demo", "mode": "shared"}).encode() css = b"a { color:blue; }" self.write("themes/demo/theme.json", theme) self.write("themes/demo/theme.css", css) files = {"mail/base/head.tmpl": b"
footer
"} meta = {"theme": "demo", "mode": "shared", "gitea_tag": self.tag, "gitea_commit": self.commit, "sources": {"theme.json": PACKER.digest(theme), "theme.css": PACKER.digest(css)}, "files": {p: PACKER.digest(data) for p, data in files.items()}} for path, data in files.items(): self.write("build/themes/demo/" + path, data) self.write_json("build/themes/demo/build.json", meta) self.write_json("gitea.lock.json", {"tag": self.tag, "commit": self.commit, "files": {"LICENSE": PACKER.digest(b"MIT"), "options/locale/locale_en-US.json": PACKER.digest(b"{}")}}) self.write("build/upstream/LICENSE", b"MIT") manifest = {"upstream": self.tag, "upstream_commit": self.commit, "themes": ["demo"], "languages": ["en-US"], "registry": {"activate": {}}} self.write("preview/rendered.js", ("window.__MAIL_PREVIEW__ = " + json.dumps(manifest) + ";").encode()) self.write("preview/rendered/en-US.js", ('window.__MAIL_PREVIEW_DATA__["en-US"] = ' + json.dumps({"demo": {"activate": ""}}) + ";").encode()) for name in ["LICENSE", "README.md", "CONTRIBUTING.md", "COMPATIBILITY.md", "THIRD_PARTY_NOTICES.md", "docs/README.zh-CN.md", "docs/CONTRIBUTING.zh-CN.md", "preview/index.html", "docs/images/README.md"]: self.write(name, b"test") def write(self, name, data): path = self.root / name path.parent.mkdir(parents=True, exist_ok=True) path.write_bytes(data) def write_json(self, name, data): self.write(name, json.dumps(data).encode()) def test_packages_declared_outputs_only_and_never_overwrites(self): self.write("build/themes/stale/mail/stale.tmpl", b"stale") out = self.root / "artifacts" PACKER.package(self.root, self.tag, out) with zipfile.ZipFile(next(out.glob("*.zip"))) as archive: names = archive.namelist() self.assertTrue(any(name.endswith("themes/demo/mail/base/head.tmpl") for name in names)) self.assertFalse(any("stale" in name or "/build/" in name for name in names)) with self.assertRaises(ValueError): PACKER.package(self.root, self.tag, out) def test_refuses_stale_source_tampered_output_and_wrong_version(self): with self.assertRaises(ValueError): PACKER.collect(self.root, "v28.1.0") self.write("themes/demo/theme.css", b"changed") with self.assertRaisesRegex(ValueError, "Source changed"): PACKER.collect(self.root, self.tag) def test_refuses_missing_language_bundle(self): (self.root / "preview/rendered/en-US.js").unlink() with self.assertRaises(ValueError): PACKER.collect(self.root, self.tag) def test_refuses_modified_generated_files(self): self.write("build/themes/demo/mail/base/head.tmpl", b"modified") with self.assertRaisesRegex(ValueError, "checksum mismatch"): PACKER.collect(self.root, self.tag) if __name__ == "__main__": unittest.main()