mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
feat: implement --dry-run for npx playwright install (#17158)
* feat: implement `--dry-run` for `npx playwright install` The `--dry-run` command prints URLs for browsers to be installed. Demo output: ``` browser: chromium version 106.0.5249.21 Install location: /Users/andreylushnikov/Library/Caches/ms-playwright/chromium-1023 Download url: https://playwright.azureedge.net/builds/chromium/1023/chromium-mac-arm64.zip Download fallback 1: https://playwright-akamai.azureedge.net/builds/chromium/1023/chromium-mac-arm64.zip Download fallback 2: https://playwright-verizon.azureedge.net/builds/chromium/1023/chromium-mac-arm64.zip browser: firefox version 104.0 Install location: /Users/andreylushnikov/Library/Caches/ms-playwright/firefox-1350 Download url: https://playwright.azureedge.net/builds/firefox/1350/firefox-mac-11-arm64.zip Download fallback 1: https://playwright-akamai.azureedge.net/builds/firefox/1350/firefox-mac-11-arm64.zip Download fallback 2: https://playwright-verizon.azureedge.net/builds/firefox/1350/firefox-mac-11-arm64.zip browser: webkit version 16.0 Install location: /Users/andreylushnikov/Library/Caches/ms-playwright/webkit-1714 Download url: https://playwright.azureedge.net/builds/webkit/1714/webkit-mac-12-arm64.zip Download fallback 1: https://playwright-akamai.azureedge.net/builds/webkit/1714/webkit-mac-12-arm64.zip Download fallback 2: https://playwright-verizon.azureedge.net/builds/webkit/1714/webkit-mac-12-arm64.zip browser: ffmpeg Install location: /Users/andreylushnikov/Library/Caches/ms-playwright/ffmpeg-1007 Download url: https://playwright.azureedge.net/builds/ffmpeg/1007/ffmpeg-mac-arm64.zip Download fallback 1: https://playwright-akamai.azureedge.net/builds/ffmpeg/1007/ffmpeg-mac-arm64.zip Download fallback 2: https://playwright-verizon.azureedge.net/builds/ffmpeg/1007/ffmpeg-mac-arm64.zip ``` Fixes #16926
This commit is contained in:
parent
3708ba7a1f
commit
b0ff4f58ce
@ -32,9 +32,7 @@ import type { Page } from '../client/page';
|
||||
import type { BrowserType } from '../client/browserType';
|
||||
import type { BrowserContextOptions, LaunchOptions } from '../client/types';
|
||||
import { spawn } from 'child_process';
|
||||
import { getPlaywrightVersion } from '../common/userAgent';
|
||||
import { wrapInASCIIBox, isLikelyNpxGlobal, assert } from '../utils';
|
||||
import { spawnAsync } from '../utils/spawnAsync';
|
||||
import { launchGridAgent } from '../grid/gridAgent';
|
||||
import type { GridFactory } from '../grid/gridServer';
|
||||
import { GridServer } from '../grid/gridServer';
|
||||
@ -120,8 +118,9 @@ program
|
||||
.command('install [browser...]')
|
||||
.description('ensure browsers necessary for this version of Playwright are installed')
|
||||
.option('--with-deps', 'install system dependencies for browsers')
|
||||
.option('--dry-run', 'do not execute installation, only print information')
|
||||
.option('--force', 'force reinstall of stable browser channels')
|
||||
.action(async function(args: string[], options: { withDeps?: boolean, force?: boolean }) {
|
||||
.action(async function(args: string[], options: { withDeps?: boolean, force?: boolean, dryRun?: boolean }) {
|
||||
if (isLikelyNpxGlobal()) {
|
||||
console.error(wrapInASCIIBox([
|
||||
`WARNING: It looks like you are running 'npx playwright install' without first`,
|
||||
@ -143,27 +142,26 @@ program
|
||||
].join('\n'), 1));
|
||||
}
|
||||
try {
|
||||
if (!args.length) {
|
||||
const executables = registry.defaultExecutables();
|
||||
if (options.withDeps)
|
||||
await registry.installDeps(executables, false);
|
||||
await registry.install(executables, false /* forceReinstall */);
|
||||
} else {
|
||||
const installDockerImage = args.some(arg => arg === 'docker-image');
|
||||
args = args.filter(arg => arg !== 'docker-image');
|
||||
if (installDockerImage) {
|
||||
const imageName = `mcr.microsoft.com/playwright:v${getPlaywrightVersion()}-focal`;
|
||||
const { code } = await spawnAsync('docker', ['pull', imageName], { stdio: 'inherit' });
|
||||
if (code !== 0) {
|
||||
console.log('Failed to pull docker image');
|
||||
process.exit(1);
|
||||
const hasNoArguments = !args.length;
|
||||
const executables = hasNoArguments ? registry.defaultExecutables() : checkBrowsersToInstall(args);
|
||||
if (options.withDeps)
|
||||
await registry.installDeps(executables, !!options.dryRun);
|
||||
if (options.dryRun) {
|
||||
for (const executable of executables) {
|
||||
const version = executable.browserVersion ? `version ` + executable.browserVersion : '';
|
||||
console.log(`browser: ${executable.name}${version ? ' ' + version : ''}`);
|
||||
console.log(` Install location: ${executable.directory ?? '<system>'}`);
|
||||
if (executable.downloadURLs?.length) {
|
||||
const [url, ...fallbacks] = executable.downloadURLs;
|
||||
console.log(` Download url: ${url}`);
|
||||
for (let i = 0; i < fallbacks.length; ++i)
|
||||
console.log(` Download fallback ${i + 1}: ${fallbacks[i]}`);
|
||||
}
|
||||
console.log(``);
|
||||
}
|
||||
|
||||
const executables = checkBrowsersToInstall(args);
|
||||
if (options.withDeps)
|
||||
await registry.installDeps(executables, false);
|
||||
await registry.install(executables, !!options.force /* forceReinstall */);
|
||||
} else {
|
||||
const forceReinstall = hasNoArguments ? false : !!options.force;
|
||||
await registry.install(executables, forceReinstall);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(`Failed to install browsers\n${e}`);
|
||||
|
||||
@ -310,6 +310,8 @@ export interface Executable {
|
||||
browserName: BrowserName | undefined;
|
||||
installType: 'download-by-default' | 'download-on-demand' | 'install-script' | 'none';
|
||||
directory: string | undefined;
|
||||
downloadURLs?: string[],
|
||||
browserVersion?: string,
|
||||
executablePathOrDie(sdkLanguage: string): string;
|
||||
executablePath(sdkLanguage: string): string | undefined;
|
||||
validateHostRequirements(sdkLanguage: string): Promise<void>;
|
||||
@ -376,7 +378,9 @@ export class Registry {
|
||||
executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('chromium', chromiumExecutable, chromium.installByDefault, sdkLanguage),
|
||||
installType: chromium.installByDefault ? 'download-by-default' : 'download-on-demand',
|
||||
validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, 'chromium', chromium.dir, ['chrome-linux'], [], ['chrome-win']),
|
||||
_install: () => this._downloadExecutable(chromium, chromiumExecutable, DOWNLOAD_PATHS['chromium'][hostPlatform], 'PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST'),
|
||||
downloadURLs: this._downloadURLs(chromium),
|
||||
browserVersion: chromium.browserVersion,
|
||||
_install: () => this._downloadExecutable(chromium, chromiumExecutable),
|
||||
_dependencyGroup: 'chromium',
|
||||
_isHermeticInstallation: true,
|
||||
});
|
||||
@ -392,7 +396,9 @@ export class Registry {
|
||||
executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('chromium-with-symbols', chromiumWithSymbolsExecutable, chromiumWithSymbols.installByDefault, sdkLanguage),
|
||||
installType: chromiumWithSymbols.installByDefault ? 'download-by-default' : 'download-on-demand',
|
||||
validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, 'chromium', chromiumWithSymbols.dir, ['chrome-linux'], [], ['chrome-win']),
|
||||
_install: () => this._downloadExecutable(chromiumWithSymbols, chromiumWithSymbolsExecutable, DOWNLOAD_PATHS['chromium-with-symbols'][hostPlatform], 'PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST'),
|
||||
downloadURLs: this._downloadURLs(chromiumWithSymbols),
|
||||
browserVersion: chromiumWithSymbols.browserVersion,
|
||||
_install: () => this._downloadExecutable(chromiumWithSymbols, chromiumWithSymbolsExecutable),
|
||||
_dependencyGroup: 'chromium',
|
||||
_isHermeticInstallation: true,
|
||||
});
|
||||
@ -408,7 +414,9 @@ export class Registry {
|
||||
executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('chromium-tip-of-tree', chromiumTipOfTreeExecutable, chromiumTipOfTree.installByDefault, sdkLanguage),
|
||||
installType: chromiumTipOfTree.installByDefault ? 'download-by-default' : 'download-on-demand',
|
||||
validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, 'chromium', chromiumTipOfTree.dir, ['chrome-linux'], [], ['chrome-win']),
|
||||
_install: () => this._downloadExecutable(chromiumTipOfTree, chromiumTipOfTreeExecutable, DOWNLOAD_PATHS['chromium-tip-of-tree'][hostPlatform], 'PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST'),
|
||||
downloadURLs: this._downloadURLs(chromiumTipOfTree),
|
||||
browserVersion: chromiumTipOfTree.browserVersion,
|
||||
_install: () => this._downloadExecutable(chromiumTipOfTree, chromiumTipOfTreeExecutable),
|
||||
_dependencyGroup: 'chromium',
|
||||
_isHermeticInstallation: true,
|
||||
});
|
||||
@ -492,7 +500,9 @@ export class Registry {
|
||||
executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('firefox', firefoxExecutable, firefox.installByDefault, sdkLanguage),
|
||||
installType: firefox.installByDefault ? 'download-by-default' : 'download-on-demand',
|
||||
validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, 'firefox', firefox.dir, ['firefox'], [], ['firefox']),
|
||||
_install: () => this._downloadExecutable(firefox, firefoxExecutable, DOWNLOAD_PATHS['firefox'][hostPlatform], 'PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST'),
|
||||
downloadURLs: this._downloadURLs(firefox),
|
||||
browserVersion: firefox.browserVersion,
|
||||
_install: () => this._downloadExecutable(firefox, firefoxExecutable),
|
||||
_dependencyGroup: 'firefox',
|
||||
_isHermeticInstallation: true,
|
||||
});
|
||||
@ -508,7 +518,9 @@ export class Registry {
|
||||
executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('firefox-beta', firefoxBetaExecutable, firefoxBeta.installByDefault, sdkLanguage),
|
||||
installType: firefoxBeta.installByDefault ? 'download-by-default' : 'download-on-demand',
|
||||
validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, 'firefox', firefoxBeta.dir, ['firefox'], [], ['firefox']),
|
||||
_install: () => this._downloadExecutable(firefoxBeta, firefoxBetaExecutable, DOWNLOAD_PATHS['firefox-beta'][hostPlatform], 'PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST'),
|
||||
downloadURLs: this._downloadURLs(firefoxBeta),
|
||||
browserVersion: firefoxBeta.browserVersion,
|
||||
_install: () => this._downloadExecutable(firefoxBeta, firefoxBetaExecutable),
|
||||
_dependencyGroup: 'firefox',
|
||||
_isHermeticInstallation: true,
|
||||
});
|
||||
@ -534,7 +546,9 @@ export class Registry {
|
||||
executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('webkit', webkitExecutable, webkit.installByDefault, sdkLanguage),
|
||||
installType: webkit.installByDefault ? 'download-by-default' : 'download-on-demand',
|
||||
validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, 'webkit', webkit.dir, webkitLinuxLddDirectories, ['libGLESv2.so.2', 'libx264.so'], ['']),
|
||||
_install: () => this._downloadExecutable(webkit, webkitExecutable, DOWNLOAD_PATHS['webkit'][hostPlatform], 'PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST'),
|
||||
downloadURLs: this._downloadURLs(webkit),
|
||||
browserVersion: webkit.browserVersion,
|
||||
_install: () => this._downloadExecutable(webkit, webkitExecutable),
|
||||
_dependencyGroup: 'webkit',
|
||||
_isHermeticInstallation: true,
|
||||
});
|
||||
@ -550,7 +564,8 @@ export class Registry {
|
||||
executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('ffmpeg', ffmpegExecutable, ffmpeg.installByDefault, sdkLanguage),
|
||||
installType: ffmpeg.installByDefault ? 'download-by-default' : 'download-on-demand',
|
||||
validateHostRequirements: () => Promise.resolve(),
|
||||
_install: () => this._downloadExecutable(ffmpeg, ffmpegExecutable, DOWNLOAD_PATHS['ffmpeg'][hostPlatform], 'PLAYWRIGHT_FFMPEG_DOWNLOAD_HOST'),
|
||||
downloadURLs: this._downloadURLs(ffmpeg),
|
||||
_install: () => this._downloadExecutable(ffmpeg, ffmpegExecutable),
|
||||
_dependencyGroup: 'tools',
|
||||
_isHermeticInstallation: true,
|
||||
});
|
||||
@ -727,17 +742,33 @@ export class Registry {
|
||||
}
|
||||
}
|
||||
|
||||
private async _downloadExecutable(descriptor: BrowsersJSONDescriptor, executablePath: string | undefined, downloadPathTemplate: string | undefined, downloadHostEnv: string) {
|
||||
if (!downloadPathTemplate || !executablePath)
|
||||
throw new Error(`ERROR: Playwright does not support ${descriptor.name} on ${hostPlatform}`);
|
||||
if (hostPlatform === 'generic-linux' || hostPlatform === 'generic-linux-arm64')
|
||||
logPolitely('BEWARE: your OS is not officially supported by Playwright; downloading fallback build.');
|
||||
private _downloadURLs(descriptor: BrowsersJSONDescriptor): string[] {
|
||||
const downloadPathTemplate: string|undefined = (DOWNLOAD_PATHS as any)[descriptor.name][hostPlatform];
|
||||
if (!downloadPathTemplate)
|
||||
return [];
|
||||
const downloadPath = util.format(downloadPathTemplate, descriptor.revision);
|
||||
|
||||
let downloadURLs = PLAYWRIGHT_CDN_MIRRORS.map(mirror => `${mirror}/${downloadPath}`) ;
|
||||
let downloadHostEnv;
|
||||
if (descriptor.name.startsWith('chromium'))
|
||||
downloadHostEnv = 'PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST';
|
||||
else if (descriptor.name.startsWith('firefox'))
|
||||
downloadHostEnv = 'PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST';
|
||||
else if (descriptor.name.startsWith('webkit'))
|
||||
downloadHostEnv = 'PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST';
|
||||
|
||||
const customHostOverride = (downloadHostEnv && getFromENV(downloadHostEnv)) || getFromENV('PLAYWRIGHT_DOWNLOAD_HOST');
|
||||
if (customHostOverride)
|
||||
downloadURLs = [`${customHostOverride}/${downloadPath}`];
|
||||
return downloadURLs;
|
||||
}
|
||||
|
||||
private async _downloadExecutable(descriptor: BrowsersJSONDescriptor, executablePath: string | undefined) {
|
||||
const downloadURLs = this._downloadURLs(descriptor);
|
||||
if (!downloadURLs.length || !executablePath)
|
||||
throw new Error(`ERROR: Playwright does not support ${descriptor.name} on ${hostPlatform}`);
|
||||
if (hostPlatform === 'generic-linux' || hostPlatform === 'generic-linux-arm64')
|
||||
logPolitely('BEWARE: your OS is not officially supported by Playwright; downloading fallback build.');
|
||||
|
||||
const displayName = descriptor.name.split('-').map(word => {
|
||||
return word === 'ffmpeg' ? 'FFMPEG' : word.charAt(0).toUpperCase() + word.slice(1);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user