chore: add CDN download fallbacks (#14933)

This commit is contained in:
Max Schmitt 2022-06-17 20:47:32 +02:00 committed by GitHub
parent 466d50e3e3
commit 822b86d8a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 21 deletions

View File

@ -24,17 +24,16 @@ import { debugLogger } from '../../common/debugLogger';
import { download } from './download'; import { download } from './download';
import { extract } from '../../zipBundle'; import { extract } from '../../zipBundle';
export async function downloadBrowserWithProgressBar(title: string, browserDirectory: string, executablePath: string, downloadURL: string, downloadFileName: string): Promise<boolean> { export async function downloadBrowserWithProgressBar(title: string, browserDirectory: string, executablePath: string, downloadURLs: string[], downloadFileName: string): Promise<boolean> {
if (await existsAsync(browserDirectory)) { if (await existsAsync(browserDirectory)) {
// Already downloaded. // Already downloaded.
debugLogger.log('install', `${title} is already downloaded.`); debugLogger.log('install', `${title} is already downloaded.`);
return false; return false;
} }
const url = downloadURL;
const zipPath = path.join(os.tmpdir(), downloadFileName); const zipPath = path.join(os.tmpdir(), downloadFileName);
try { try {
await download(url, zipPath, { await download(downloadURLs, zipPath, {
progressBarName: title, progressBarName: title,
log: debugLogger.log.bind(debugLogger, 'install'), log: debugLogger.log.bind(debugLogger, 'install'),
userAgent: getUserAgent(), userAgent: getUserAgent(),

View File

@ -79,7 +79,7 @@ type DownloadOptions = {
}; };
export async function download( export async function download(
url: string, urls: string | string[],
destination: string, destination: string,
options: DownloadOptions = {} options: DownloadOptions = {}
) { ) {
@ -88,6 +88,9 @@ export async function download(
log( log(
`downloading ${progressBarName} - attempt #${attempt}` `downloading ${progressBarName} - attempt #${attempt}`
); );
if (!Array.isArray(urls))
urls = [urls];
const url = urls[(attempt - 1) % urls.length];
const { error } = await downloadFile(url, destination, { const { error } = await downloadFile(url, destination, {
progressCallback: getDownloadProgress(progressBarName), progressCallback: getDownloadProgress(progressBarName),
log, log,
@ -99,18 +102,8 @@ export async function download(
} }
const errorMessage = error?.message || ''; const errorMessage = error?.message || '';
log(`attempt #${attempt} - ERROR: ${errorMessage}`); log(`attempt #${attempt} - ERROR: ${errorMessage}`);
if ( if (attempt >= retryCount)
attempt < retryCount &&
(errorMessage.includes('ECONNRESET') ||
errorMessage.includes('ETIMEDOUT'))
) {
// Maximum default delay is 3rd retry: 1337.5ms
const millis = Math.random() * 200 + 250 * Math.pow(1.5, attempt);
log(`sleeping ${millis}ms before retry...`);
await new Promise(c => setTimeout(c, millis));
} else {
throw error; throw error;
}
} }
} }

View File

@ -36,6 +36,12 @@ export { writeDockerVersion } from './dependencies';
const PACKAGE_PATH = path.join(__dirname, '..', '..', '..'); const PACKAGE_PATH = path.join(__dirname, '..', '..', '..');
const BIN_PATH = path.join(__dirname, '..', '..', '..', 'bin'); const BIN_PATH = path.join(__dirname, '..', '..', '..', 'bin');
const PLAYWRIGHT_CDN_MIRRORS = [
'https://playwright.azureedge.net',
'https://playwright-akamai.azureedge.net',
'https://playwright-verizon.azureedge.net',
];
const EXECUTABLE_PATHS = { const EXECUTABLE_PATHS = {
'chromium': { 'chromium': {
'linux': ['chrome-linux', 'chrome'], 'linux': ['chrome-linux', 'chrome'],
@ -701,12 +707,12 @@ export class Registry {
throw new Error(`ERROR: Playwright does not support ${descriptor.name} on ${hostPlatform}`); throw new Error(`ERROR: Playwright does not support ${descriptor.name} on ${hostPlatform}`);
if (hostPlatform === 'generic-linux' || hostPlatform === 'generic-linux-arm64') if (hostPlatform === 'generic-linux' || hostPlatform === 'generic-linux-arm64')
logPolitely('BEWARE: your OS is not officially supported by Playwright; downloading Ubuntu build as a fallback.'); logPolitely('BEWARE: your OS is not officially supported by Playwright; downloading Ubuntu build as a fallback.');
const downloadHost =
(downloadHostEnv && getFromENV(downloadHostEnv)) ||
getFromENV('PLAYWRIGHT_DOWNLOAD_HOST') ||
'https://playwright.azureedge.net';
const downloadPath = util.format(downloadPathTemplate, descriptor.revision); const downloadPath = util.format(downloadPathTemplate, descriptor.revision);
const downloadURL = `${downloadHost}/${downloadPath}`;
let downloadURLs = PLAYWRIGHT_CDN_MIRRORS.map(mirror => `${mirror}/${downloadPath}`) ;
const customHostOverride = (downloadHostEnv && getFromENV(downloadHostEnv)) || getFromENV('PLAYWRIGHT_DOWNLOAD_HOST');
if (customHostOverride)
downloadURLs = [`${customHostOverride}/${downloadPath}`];
const displayName = descriptor.name.split('-').map(word => { const displayName = descriptor.name.split('-').map(word => {
return word === 'ffmpeg' ? 'FFMPEG' : word.charAt(0).toUpperCase() + word.slice(1); return word === 'ffmpeg' ? 'FFMPEG' : word.charAt(0).toUpperCase() + word.slice(1);
@ -716,7 +722,7 @@ export class Registry {
: `${displayName} playwright build v${descriptor.revision}`; : `${displayName} playwright build v${descriptor.revision}`;
const downloadFileName = `playwright-download-${descriptor.name}-${hostPlatform}-${descriptor.revision}.zip`; const downloadFileName = `playwright-download-${descriptor.name}-${hostPlatform}-${descriptor.revision}.zip`;
await downloadBrowserWithProgressBar(title, descriptor.dir, executablePath, downloadURL, downloadFileName).catch(e => { await downloadBrowserWithProgressBar(title, descriptor.dir, executablePath, downloadURLs, downloadFileName).catch(e => {
throw new Error(`Failed to download ${title}, caused by\n${e.stack}`); throw new Error(`Failed to download ${title}, caused by\n${e.stack}`);
}); });
await fs.promises.writeFile(markerFilePath(descriptor.dir), ''); await fs.promises.writeFile(markerFilePath(descriptor.dir), '');