mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
feat: install chrome-beta via cli (#6831)
This patch starts introduces `npx playwright install chrome-beta` command and switches our Chrome Beta tests to it.
This commit is contained in:
parent
3c3a7f9293
commit
cb4adb1446
10
.github/workflows/tests_secondary.yml
vendored
10
.github/workflows/tests_secondary.yml
vendored
@ -472,7 +472,6 @@ jobs:
|
|||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: ./utils/install-chrome-beta/reinstall_linux.sh
|
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 12
|
node-version: 12
|
||||||
@ -481,7 +480,7 @@ jobs:
|
|||||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
- run: node lib/cli/cli install-deps chromium
|
- run: node lib/cli/cli install-deps chromium
|
||||||
- run: node lib/cli/cli install ffmpeg
|
- run: node lib/cli/cli install chrome-beta
|
||||||
# XVFB-RUN merges both STDOUT and STDERR, whereas we need only STDERR
|
# XVFB-RUN merges both STDOUT and STDERR, whereas we need only STDERR
|
||||||
# Wrap `npm run` in a subshell to redirect STDERR to file.
|
# Wrap `npm run` in a subshell to redirect STDERR to file.
|
||||||
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- bash -c "npm run ctest"
|
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- bash -c "npm run ctest"
|
||||||
@ -500,8 +499,6 @@ jobs:
|
|||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Install Chrome Beta
|
|
||||||
run: pwsh -command ".\$GITHUB_WORKSPACE\utils\install-chrome-beta\reinstall_win.ps1"
|
|
||||||
- name: Install Media Pack
|
- name: Install Media Pack
|
||||||
shell: powershell
|
shell: powershell
|
||||||
run: Install-WindowsFeature Server-Media-Foundation
|
run: Install-WindowsFeature Server-Media-Foundation
|
||||||
@ -512,7 +509,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
- run: node lib/cli/cli install ffmpeg
|
- run: node lib/cli/cli install chrome-beta
|
||||||
- run: npm run ctest
|
- run: npm run ctest
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
@ -531,7 +528,6 @@ jobs:
|
|||||||
runs-on: macos-10.15
|
runs-on: macos-10.15
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: ./utils/install-chrome-beta/reinstall_mac.sh
|
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 12
|
node-version: 12
|
||||||
@ -539,7 +535,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
- run: node lib/cli/cli install ffmpeg
|
- run: node lib/cli/cli install chrome-beta
|
||||||
- run: npm run ctest
|
- run: npm run ctest
|
||||||
env:
|
env:
|
||||||
PWTEST_CHANNEL: chrome-beta
|
PWTEST_CHANNEL: chrome-beta
|
||||||
|
@ -28,7 +28,7 @@ const cpAsync = util.promisify(ncp);
|
|||||||
const SCRIPT_NAME = path.basename(__filename);
|
const SCRIPT_NAME = path.basename(__filename);
|
||||||
const ROOT_PATH = path.join(__dirname, '..');
|
const ROOT_PATH = path.join(__dirname, '..');
|
||||||
|
|
||||||
const PLAYWRIGHT_CORE_FILES = ['bin/PrintDeps.exe', 'lib', 'types', 'NOTICE', 'LICENSE', 'bin/android-driver.apk', 'bin/android-driver-target.apk'];
|
const PLAYWRIGHT_CORE_FILES = ['bin', 'lib', 'types', 'NOTICE', 'LICENSE', ];
|
||||||
|
|
||||||
const PACKAGES = {
|
const PACKAGES = {
|
||||||
'playwright': {
|
'playwright': {
|
||||||
|
@ -34,7 +34,13 @@ import { BrowserType } from '../client/browserType';
|
|||||||
import { BrowserContextOptions, LaunchOptions } from '../client/types';
|
import { BrowserContextOptions, LaunchOptions } from '../client/types';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import { installDeps } from '../install/installDeps';
|
import { installDeps } from '../install/installDeps';
|
||||||
import { allBrowserNames } from '../utils/registry';
|
import { allBrowserNames, BrowserName } from '../utils/registry';
|
||||||
|
import * as utils from '../utils/utils';
|
||||||
|
|
||||||
|
const SCRIPTS_DIRECTORY = path.join(__dirname, '..', '..', 'bin');
|
||||||
|
|
||||||
|
type BrowserChannel = 'chrome-beta';
|
||||||
|
const allBrowserChannels: Set<BrowserChannel> = new Set(['chrome-beta']);
|
||||||
|
|
||||||
program
|
program
|
||||||
.version('Version ' + require('../../package.json').version)
|
.version('Version ' + require('../../package.json').version)
|
||||||
@ -86,24 +92,56 @@ program
|
|||||||
program
|
program
|
||||||
.command('install [browserType...]')
|
.command('install [browserType...]')
|
||||||
.description('ensure browsers necessary for this version of Playwright are installed')
|
.description('ensure browsers necessary for this version of Playwright are installed')
|
||||||
.action(async function(browserTypes) {
|
.action(async function(args) {
|
||||||
try {
|
try {
|
||||||
const allBrowsers = new Set(allBrowserNames);
|
// Install default browsers when invoked without arguments.
|
||||||
for (const browserType of browserTypes) {
|
if (!args.length) {
|
||||||
if (!allBrowsers.has(browserType)) {
|
await installBrowsers();
|
||||||
console.log(`Invalid browser name: '${browserType}'. Expecting one of: ${allBrowserNames.map(name => `'${name}'`).join(', ')}`);
|
return;
|
||||||
process.exit(1);
|
}
|
||||||
}
|
const browserNames: Set<BrowserName> = new Set(args.filter((browser: any) => allBrowserNames.has(browser)));
|
||||||
|
const browserChannels: Set<BrowserChannel> = new Set(args.filter((browser: any) => allBrowserChannels.has(browser)));
|
||||||
|
const faultyArguments: string[] = args.filter((browser: any) => !browserNames.has(browser) && !browserChannels.has(browser));
|
||||||
|
if (faultyArguments.length) {
|
||||||
|
console.log(`Invalid installation targets: ${faultyArguments.map(name => `'${name}'`).join(', ')}. Expecting one of: ${[...allBrowserNames, ...allBrowserChannels].map(name => `'${name}'`).join(', ')}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
if (browserNames.has('chromium') || browserChannels.has('chrome-beta'))
|
||||||
|
browserNames.add('ffmpeg');
|
||||||
|
if (browserNames.size)
|
||||||
|
await installBrowsers([...browserNames]);
|
||||||
|
for (const browserChannel of browserChannels) {
|
||||||
|
if (browserChannel === 'chrome-beta')
|
||||||
|
await installChromeBeta();
|
||||||
|
else
|
||||||
|
throw new Error(`ERROR: no installation instructions for '${browserChannel}' channel.`);
|
||||||
}
|
}
|
||||||
if (browserTypes.length && browserTypes.includes('chromium'))
|
|
||||||
browserTypes = browserTypes.concat('ffmpeg');
|
|
||||||
await installBrowsers(browserTypes.length ? browserTypes : undefined);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(`Failed to install browsers\n${e}`);
|
console.log(`Failed to install browsers\n${e}`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function installChromeBeta() {
|
||||||
|
const platform: string = os.platform();
|
||||||
|
const shell: (string|undefined) = {
|
||||||
|
'linux': 'bash',
|
||||||
|
'darwin': 'bash',
|
||||||
|
'win32': 'powershell.exe',
|
||||||
|
}[platform];
|
||||||
|
const scriptName: (string|undefined) = {
|
||||||
|
'linux': 'reinstall_chrome_beta_linux.sh',
|
||||||
|
'darwin': 'reinstall_chrome_beta_mac.sh',
|
||||||
|
'win32': 'reinstall_chrome_beta_win.ps1',
|
||||||
|
}[platform];
|
||||||
|
if (!shell || !scriptName)
|
||||||
|
throw new Error(`Cannot install chrome-beta on ${platform}`);
|
||||||
|
|
||||||
|
const {code} = await utils.spawnAsync(shell, [path.join(SCRIPTS_DIRECTORY, scriptName)], { cwd: SCRIPTS_DIRECTORY, stdio: 'inherit' });
|
||||||
|
if (code !== 0)
|
||||||
|
throw new Error('Failed to install chrome-beta');
|
||||||
|
}
|
||||||
|
|
||||||
program
|
program
|
||||||
.command('install-deps [browserType...]')
|
.command('install-deps [browserType...]')
|
||||||
.description('install dependencies necessary to run browsers (will ask for sudo permissions)')
|
.description('install dependencies necessary to run browsers (will ask for sudo permissions)')
|
||||||
|
@ -17,7 +17,6 @@ import fs from 'fs';
|
|||||||
import * as util from 'util';
|
import * as util from 'util';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import { spawn } from 'child_process';
|
|
||||||
import { getUbuntuVersion } from '../utils/ubuntuVersion';
|
import { getUbuntuVersion } from '../utils/ubuntuVersion';
|
||||||
import * as registry from '../utils/registry';
|
import * as registry from '../utils/registry';
|
||||||
import * as utils from '../utils/utils';
|
import * as utils from '../utils/utils';
|
||||||
@ -218,7 +217,7 @@ async function missingFileDependenciesWindows(filePath: string): Promise<Array<s
|
|||||||
return [];
|
return [];
|
||||||
|
|
||||||
const dirname = path.dirname(filePath);
|
const dirname = path.dirname(filePath);
|
||||||
const {stdout, code} = await spawnAsync(executable, [filePath], {
|
const {stdout, code} = await utils.spawnAsync(executable, [filePath], {
|
||||||
cwd: dirname,
|
cwd: dirname,
|
||||||
env: {
|
env: {
|
||||||
...process.env,
|
...process.env,
|
||||||
@ -236,7 +235,7 @@ async function missingFileDependencies(filePath: string, extraLDPaths: string[])
|
|||||||
let LD_LIBRARY_PATH = extraLDPaths.join(':');
|
let LD_LIBRARY_PATH = extraLDPaths.join(':');
|
||||||
if (process.env.LD_LIBRARY_PATH)
|
if (process.env.LD_LIBRARY_PATH)
|
||||||
LD_LIBRARY_PATH = `${process.env.LD_LIBRARY_PATH}:${LD_LIBRARY_PATH}`;
|
LD_LIBRARY_PATH = `${process.env.LD_LIBRARY_PATH}:${LD_LIBRARY_PATH}`;
|
||||||
const {stdout, code} = await spawnAsync('ldd', [filePath], {
|
const {stdout, code} = await utils.spawnAsync('ldd', [filePath], {
|
||||||
cwd: dirname,
|
cwd: dirname,
|
||||||
env: {
|
env: {
|
||||||
...process.env,
|
...process.env,
|
||||||
@ -256,26 +255,13 @@ async function missingDLOPENLibraries(browserName: registry.BrowserName): Promis
|
|||||||
// NOTE: Using full-qualified path to `ldconfig` since `/sbin` is not part of the
|
// NOTE: Using full-qualified path to `ldconfig` since `/sbin` is not part of the
|
||||||
// default PATH in CRON.
|
// default PATH in CRON.
|
||||||
// @see https://github.com/microsoft/playwright/issues/3397
|
// @see https://github.com/microsoft/playwright/issues/3397
|
||||||
const {stdout, code, error} = await spawnAsync('/sbin/ldconfig', ['-p'], {});
|
const {stdout, code, error} = await utils.spawnAsync('/sbin/ldconfig', ['-p'], {});
|
||||||
if (code !== 0 || error)
|
if (code !== 0 || error)
|
||||||
return [];
|
return [];
|
||||||
const isLibraryAvailable = (library: string) => stdout.toLowerCase().includes(library.toLowerCase());
|
const isLibraryAvailable = (library: string) => stdout.toLowerCase().includes(library.toLowerCase());
|
||||||
return libraries.filter(library => !isLibraryAvailable(library));
|
return libraries.filter(library => !isLibraryAvailable(library));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function spawnAsync(cmd: string, args: string[], options: any): Promise<{stdout: string, stderr: string, code: number, error?: Error}> {
|
|
||||||
const process = spawn(cmd, args, options);
|
|
||||||
|
|
||||||
return new Promise(resolve => {
|
|
||||||
let stdout = '';
|
|
||||||
let stderr = '';
|
|
||||||
process.stdout.on('data', data => stdout += data);
|
|
||||||
process.stderr.on('data', data => stderr += data);
|
|
||||||
process.on('close', code => resolve({stdout, stderr, code}));
|
|
||||||
process.on('error', error => resolve({stdout, stderr, code: 0, error}));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This list is generted with the following program:
|
// This list is generted with the following program:
|
||||||
// ./utils/linux-browser-dependencies/run.sh ubuntu:18.04
|
// ./utils/linux-browser-dependencies/run.sh ubuntu:18.04
|
||||||
const LIBRARY_TO_PACKAGE_NAME_UBUNTU_18_04: { [s: string]: string} = {
|
const LIBRARY_TO_PACKAGE_NAME_UBUNTU_18_04: { [s: string]: string} = {
|
||||||
|
@ -23,7 +23,7 @@ import { getUbuntuVersionSync } from './ubuntuVersion';
|
|||||||
import { assert, getFromENV } from './utils';
|
import { assert, getFromENV } from './utils';
|
||||||
|
|
||||||
export type BrowserName = 'chromium'|'webkit'|'firefox'|'firefox-stable'|'ffmpeg'|'webkit-technology-preview';
|
export type BrowserName = 'chromium'|'webkit'|'firefox'|'firefox-stable'|'ffmpeg'|'webkit-technology-preview';
|
||||||
export const allBrowserNames: BrowserName[] = ['chromium', 'webkit', 'firefox', 'ffmpeg', 'webkit-technology-preview', 'firefox-stable'];
|
export const allBrowserNames: Set<BrowserName> = new Set(['chromium', 'webkit', 'firefox', 'ffmpeg', 'webkit-technology-preview', 'firefox-stable']);
|
||||||
|
|
||||||
const PACKAGE_PATH = path.join(__dirname, '..', '..');
|
const PACKAGE_PATH = path.join(__dirname, '..', '..');
|
||||||
|
|
||||||
|
@ -19,9 +19,25 @@ import fs from 'fs';
|
|||||||
import removeFolder from 'rimraf';
|
import removeFolder from 'rimraf';
|
||||||
import * as util from 'util';
|
import * as util from 'util';
|
||||||
import * as crypto from 'crypto';
|
import * as crypto from 'crypto';
|
||||||
|
import { spawn } from 'child_process';
|
||||||
|
|
||||||
const mkdirAsync = util.promisify(fs.mkdir.bind(fs));
|
const mkdirAsync = util.promisify(fs.mkdir.bind(fs));
|
||||||
|
|
||||||
|
export function spawnAsync(cmd: string, args: string[], options: any): Promise<{stdout: string, stderr: string, code: number, error?: Error}> {
|
||||||
|
const process = spawn(cmd, args, options);
|
||||||
|
|
||||||
|
return new Promise(resolve => {
|
||||||
|
let stdout = '';
|
||||||
|
let stderr = '';
|
||||||
|
if (process.stdout)
|
||||||
|
process.stdout.on('data', data => stdout += data);
|
||||||
|
if (process.stderr)
|
||||||
|
process.stderr.on('data', data => stderr += data);
|
||||||
|
process.on('close', code => resolve({stdout, stderr, code}));
|
||||||
|
process.on('error', error => resolve({stdout, stderr, code: 0, error}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// See https://joel.tools/microtasks/
|
// See https://joel.tools/microtasks/
|
||||||
export function makeWaitForNextTask() {
|
export function makeWaitForNextTask() {
|
||||||
// As of Mar 2021, Electorn v12 doesn't create new task with `setImmediate` despite
|
// As of Mar 2021, Electorn v12 doesn't create new task with `setImmediate` despite
|
||||||
|
Loading…
x
Reference in New Issue
Block a user