fix: implement a fallback to download URLs provided by dashboard (#11951)

This commit is contained in:
Alex Rudenko 2024-02-20 13:46:53 +01:00 committed by GitHub
parent 5c6a3e410e
commit 73c1f9bbf3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 100 additions and 21 deletions

View File

@ -11,15 +11,15 @@ import os from 'os';
import path from 'path'; import path from 'path';
import { import {
type Browser, Browser,
type BrowserPlatform, BrowserPlatform,
downloadUrls, downloadUrls,
} from './browser-data/browser-data.js'; } from './browser-data/browser-data.js';
import {Cache, InstalledBrowser} from './Cache.js'; import {Cache, InstalledBrowser} from './Cache.js';
import {debug} from './debug.js'; import {debug} from './debug.js';
import {detectBrowserPlatform} from './detectPlatform.js'; import {detectBrowserPlatform} from './detectPlatform.js';
import {unpackArchive} from './fileUtil.js'; import {unpackArchive} from './fileUtil.js';
import {downloadFile, headHttpRequest} from './httpUtil.js'; import {downloadFile, getJSON, headHttpRequest} from './httpUtil.js';
const debugInstall = debug('puppeteer:browsers:install'); const debugInstall = debug('puppeteer:browsers:install');
@ -115,6 +115,68 @@ export async function install(
options.buildId, options.buildId,
options.baseUrl options.baseUrl
); );
try {
return await installUrl(url, options);
} catch (err) {
debugInstall(`Error downloading from ${url}.`);
switch (options.browser) {
case Browser.CHROME:
case Browser.CHROMEDRIVER:
case Browser.CHROMEHEADLESSSHELL: {
debugInstall(
`Trying to find download URL via https://googlechromelabs.github.io/chrome-for-testing.`
);
interface Version {
downloads: Record<string, Array<{platform: string; url: string}>>;
}
const version = (await getJSON(
new URL(
`https://googlechromelabs.github.io/chrome-for-testing/${options.buildId}.json`
)
)) as Version;
let platform = '';
switch (options.platform) {
case BrowserPlatform.LINUX:
platform = 'linux64';
break;
case BrowserPlatform.MAC_ARM:
platform = 'mac-arm64';
break;
case BrowserPlatform.MAC:
platform = 'mac-x64';
break;
case BrowserPlatform.WIN32:
platform = 'win32';
break;
case BrowserPlatform.WIN64:
platform = 'win64';
break;
}
const url = version.downloads[options.browser]?.find(link => {
return link['platform'] === platform;
})?.url;
if (url) {
debugInstall(`Falling back to downloading from ${url}.`);
return await installUrl(new URL(url), options);
}
throw err;
}
default:
throw err;
}
}
}
async function installUrl(
url: URL,
options: InstallOptions
): Promise<InstalledBrowser | string> {
options.platform ??= detectBrowserPlatform();
if (!options.platform) {
throw new Error(
`Cannot download a binary for the provided platform: ${os.platform()} (${os.arch()})`
);
}
const fileName = url.toString().split('/').pop(); const fileName = url.toString().split('/').pop();
assert(fileName, `A malformed download URL was found: ${url}.`); assert(fileName, `A malformed download URL was found: ${url}.`);
const cache = new Cache(options.cacheDir); const cache = new Cache(options.cacheDir);

View File

@ -137,30 +137,21 @@ describe('Chrome install', () => {
); );
}); });
it('throws on invalid URL', async function () { it('falls back to the chrome-for-testing dashboard URLs if URL is not available', async function () {
const expectedOutputPath = path.join( const expectedOutputPath = path.join(
tmpDir, tmpDir,
'chrome', 'chrome',
`${BrowserPlatform.LINUX}-${testChromeBuildId}` `${BrowserPlatform.LINUX}-${testChromeBuildId}`
); );
assert.strictEqual(fs.existsSync(expectedOutputPath), false); assert.strictEqual(fs.existsSync(expectedOutputPath), false);
await install({
async function installThatThrows(): Promise<unknown> { cacheDir: tmpDir,
try { browser: Browser.CHROME,
await install({ platform: BrowserPlatform.LINUX,
cacheDir: tmpDir, buildId: testChromeBuildId,
browser: Browser.CHROME, baseUrl: 'https://127.0.0.1',
platform: BrowserPlatform.LINUX, });
buildId: testChromeBuildId, assert.strictEqual(fs.existsSync(expectedOutputPath), true);
baseUrl: 'https://127.0.0.1',
});
return undefined;
} catch (err) {
return err;
}
}
assert.ok(await installThatThrows());
assert.strictEqual(fs.existsSync(expectedOutputPath), false);
}); });
describe('with proxy', () => { describe('with proxy', () => {

View File

@ -49,6 +49,32 @@ describe('Firefox install', () => {
assert.ok(fs.existsSync(expectedOutputPath)); assert.ok(fs.existsSync(expectedOutputPath));
}); });
it('throws on invalid URL', async function () {
const expectedOutputPath = path.join(
tmpDir,
'chrome',
`${BrowserPlatform.LINUX}-${testFirefoxBuildId}`
);
assert.strictEqual(fs.existsSync(expectedOutputPath), false);
async function installThatThrows(): Promise<unknown> {
try {
await install({
cacheDir: tmpDir,
browser: Browser.FIREFOX,
platform: BrowserPlatform.LINUX,
buildId: testFirefoxBuildId,
baseUrl: 'https://127.0.0.1',
});
return undefined;
} catch (err) {
return err;
}
}
assert.ok(await installThatThrows());
assert.strictEqual(fs.existsSync(expectedOutputPath), false);
});
// install relies on the `hdiutil` utility on MacOS. // install relies on the `hdiutil` utility on MacOS.
// The utility is not available on other platforms. // The utility is not available on other platforms.
(os.platform() === 'darwin' ? it : it.skip)( (os.platform() === 'darwin' ? it : it.skip)(