chore: test server for browsers (#9974)

Co-authored-by: Nikolay Vitkov <34244704+Lightning00Blade@users.noreply.github.com>
This commit is contained in:
Alex Rudenko 2023-04-05 16:18:25 +02:00 committed by GitHub
parent 0b2d988cc1
commit fa93e4ebdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 256 additions and 18 deletions

View File

@ -399,6 +399,11 @@ jobs:
run: npm ci run: npm ci
env: env:
PUPPETEER_SKIP_DOWNLOAD: true PUPPETEER_SKIP_DOWNLOAD: true
- name: Setup cache for browser binaries
uses: actions/cache@v3
with:
path: packages/browsers/test/cache
key: browsers-${{ hashFiles('packages/browsers/tools/downloadTestBrowsers.mjs') }}-${{ hashFiles('packages/browsers/test/src/versions.ts') }}
- name: Run tests - name: Run tests
run: npm run test --workspace @puppeteer/browsers run: npm run test --workspace @puppeteer/browsers

1
packages/browsers/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
test/cache

View File

@ -3,4 +3,5 @@ module.exports = {
spec: 'test/build/**/*.spec.js', spec: 'test/build/**/*.spec.js',
exit: !!process.env.CI, exit: !!process.env.CI,
reporter: 'spec', reporter: 'spec',
timeout: 10_000,
}; };

View File

