From 4f3e5fc60f4e450e92122a4c505dbcf28b075d2c Mon Sep 17 00:00:00 2001 From: plexerPK <160128888+plexerPK@users.noreply.github.com> Date: Sat, 24 Oct 2026 12:43:50 +0200 Subject: [PATCH 1/2] fix(tools): report invalid release zip archives as CLI errors --- tools/build_web.py | 2 +- tools/tests/test_web_release.py | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/tools/build_web.py b/tools/build_web.py index 8a5e555bf0..8bf9dd9af6 100644 --- a/tools/build_web.py +++ b/tools/build_web.py @@ -185,7 +185,7 @@ def main(argv=None): copy_sources(output) print(output) return 0 - except (OSError, ValueError) as error: + except (OSError, ValueError, zipfile.BadZipFile) as error: parser.error(str(error)) diff --git a/tools/tests/test_web_release.py b/tools/tests/test_web_release.py index d67632e117..781df3171e 100644 --- a/tools/tests/test_web_release.py +++ b/tools/tests/test_web_release.py @@ -212,6 +212,27 @@ class WebReleaseTests(unittest.TestCase): build_web.main() self.assertEqual((self.output / "native/relinker_wasm.mjs").read_bytes(), self.contents["native/relinker_wasm.mjs"]) + def test_invalid_zip_reports_cli_error_and_preserves_previous_site(self): + self.seed_previous() + previous = self.snapshot() + for name in ("web-v1.zip", "prx-windows-v1.zip", "prx-linux-v1.zip"): + with self.subTest(asset=name): + self.requests.clear() + original = self.responses[f"https://example.test/{name}"] + self.set_asset(name, original[:-22]) + errors = io.StringIO() + try: + with patch.object(build_web, "request", self.request), contextlib.redirect_stderr(errors): + with self.assertRaises(SystemExit) as error: + build_web.main(["--build", str(self.build), "--release"]) + self.assertEqual(error.exception.code, 2) + self.assertIn("error: File is not a zip file", errors.getvalue()) + self.assertNotIn("Traceback", errors.getvalue()) + self.assertEqual(self.snapshot(), previous) + self.assertEqual(list(self.build.glob(".web-release-*")), []) + finally: + self.set_asset(name, original) + def test_local_build_still_copies_sources_without_network(self): source = self.root / "source/demo/web" source.mkdir(parents=True) From c32942496d945a9558b3f3fce10be6193dcba8fe Mon Sep 17 00:00:00 2001 From: plexerPK <160128888+plexerPK@users.noreply.github.com> Date: Sat, 24 Oct 2026 19:03:00 +0200 Subject: [PATCH 2/2] fix(tools): name malformed release archives in CLI errors --- tools/build_web.py | 6 +++++- tools/tests/test_web_release.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/build_web.py b/tools/build_web.py index 8bf9dd9af6..9e141735b0 100644 --- a/tools/build_web.py +++ b/tools/build_web.py @@ -90,6 +90,8 @@ def publish_libraries(output, release=None): path = f"libraries/{platform}-{checksum}.zip" temporary.replace(output / path) manifest["platforms"][platform] = {"path": path, "size": size, "expandedBytes": expanded, "sha256": checksum} + except zipfile.BadZipFile as error: + raise ValueError(f"Invalid release archive {asset['name']}: {error}") from error finally: temporary.unlink(missing_ok=True) (output / "release.json").write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8") @@ -158,6 +160,8 @@ def publish_release(output): raise RuntimeError(f"Could not restore release output. Previous site is preserved at {previous}") from error raise published = True + except zipfile.BadZipFile as error: + raise ValueError(f"Invalid release archive {asset['name']}: {error}") from error finally: if published or not previous.exists(): shutil.rmtree(temporary) @@ -185,7 +189,7 @@ def main(argv=None): copy_sources(output) print(output) return 0 - except (OSError, ValueError, zipfile.BadZipFile) as error: + except (OSError, ValueError) as error: parser.error(str(error)) diff --git a/tools/tests/test_web_release.py b/tools/tests/test_web_release.py index 781df3171e..6675c59869 100644 --- a/tools/tests/test_web_release.py +++ b/tools/tests/test_web_release.py @@ -226,7 +226,7 @@ class WebReleaseTests(unittest.TestCase): with self.assertRaises(SystemExit) as error: build_web.main(["--build", str(self.build), "--release"]) self.assertEqual(error.exception.code, 2) - self.assertIn("error: File is not a zip file", errors.getvalue()) + self.assertIn(f"error: Invalid release archive {name}: File is not a zip file", errors.getvalue()) self.assertNotIn("Traceback", errors.getvalue()) self.assertEqual(self.snapshot(), previous) self.assertEqual(list(self.build.glob(".web-release-*")), [])