fix!: replace extract-zip with OS tar.exe or unzip (#14960)

This commit is contained in:
Alex Rudenko
2026-05-11 13:21:51 +02:00
committed by GitHub
parent cb288aca98
commit f1ecfb5cf2
5 changed files with 92 additions and 120 deletions
+1
View File
@@ -45,6 +45,7 @@ jobs:
- '.github/workflows/ci.yml'
- 'packages/browsers/src/install.ts'
- 'packages/browsers/src/browser-data/firefox.ts'
- 'packages/browsers/src/fileUtil.ts'
- 'packages/puppeteer/**'
- 'packages/puppeteer-core/**'
- 'packages/testserver/**'
+1
View File
@@ -14,6 +14,7 @@
- Required system packages https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/linux/debian/dist_package_versions.json
- [openSUSE/Fedora Linux](https://support.google.com/chrome/a/answer/7100626?hl=en#:~:text=10.15%20or%20later-,Linux,-To%20use%20Chrome), with x64 architecture
- Required system packages https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/linux/rpm/dist_package_provides.json
- `tar.exe` on Windows and `unzip` on MacOS/Linux for unpacking Chrome for Testing binaries.
- Firefox browser system requirements:
- https://www.mozilla.org/en-US/firefox/system-requirements/
+55 -116
View File
@@ -4378,7 +4378,7 @@
"version": "22.13.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz",
"integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==",
"devOptional": true,
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.20.0"
@@ -4388,7 +4388,7 @@
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
"devOptional": true,
"dev": true,
"license": "MIT"
},
"node_modules/@types/semver": {
@@ -31653,7 +31653,6 @@
"license": "Apache-2.0",
"dependencies": {
"debug": "^4.4.3",
"extract-zip": "^2.0.1",
"progress": "^2.0.3",
"proxy-agent": "^6.5.0",
"semver": "^7.7.4",
@@ -31772,119 +31771,6 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"packages/browsers/node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
"license": "BSD-2-Clause",
"dependencies": {
"debug": "^4.1.1",
"get-stream": "^5.1.0",
"yauzl": "^2.10.0"
},
"bin": {
"extract-zip": "cli.js"
},
"engines": {
"node": ">= 10.17.0"
},
"optionalDependencies": {
"@types/yauzl": "^2.9.1"
}
},
"packages/browsers/node_modules/extract-zip/node_modules/@types/yauzl": {
"version": "2.10.3",
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
"integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
"license": "MIT",
"optional": true,
"dependencies": {
"@types/node": "*"
}
},
"packages/browsers/node_modules/extract-zip/node_modules/get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"license": "MIT",
"dependencies": {
"pump": "^3.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"packages/browsers/node_modules/extract-zip/node_modules/get-stream/node_modules/pump": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
"integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
"license": "MIT",
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"packages/browsers/node_modules/extract-zip/node_modules/get-stream/node_modules/pump/node_modules/end-of-stream": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
"license": "MIT",
"dependencies": {
"once": "^1.4.0"
}
},
"packages/browsers/node_modules/extract-zip/node_modules/get-stream/node_modules/pump/node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"license": "ISC",
"dependencies": {
"wrappy": "1"
}
},
"packages/browsers/node_modules/extract-zip/node_modules/get-stream/node_modules/pump/node_modules/once/node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
},
"packages/browsers/node_modules/extract-zip/node_modules/yauzl": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
"license": "MIT",
"dependencies": {
"buffer-crc32": "~0.2.3",
"fd-slicer": "~1.1.0"
}
},
"packages/browsers/node_modules/extract-zip/node_modules/yauzl/node_modules/buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
"license": "MIT",
"engines": {
"node": "*"
}
},
"packages/browsers/node_modules/extract-zip/node_modules/yauzl/node_modules/fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
"license": "MIT",
"dependencies": {
"pend": "~1.2.0"
}
},
"packages/browsers/node_modules/extract-zip/node_modules/yauzl/node_modules/fd-slicer/node_modules/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
"license": "MIT"
},
"packages/browsers/node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
@@ -32757,6 +32643,59 @@
}
}
},
"packages/ng-schematics/node_modules/@angular-devkit/core/node_modules/ajv-formats/node_modules/ajv": {
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"packages/ng-schematics/node_modules/@angular-devkit/core/node_modules/ajv-formats/node_modules/ajv/node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"license": "MIT"
},
"packages/ng-schematics/node_modules/@angular-devkit/core/node_modules/ajv-formats/node_modules/ajv/node_modules/fast-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz",
"integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "BSD-3-Clause"
},
"packages/ng-schematics/node_modules/@angular-devkit/core/node_modules/ajv-formats/node_modules/ajv/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"license": "MIT"
},
"packages/ng-schematics/node_modules/@angular-devkit/core/node_modules/ajv-formats/node_modules/ajv/node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"packages/ng-schematics/node_modules/@angular-devkit/core/node_modules/ajv/node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-1
View File
@@ -108,7 +108,6 @@
],
"dependencies": {
"debug": "^4.4.3",
"extract-zip": "^2.0.1",
"progress": "^2.0.3",
"proxy-agent": "^6.5.0",
"tar-fs": "^3.1.1",
+35 -3
View File
@@ -5,15 +5,17 @@
*/
import type {ChildProcessByStdio} from 'node:child_process';
import {spawnSync, spawn} from 'node:child_process';
import {spawnSync, spawn, execFile} from 'node:child_process';
import {createReadStream} from 'node:fs';
import {mkdir, readdir} from 'node:fs/promises';
import * as path from 'node:path';
import type {Readable, Transform, Writable} from 'node:stream';
import {Stream} from 'node:stream';
import {promisify} from 'node:util';
import debug from 'debug';
const execFileAsync = promisify(execFile);
const debugFileUtil = debug('puppeteer:browsers:fileUtil');
/**
@@ -27,8 +29,8 @@ export async function unpackArchive(
folderPath = path.resolve(process.cwd(), folderPath);
}
if (archivePath.endsWith('.zip')) {
const extractZip = await import('extract-zip');
await extractZip.default(archivePath, {dir: folderPath});
await mkdir(folderPath, {recursive: true});
await extractZip(archivePath, folderPath);
} else if (archivePath.endsWith('.tar.bz2')) {
await extractTar(archivePath, folderPath, 'bzip2');
} else if (archivePath.endsWith('.dmg')) {
@@ -181,3 +183,33 @@ async function installDMG(dmgPath: string, folderPath: string): Promise<void> {
spawnSync('hdiutil', ['detach', mountPath, '-quiet']);
}
}
/**
* @internal
*/
async function extractZip(
archivePath: string,
folderPath: string,
): Promise<void> {
try {
if (process.platform === 'win32') {
// -x: extract files
// -f: specify the archive file
// -C: extract to the specified directory
await execFileAsync('tar.exe', ['-xf', archivePath, '-C', folderPath]);
} else {
// -o: overwrite existing files without prompting
// -d: extract files into the specified directory
await execFileAsync('unzip', ['-o', archivePath, '-d', folderPath]);
}
} catch (error: any) {
if (error?.code === 'ENOENT') {
throw new Error(
`Extraction failed: Required native binary ('tar.exe' or 'unzip') was not found in the system PATH.`,
);
}
throw new Error(
`Extraction failed: ${error?.stderr?.toString() || error?.message}`,
);
}
}