@ -22,13 +22,27 @@
}, },
"wireit": { "wireit": {
"build": { "build": {
"command": "tsc -b && chmod a+x lib/cjs/main-cli.js lib/esm/main-cli.js && echo '{\"type\":\"module\"}' > lib/esm/package.json", "command": "tsc -b && chmod a+x lib/cjs/main-cli.js lib/esm/main-cli.js",
"files": [ "files": [
"src/**/*.ts", "src/**/*.ts",
"tsconfig.json" "tsconfig.json"
], ],
"clean": "if-file-deleted",
"output": [ "output": [
"lib/**" "lib/**",
"!lib/esm/package.json"
],
"dependencies": [
"generate:package-json"
]
},
"generate:package-json": {
"command": "tsx ../../tools/generate_module_package_json.ts lib/esm/package.json",
"files": [
"../../tools/generate_module_package_json.ts"
],
"output": [
"lib/esm/package.json"
] ]
}, },
"build:test": { "build:test": {
@ -41,11 +55,12 @@
"test/build/**" "test/build/**"
], ],
"dependencies": [ "dependencies": [
"build" "build",
"../testserver:build"
] ]
}, },
"test": { "test": {
"command": "mocha", "command": "node tools/downloadTestBrowsers.mjs && mocha",
"files": [ "files": [
".mocharc.cjs" ".mocharc.cjs"
], ],

View File

@ -44,6 +44,7 @@ type InstallArgs = {
}; };
path?: string; path?: string;
platform?: BrowserPlatform; platform?: BrowserPlatform;
baseUrl?: string;
}; };
type LaunchArgs = { type LaunchArgs = {
@ -116,6 +117,10 @@ export class CLI {
this.#defineBrowserParameter(yargs); this.#defineBrowserParameter(yargs);
this.#definePlatformParameter(yargs); this.#definePlatformParameter(yargs);
this.#definePathParameter(yargs); this.#definePathParameter(yargs);
yargs.option('base-url', {
type: 'string',
desc: 'Base URL to download from',
});
yargs.example( yargs.example(
'$0 install chrome', '$0 install chrome',
'Install the latest available build of the Chrome browser.' 'Install the latest available build of the Chrome browser.'
@ -161,6 +166,7 @@ export class CLI {
args.browser.name, args.browser.name,
args.browser.buildId args.browser.buildId
), ),
baseUrl: args.baseUrl,
}); });
console.log( console.log(
`${args.browser.name}@${ `${args.browser.name}@${

View File

@ -31,6 +31,12 @@ export const downloadUrls = {
[Browser.FIREFOX]: firefox.resolveDownloadUrl, [Browser.FIREFOX]: firefox.resolveDownloadUrl,
}; };
export const downloadPaths = {
[Browser.CHROME]: chrome.resolveDownloadPath,
[Browser.CHROMIUM]: chromium.resolveDownloadPath,
[Browser.FIREFOX]: firefox.resolveDownloadPath,
};
export const executablePathByBrowser = { export const executablePathByBrowser = {
[Browser.CHROME]: chrome.relativeExecutablePath, [Browser.CHROME]: chrome.relativeExecutablePath,
[Browser.CHROMIUM]: chromium.relativeExecutablePath, [Browser.CHROMIUM]: chromium.relativeExecutablePath,

View File

@ -55,9 +55,14 @@ export function resolveDownloadUrl(
buildId: string, buildId: string,
baseUrl = 'https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing' baseUrl = 'https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing'
): string { ): string {
return `${baseUrl}/${buildId}/${folder(platform)}/chrome-${folder( return `${baseUrl}/${resolveDownloadPath(platform, buildId).join('/')}`;
platform }
)}.zip`;
export function resolveDownloadPath(
platform: BrowserPlatform,
buildId: string
): string[] {
return [buildId, folder(platform), `chrome-${folder(platform)}.zip`];
} }
export function relativeExecutablePath( export function relativeExecutablePath(

View File

@ -56,10 +56,14 @@ export function resolveDownloadUrl(
buildId: string, buildId: string,
baseUrl = 'https://storage.googleapis.com/chromium-browser-snapshots' baseUrl = 'https://storage.googleapis.com/chromium-browser-snapshots'
): string { ): string {
return `${baseUrl}/${folder(platform)}/${buildId}/${archive( return `${baseUrl}/${resolveDownloadPath(platform, buildId).join('/')}`;
platform, }
buildId
)}.zip`; export function resolveDownloadPath(
platform: BrowserPlatform,
buildId: string
): string[] {
return [folder(platform), buildId, `${archive(platform, buildId)}.zip`];
} }
export function relativeExecutablePath( export function relativeExecutablePath(

View File

@ -39,7 +39,14 @@ export function resolveDownloadUrl(
buildId: string, buildId: string,
baseUrl = 'https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central' baseUrl = 'https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central'
): string { ): string {
return `${baseUrl}/${archive(platform, buildId)}`; return `${baseUrl}/${resolveDownloadPath(platform, buildId).join('/')}`;
}
export function resolveDownloadPath(
platform: BrowserPlatform,
buildId: string
): string[] {
return [archive(platform, buildId)];
} }
export function relativeExecutablePath( export function relativeExecutablePath(

View File

@ -73,6 +73,12 @@ export interface Options {
* *
*/ */
baseUrl?: string; baseUrl?: string;
/**
* Whether to unpack and install browser archives.
*
* @defaultValue `true`
*/
install?: boolean;
} }
export type InstalledBrowser = { export type InstalledBrowser = {
@ -84,6 +90,7 @@ export type InstalledBrowser = {
export async function fetch(options: Options): Promise<InstalledBrowser> { export async function fetch(options: Options): Promise<InstalledBrowser> {
options.platform ??= detectBrowserPlatform(); options.platform ??= detectBrowserPlatform();
options.install ??= true;
if (!options.platform) { if (!options.platform) {
throw new Error( throw new Error(
`Cannot download a binary for the provided platform: ${os.platform()} (${os.arch()})` `Cannot download a binary for the provided platform: ${os.platform()} (${os.arch()})`
@ -103,6 +110,26 @@ export async function fetch(options: Options): Promise<InstalledBrowser> {
if (!existsSync(browserRoot)) { if (!existsSync(browserRoot)) {
await mkdir(browserRoot, {recursive: true}); await mkdir(browserRoot, {recursive: true});
} }
if (!options.install) {
if (existsSync(archivePath)) {
return {
path: archivePath,
browser: options.browser,
platform: options.platform,
buildId: options.buildId,
};
}
debugFetch(`Downloading binary from ${url}`);
await downloadFile(url, archivePath, options.downloadProgressCallback);
return {
path: archivePath,
browser: options.browser,
platform: options.platform,
buildId: options.buildId,
};
}
const outputPath = structure.installationDir( const outputPath = structure.installationDir(
options.browser, options.browser,
options.platform, options.platform,

View File

@ -20,12 +20,18 @@ import os from 'os';
import path from 'path'; import path from 'path';
import {CLI} from '../../../lib/cjs/CLI.js'; import {CLI} from '../../../lib/cjs/CLI.js';
import {createMockedReadlineInterface} from '../utils.js'; import {
createMockedReadlineInterface,
setupTestServer,
getServerUrl,
} from '../utils.js';
import {testChromeBuildId} from '../versions.js'; import {testChromeBuildId} from '../versions.js';
describe('Chrome CLI', function () { describe('Chrome CLI', function () {
this.timeout(90000); this.timeout(90000);
setupTestServer();
let tmpDir = '/tmp/puppeteer-browsers-test'; let tmpDir = '/tmp/puppeteer-browsers-test';
beforeEach(() => { beforeEach(() => {
@ -38,6 +44,7 @@ describe('Chrome CLI', function () {
'@puppeteer/browsers', '@puppeteer/browsers',
'clear', 'clear',
`--path=${tmpDir}`, `--path=${tmpDir}`,
`--base-url=${getServerUrl()}`,
]); ]);
}); });
@ -49,6 +56,7 @@ describe('Chrome CLI', function () {
`chrome@${testChromeBuildId}`, `chrome@${testChromeBuildId}`,
`--path=${tmpDir}`, `--path=${tmpDir}`,
'--platform=linux', '--platform=linux',
`--base-url=${getServerUrl()}`,
]); ]);
assert.ok( assert.ok(
fs.existsSync( fs.existsSync(
@ -90,6 +98,7 @@ describe('Chrome CLI', function () {
`chrome@latest`, `chrome@latest`,
`--path=${tmpDir}`, `--path=${tmpDir}`,
'--platform=linux', '--platform=linux',
`--base-url=${getServerUrl()}`,
]); ]);
}); });
}); });

View File

@ -28,6 +28,7 @@ import {
BrowserPlatform, BrowserPlatform,
Cache, Cache,
} from '../../../lib/cjs/main.js'; } from '../../../lib/cjs/main.js';
import {getServerUrl, setupTestServer} from '../utils.js';
import {testChromeBuildId} from '../versions.js'; import {testChromeBuildId} from '../versions.js';
/** /**
@ -35,6 +36,8 @@ import {testChromeBuildId} from '../versions.js';
* so it requires the network access. * so it requires the network access.
*/ */
describe('Chrome fetch', () => { describe('Chrome fetch', () => {
setupTestServer();
let tmpDir = '/tmp/puppeteer-browsers-test'; let tmpDir = '/tmp/puppeteer-browsers-test';
beforeEach(() => { beforeEach(() => {
@ -52,6 +55,7 @@ describe('Chrome fetch', () => {
browser: Browser.CHROME, browser: Browser.CHROME,
platform: BrowserPlatform.LINUX, platform: BrowserPlatform.LINUX,
buildId: testChromeBuildId, buildId: testChromeBuildId,
baseUrl: getServerUrl(),
}) })
); );
}); });
@ -63,6 +67,7 @@ describe('Chrome fetch', () => {
browser: Browser.CHROME, browser: Browser.CHROME,
platform: BrowserPlatform.LINUX, platform: BrowserPlatform.LINUX,
buildId: 'unknown', buildId: 'unknown',
baseUrl: getServerUrl(),
}), }),
false false
); );
@ -81,6 +86,7 @@ describe('Chrome fetch', () => {
browser: Browser.CHROME, browser: Browser.CHROME,
platform: BrowserPlatform.LINUX, platform: BrowserPlatform.LINUX,
buildId: testChromeBuildId, buildId: testChromeBuildId,
baseUrl: getServerUrl(),
}); });
assert.strictEqual(browser.path, expectedOutputPath); assert.strictEqual(browser.path, expectedOutputPath);
assert.ok(fs.existsSync(expectedOutputPath)); assert.ok(fs.existsSync(expectedOutputPath));
@ -90,6 +96,7 @@ describe('Chrome fetch', () => {
browser: Browser.CHROME, browser: Browser.CHROME,
platform: BrowserPlatform.LINUX, platform: BrowserPlatform.LINUX,
buildId: testChromeBuildId, buildId: testChromeBuildId,
baseUrl: getServerUrl(),
}); });
assert.strictEqual(browser.path, expectedOutputPath); assert.strictEqual(browser.path, expectedOutputPath);
assert.ok(fs.existsSync(expectedOutputPath)); assert.ok(fs.existsSync(expectedOutputPath));
@ -159,11 +166,12 @@ describe('Chrome fetch', () => {
browser: Browser.CHROME, browser: Browser.CHROME,
platform: BrowserPlatform.LINUX, platform: BrowserPlatform.LINUX,
buildId: testChromeBuildId, buildId: testChromeBuildId,
baseUrl: getServerUrl(),
}), }),
true true
); );
assert.deepStrictEqual(proxiedRequestUrls, [ assert.deepStrictEqual(proxiedRequestUrls, [
'https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/113.0.5672.0/linux64/chrome-linux64.zip', getServerUrl() + '/113.0.5672.0/linux64/chrome-linux64.zip',
]); ]);
}); });
@ -180,11 +188,12 @@ describe('Chrome fetch', () => {
browser: Browser.CHROME, browser: Browser.CHROME,
platform: BrowserPlatform.LINUX, platform: BrowserPlatform.LINUX,
buildId: testChromeBuildId, buildId: testChromeBuildId,
baseUrl: getServerUrl(),
}); });
assert.strictEqual(browser.path, expectedOutputPath); assert.strictEqual(browser.path, expectedOutputPath);
assert.ok(fs.existsSync(expectedOutputPath)); assert.ok(fs.existsSync(expectedOutputPath));
assert.deepStrictEqual(proxiedRequestUrls, [ assert.deepStrictEqual(proxiedRequestUrls, [
'https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/113.0.5672.0/linux64/chrome-linux64.zip', getServerUrl() + '/113.0.5672.0/linux64/chrome-linux64.zip',
]); ]);
}); });
}); });

