diff --git a/.github/workflows/tests_secondary.yml b/.github/workflows/tests_secondary.yml index 5200c86a59..1ad2c523bf 100644 --- a/.github/workflows/tests_secondary.yml +++ b/.github/workflows/tests_secondary.yml @@ -472,7 +472,6 @@ jobs: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - - run: ./utils/install-chrome-beta/reinstall_linux.sh - uses: actions/setup-node@v2 with: node-version: 12 @@ -481,7 +480,7 @@ jobs: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: npm run build - 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 # 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" @@ -500,8 +499,6 @@ jobs: runs-on: windows-latest steps: - uses: actions/checkout@v2 - - name: Install Chrome Beta - run: pwsh -command ".\$GITHUB_WORKSPACE\utils\install-chrome-beta\reinstall_win.ps1" - name: Install Media Pack shell: powershell run: Install-WindowsFeature Server-Media-Foundation @@ -512,7 +509,7 @@ jobs: env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: npm run build - - run: node lib/cli/cli install ffmpeg + - run: node lib/cli/cli install chrome-beta - run: npm run ctest shell: bash env: @@ -531,7 +528,6 @@ jobs: runs-on: macos-10.15 steps: - uses: actions/checkout@v2 - - run: ./utils/install-chrome-beta/reinstall_mac.sh - uses: actions/setup-node@v2 with: node-version: 12 @@ -539,7 +535,7 @@ jobs: env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: npm run build - - run: node lib/cli/cli install ffmpeg + - run: node lib/cli/cli install chrome-beta - run: npm run ctest env: PWTEST_CHANNEL: chrome-beta diff --git a/utils/install-chrome-beta/reinstall_linux.sh b/bin/reinstall_chrome_beta_linux.sh similarity index 100% rename from utils/install-chrome-beta/reinstall_linux.sh rename to bin/reinstall_chrome_beta_linux.sh diff --git a/utils/install-chrome-beta/reinstall_mac.sh b/bin/reinstall_chrome_beta_mac.sh similarity index 100% rename from utils/install-chrome-beta/reinstall_mac.sh rename to bin/reinstall_chrome_beta_mac.sh diff --git a/utils/install-chrome-beta/reinstall_win.ps1 b/bin/reinstall_chrome_beta_win.ps1 similarity index 100% rename from utils/install-chrome-beta/reinstall_win.ps1 rename to bin/reinstall_chrome_beta_win.ps1 diff --git a/packages/build_package.js b/packages/build_package.js index 9c5ab40611..e12f60518b 100755 --- a/packages/build_package.js +++ b/packages/build_package.js @@ -28,7 +28,7 @@ const cpAsync = util.promisify(ncp); const SCRIPT_NAME = path.basename(__filename); 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 = { 'playwright': { diff --git a/src/cli/cli.ts b/src/cli/cli.ts index 08726450ad..e2408945c8 100755 --- a/src/cli/cli.ts +++ b/src/cli/cli.ts @@ -34,7 +34,13 @@ import { BrowserType } from '../client/browserType'; import { BrowserContextOptions, LaunchOptions } from '../client/types'; import { spawn } from 'child_process'; 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 = new Set(['chrome-beta']); program .version('Version ' + require('../../package.json').version) @@ -86,24 +92,56 @@ program program .command('install [browserType...]') .description('ensure browsers necessary for this version of Playwright are installed') - .action(async function(browserTypes) { + .action(async function(args) { try { - const allBrowsers = new Set(allBrowserNames); - for (const browserType of browserTypes) { - if (!allBrowsers.has(browserType)) { - console.log(`Invalid browser name: '${browserType}'. Expecting one of: ${allBrowserNames.map(name => `'${name}'`).join(', ')}`); - process.exit(1); - } + // Install default browsers when invoked without arguments. + if (!args.length) { + await installBrowsers(); + return; + } + const browserNames: Set = new Set(args.filter((browser: any) => allBrowserNames.has(browser))); + const browserChannels: Set = 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) { console.log(`Failed to install browsers\n${e}`); 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 .command('install-deps [browserType...]') .description('install dependencies necessary to run browsers (will ask for sudo permissions)') diff --git a/src/server/validateDependencies.ts b/src/server/validateDependencies.ts index e917e026f1..765eceac6b 100644 --- a/src/server/validateDependencies.ts +++ b/src/server/validateDependencies.ts @@ -17,7 +17,6 @@ import fs from 'fs'; import * as util from 'util'; import path from 'path'; import * as os from 'os'; -import { spawn } from 'child_process'; import { getUbuntuVersion } from '../utils/ubuntuVersion'; import * as registry from '../utils/registry'; import * as utils from '../utils/utils'; @@ -218,7 +217,7 @@ async function missingFileDependenciesWindows(filePath: string): Promise stdout.toLowerCase().includes(library.toLowerCase()); 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: // ./utils/linux-browser-dependencies/run.sh ubuntu:18.04 const LIBRARY_TO_PACKAGE_NAME_UBUNTU_18_04: { [s: string]: string} = { diff --git a/src/utils/registry.ts b/src/utils/registry.ts index 2c14aef6fc..526b16c397 100644 --- a/src/utils/registry.ts +++ b/src/utils/registry.ts @@ -23,7 +23,7 @@ import { getUbuntuVersionSync } from './ubuntuVersion'; import { assert, getFromENV } from './utils'; 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 = new Set(['chromium', 'webkit', 'firefox', 'ffmpeg', 'webkit-technology-preview', 'firefox-stable']); const PACKAGE_PATH = path.join(__dirname, '..', '..'); diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 5de864c371..c77c045046 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -19,9 +19,25 @@ import fs from 'fs'; import removeFolder from 'rimraf'; import * as util from 'util'; import * as crypto from 'crypto'; +import { spawn } from 'child_process'; 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/ export function makeWaitForNextTask() { // As of Mar 2021, Electorn v12 doesn't create new task with `setImmediate` despite