From 6ba306fbf493c357216dffc34867c25b29a4672f Mon Sep 17 00:00:00 2001 From: eric8810 Date: Thu, 30 Jul 2026 18:42:20 +0800 Subject: [PATCH] =?UTF-8?q?fix(release):=20=E4=BA=91=E5=BE=84=E5=AF=BB?= =?UTF-8?q?=E8=88=9F=EF=BC=8C=E5=8F=8C=E7=AA=97=E5=90=8C=E6=B8=A1=20=C2=B7?= =?UTF-8?q?=20resolve=20Windows=20npx?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolve the platform-specific npx command shim before rebuilding the bundled PDFium addon. This keeps the release builder portable when Windows exposes npx as npx.cmd. Add a focused regression test that verifies the resolved shim is passed to the subprocess invocation. --- tests/python/test_pdfium_renderer.py | 40 ++++++++++++++++++++++++++++ tools/pdfium/prepare_renderer.py | 9 ++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/tests/python/test_pdfium_renderer.py b/tests/python/test_pdfium_renderer.py index 151af3b..b355412 100644 --- a/tests/python/test_pdfium_renderer.py +++ b/tests/python/test_pdfium_renderer.py @@ -10,6 +10,46 @@ class PdfiumRendererTests(unittest.TestCase): + def test_prepare_resolves_the_npx_platform_shim(self) -> None: + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + pdfium = root / "pdfium" + pdfium.mkdir() + cache = root / "cache" + resources = [root / "font.otf", root / "OFL.txt"] + for resource in resources: + resource.write_bytes(b"fixture") + + arguments = mock.Mock( + pdfium_dir=pdfium, + font_cache=cache, + download=True, + build=True, + ) + windows_npx = r"C:\hostedtoolcache\windows\node\npx.CMD" + + with ( + mock.patch.object( + prepare_renderer, + "verified_resources", + return_value=resources, + ), + mock.patch.object(prepare_renderer, "patch_source"), + mock.patch.object( + prepare_renderer, + "required_tool", + return_value=windows_npx, + ) as resolve_tool, + mock.patch.object( + prepare_renderer.subprocess, + "run", + ) as run, + ): + prepare_renderer.prepare(arguments) + + resolve_tool.assert_called_once_with("npx") + self.assertEqual(run.call_args_list[1].args[0][0], windows_npx) + def test_patch_source_is_pinned_and_idempotent(self) -> None: with tempfile.TemporaryDirectory() as temporary: pdfium = Path(temporary) diff --git a/tools/pdfium/prepare_renderer.py b/tools/pdfium/prepare_renderer.py index d720af0..c8d5152 100644 --- a/tools/pdfium/prepare_renderer.py +++ b/tools/pdfium/prepare_renderer.py @@ -22,6 +22,13 @@ ALLOWED_FONT_ORIGIN = "https://raw.githubusercontent.com" +def required_tool(name: str) -> str: + resolved = shutil.which(name) + if resolved is None: + raise RuntimeError(f"required build tool is missing: {name}") + return resolved + + def sha256(path: Path) -> str: digest = hashlib.sha256() with path.open("rb") as source: @@ -119,7 +126,7 @@ def prepare(arguments: argparse.Namespace) -> None: ["node", "scripts/download-pdfium.mjs"], cwd=pdfium_dir, check=True ) subprocess.run( - ["npx", "--yes", "node-gyp@11.4.2", "rebuild"], + [required_tool("npx"), "--yes", "node-gyp@11.4.2", "rebuild"], cwd=pdfium_dir, check=True, )