View File

@ -28,6 +28,7 @@ import {
BrowserPlatform, BrowserPlatform,
Cache, Cache,
} from '../../../lib/cjs/main.js'; } from '../../../lib/cjs/main.js';
import {getServerUrl, setupTestServer} from '../utils.js';
import {testChromeBuildId} from '../versions.js'; import {testChromeBuildId} from '../versions.js';
describe('Chrome', () => { describe('Chrome', () => {
@ -44,6 +45,8 @@ describe('Chrome', () => {
}); });
describe('launcher', function () { describe('launcher', function () {
setupTestServer();
this.timeout(60000); this.timeout(60000);
let tmpDir = '/tmp/puppeteer-browsers-test'; let tmpDir = '/tmp/puppeteer-browsers-test';
@ -56,6 +59,7 @@ describe('Chrome', () => {
cacheDir: tmpDir, cacheDir: tmpDir,
browser: Browser.CHROME, browser: Browser.CHROME,
buildId: testChromeBuildId, buildId: testChromeBuildId,
baseUrl: getServerUrl(),
}); });
}); });

View File

@ -28,6 +28,7 @@ import {
BrowserPlatform, BrowserPlatform,
Cache, Cache,
} from '../../../lib/cjs/main.js'; } from '../../../lib/cjs/main.js';
import {getServerUrl, setupTestServer} from '../utils.js';
import {testChromiumBuildId} from '../versions.js'; import {testChromiumBuildId} from '../versions.js';
describe('Chromium', () => { describe('Chromium', () => {
@ -44,6 +45,8 @@ describe('Chromium', () => {
}); });
describe('launcher', function () { describe('launcher', function () {
setupTestServer();
this.timeout(60000); this.timeout(60000);
let tmpDir = '/tmp/puppeteer-browsers-test'; let tmpDir = '/tmp/puppeteer-browsers-test';
@ -56,6 +59,7 @@ describe('Chromium', () => {
cacheDir: tmpDir, cacheDir: tmpDir,
browser: Browser.CHROMIUM, browser: Browser.CHROMIUM,
buildId: testChromiumBuildId, buildId: testChromiumBuildId,
baseUrl: getServerUrl(),
}); });
}); });

