Repository navigation
fix(cli): the browser download unpacks on machines without an unzip command - #5433
Conversation
Edit accuracy: accurate 2061 (base branch 2061), smooth 1533 of thoseThe gate passes. Quarantined, measured but not gated (0) |
terencecho
left a comment
There was a problem hiding this comment.
Source-level review of 7053ada00cca2fdc2ada74db97e3596eab449c99. Effective merge-base is f2b81b241516531c09ee90da6472beda3d6b4d46; the API main-tip base is faa4913c9ef791733837eae4de1a579f2049b251. The reviewed four-file diff has Git/API path and blob parity and no removals.
Strengths: packages/cli/package.json:51 adds yauzl ^3.4.0 as a regular production dependency alongside @puppeteer/browsers, not a root/dev-only or optional dependency. The exact locked browsers 3.2.2 accepts that optional-peer range. packages/cli/tsup.config.ts:39–43 keeps the browser library external, leaving its dynamic yauzl import to runtime dependency resolution. The name-only publishing rewrite retains CLI dependencies (.github/workflows/publish.yml:165–179, independently source-audited); this is structurally supported for the published CLI, not only workspace hoisting. The lock delta adds only the CLI importer row, yauzl 3.4.0 and pend 1.2.0. The Fallow exception correctly documents the indirect import (.fallowrc.jsonc:429–430).
The actual manager download path calls the upstream headless-shell installer. In the inspected browsers 3.2.2 extractor, missing Unix unzip maps to ArchiverUnavailableError and reaches yauzl; other native extraction errors do not generally trigger that fallback. No manager production-code change remains in the net diff.
Nonblocking evidence limits: packages/cli/src/browser/unzipFallback.test.ts:18–48 calls the real upstream installer against a synthetic local ZIP/base URL with PATH hidden, rather than mocking extraction. Its assertion covers executable-path existence, not executable mode, browser launch, a real vendor archive or a packed clean consumer. Windows is deliberately skipped because its first extractor uses absolute tar.exe; that skip is not Windows runtime coverage. I source-read this test but did not run its server or installer.
The disclosed corrupt-ZIP retry limitation is corroborated: browsers 3.2.2 lib/install.js:110–123 aggregates provider messages without retaining the extraction cause, so the unchanged classifier (packages/cli/src/browser/manager.ts:724–754) cannot recognize that yauzl failure. Archive cleanup (lib/install.js:260–263) and staging cleanup (manager.ts:849–852) remain source-present for a subsequent fresh attempt. This is not presented as a newly introduced blocker. A CLI-only dependency also does not certify standalone engine/producer downloads.
Coverage / execution: I directly read the complete CLI manifest, test, Fallow config, tsup config, manager and exact existing browser-library manifest/extractor, plus the scoped diff/relevant lock entries. Two completed code passes traced packaging/publishing, real render/check consumers, platform/error routes and test setup. One pass literally read all four changed files; the other read three end-to-end and fully parsed/recursively compared the lockfile rather than manually reading every unchanged entry. Broader caller/source coverage and passing built-in-only inert metadata/lock checks are delegated evidence, not my test execution. Fully paginated history has no reviews or inline findings, only automated edit-accuracy telemetry. I did not perform a fresh dependency/packed-consumer install, extraction, browser/native/vendor execution, stock tests/build/pack, CI trigger, source change or direct merge; the two assigned direct code passes report the same operational limits. Author test counts are not my execution.
Verdict: APPROVE
Reasoning: no verified newly introduced correctness or packaging blocker survived the source and adversarial passes. The regular CLI dependency satisfies the actual external library's fallback contract and survives publishing; runtime extraction and clean-install success were not independently demonstrated.
— tai
What changes for the user
On a Linux machine without the
unzipcommand (a fresh WSL Ubuntu, slim containers),hyperframes checkandrenderno longer fail withFailed to download chrome-headless-shell: Extraction failed: no zip archiver is available. The managed browser download now unpacks without any system tool.Root cause
The CLI downloads chrome-headless-shell through
@puppeteer/browsers. On Linux and macOS it unzips by running the systemunzip. When that is missing, its only fallback is theyauzlpackage, which@puppeteer/browsersdeclares as an optional peer dependency. The CLI never installed it, so with nounzipboth paths failed and the download stopped.Fix
yauzlis now a dependency of the CLI, so@puppeteer/browsersfinds its fallback unzipper. No CLI code changes: the library already triesunzipfirst andyauzlsecond.yauzlis not bundled into the CLI tarball (it is only loaded by@puppeteer/browsersat runtime), so the CLI's package size budget does not change.Also
yauzlis listed in the FallowignoreDependencies, next todebug: no CLI code imports it;@puppeteer/browsersloads it at runtime.Verification
unzipFallback.test.tsruns the real@puppeteer/browsersinstall()against a local server serving a chrome-headless-shell-shaped zip, withPATHpointing at an empty directory so nounzipis found. It checks the browser executable is unpacked. Skipped on Windows, where the library unzips withtar.exeby absolute path.yauzl, the test fails with the reported error (Extraction failed: no zip archiver is available); with it, it passes on Linux.Known limits
yauzlpath a corrupt download is not re-downloaded automatically:@puppeteer/browsersreportsExtraction failed: <archive path>and drops the zip error when it combines provider failures, so the CLI cannot tell a corrupt archive from other unzip failures. Re-running the command downloads again. Upstream note: in@puppeteer/browsers3.2.x,install()builds itsAll providers failederror from each provider error'smessageonly; keeping each error as the combined error'scausewould let callers detect a corrupt archive on this path.puppeteer's browser downloader, which still has noyauzloutside this repo. The publishedhyperframesCLI is covered.Why this PR is small
It is a one-dependency fix with its regression tests; the lockfile change adds only
yauzlandpend.