View File

@ -20,12 +20,18 @@ import os from 'os';
import path from 'path'; import path from 'path';
import {CLI} from '../../../lib/cjs/CLI.js'; import {CLI} from '../../../lib/cjs/CLI.js';
import {createMockedReadlineInterface} from '../utils.js'; import {
createMockedReadlineInterface,
getServerUrl,
setupTestServer,
} from '../utils.js';
import {testFirefoxBuildId} from '../versions.js'; import {testFirefoxBuildId} from '../versions.js';
describe('Firefox CLI', function () { describe('Firefox CLI', function () {
this.timeout(90000); this.timeout(90000);
setupTestServer();
let tmpDir = '/tmp/puppeteer-browsers-test'; let tmpDir = '/tmp/puppeteer-browsers-test';
beforeEach(() => { beforeEach(() => {
@ -38,6 +44,7 @@ describe('Firefox CLI', function () {
'@puppeteer/browsers', '@puppeteer/browsers',
'clear', 'clear',
`--path=${tmpDir}`, `--path=${tmpDir}`,
`--base-url=${getServerUrl()}`,
]); ]);
}); });
@ -49,6 +56,7 @@ describe('Firefox CLI', function () {
`firefox@${testFirefoxBuildId}`, `firefox@${testFirefoxBuildId}`,
`--path=${tmpDir}`, `--path=${tmpDir}`,
'--platform=linux', '--platform=linux',
`--base-url=${getServerUrl()}`,
]); ]);
assert.ok( assert.ok(
fs.existsSync( fs.existsSync(
@ -65,6 +73,7 @@ describe('Firefox CLI', function () {
`firefox@latest`, `firefox@latest`,
`--path=${tmpDir}`, `--path=${tmpDir}`,
'--platform=linux', '--platform=linux',
`--base-url=${getServerUrl()}`,
]); ]);
}); });
}); });

View File

@ -20,6 +20,7 @@ import os from 'os';
import path from 'path'; import path from 'path';
import {fetch, Browser, BrowserPlatform, Cache} from '../../../lib/cjs/main.js'; import {fetch, Browser, BrowserPlatform, Cache} from '../../../lib/cjs/main.js';
import {setupTestServer, getServerUrl} from '../utils.js';
import {testFirefoxBuildId} from '../versions.js'; import {testFirefoxBuildId} from '../versions.js';
/** /**
@ -27,6 +28,8 @@ import {testFirefoxBuildId} from '../versions.js';
* so it requires the network access. * so it requires the network access.
*/ */
describe('Firefox fetch', () => { describe('Firefox fetch', () => {
setupTestServer();
let tmpDir = '/tmp/puppeteer-browsers-test'; let tmpDir = '/tmp/puppeteer-browsers-test';
beforeEach(() => { beforeEach(() => {
@ -50,6 +53,7 @@ describe('Firefox fetch', () => {
browser: Browser.FIREFOX, browser: Browser.FIREFOX,
platform: BrowserPlatform.LINUX, platform: BrowserPlatform.LINUX,
buildId: testFirefoxBuildId, buildId: testFirefoxBuildId,
baseUrl: getServerUrl(),
}); });
assert.strictEqual(browser.path, expectedOutputPath); assert.strictEqual(browser.path, expectedOutputPath);
assert.ok(fs.existsSync(expectedOutputPath)); assert.ok(fs.existsSync(expectedOutputPath));
@ -60,7 +64,7 @@ describe('Firefox fetch', () => {
(os.platform() === 'darwin' ? it : it.skip)( (os.platform() === 'darwin' ? it : it.skip)(
'should download a buildId that is a dmg archive', 'should download a buildId that is a dmg archive',
async function () { async function () {
this.timeout(120000); this.timeout(180000);
const expectedOutputPath = path.join( const expectedOutputPath = path.join(
tmpDir, tmpDir,
'firefox', 'firefox',
@ -72,6 +76,7 @@ describe('Firefox fetch', () => {
browser: Browser.FIREFOX, browser: Browser.FIREFOX,
platform: BrowserPlatform.MAC, platform: BrowserPlatform.MAC,
buildId: testFirefoxBuildId, buildId: testFirefoxBuildId,
baseUrl: getServerUrl(),
}); });
assert.strictEqual(browser.path, expectedOutputPath); assert.strictEqual(browser.path, expectedOutputPath);
assert.ok(fs.existsSync(expectedOutputPath)); assert.ok(fs.existsSync(expectedOutputPath));

View File

@ -29,6 +29,7 @@ import {
Cache, Cache,
createProfile, createProfile,
} from '../../../lib/cjs/main.js'; } from '../../../lib/cjs/main.js';
import {setupTestServer, getServerUrl} from '../utils.js';
import {testFirefoxBuildId} from '../versions.js'; import {testFirefoxBuildId} from '../versions.js';
describe('Firefox', () => { describe('Firefox', () => {
@ -45,7 +46,9 @@ describe('Firefox', () => {
}); });
describe('launcher', function () { describe('launcher', function () {
this.timeout(60000); this.timeout(120000);
setupTestServer();
let tmpDir = '/tmp/puppeteer-browsers-test'; let tmpDir = '/tmp/puppeteer-browsers-test';
@ -57,6 +60,7 @@ describe('Firefox', () => {
cacheDir: tmpDir, cacheDir: tmpDir,
browser: Browser.FIREFOX, browser: Browser.FIREFOX,
buildId: testFirefoxBuildId, buildId: testFirefoxBuildId,
baseUrl: getServerUrl(),
}); });
}); });

View File

@ -14,9 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
import path from 'path';
import * as readline from 'readline'; import * as readline from 'readline';
import {Writable, Readable} from 'stream'; import {Writable, Readable} from 'stream';
import {TestServer} from '@pptr/testserver';
export function createMockedReadlineInterface( export function createMockedReadlineInterface(
input: string input: string
): readline.Interface { ): readline.Interface {
@ -33,3 +36,29 @@ export function createMockedReadlineInterface(
output: writable, output: writable,
}); });
} }
const startServer = async () => {
const assetsPath = path.join(__dirname, '..', 'cache', 'server');
return await TestServer.create(assetsPath);
};
interface ServerState {
server: TestServer;
}
const state: Partial<ServerState> = {};
export function setupTestServer(): void {
before(async () => {
state.server = await startServer();
});
after(async () => {
await state.server!.stop();
state.server = undefined;
});
}
export function getServerUrl(): string {
return `http://localhost:${state.server!.port}`;
}

View File

@ -0,0 +1,88 @@
/**
* Copyright 2023 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Downloads test browser binaries to test/cache/server folder that
* mirrors the structure of the download server.
*/
import {BrowserPlatform, fetch} from '@puppeteer/browsers';
import path from 'path';
import fs from 'fs';
import * as versions from '../test/build/versions.js';
import {downloadPaths} from '../lib/esm/browser-data/browser-data.js';
function getBrowser(str) {
const regex = /test(.+)BuildId/;
const match = str.match(regex);
if (match && match[1]) {
return match[1].toLowerCase();
} else {
return null;
}
}
const cacheDir = path.normalize(path.join('.', 'test', 'cache'));
const promises = [];
for (const version of Object.keys(versions)) {
const browser = getBrowser(version);
if (!browser) {
continue;
}
const buildId = versions[version];
for (const platform of Object.values(BrowserPlatform)) {
promises.push(
(async function download(buildId, platform) {
const targetPath = path.join(
cacheDir,
'server',
...downloadPaths[browser](platform, buildId)
);
if (fs.existsSync(targetPath)) {
return;
}
const result = await fetch({
browser,
buildId,
platform,
cacheDir: path.join(cacheDir, 'tmp'),
install: false,
});
fs.mkdirSync(path.dirname(targetPath), {
recursive: true,
});
fs.copyFileSync(result.path, targetPath);
})(buildId, platform)
);
}
}
await Promise.all(promises);
fs.rmSync(path.join(cacheDir, 'tmp'), {
recursive: true,
force: true,
maxRetries: 10,
});