chore: move installDeps to Registry (#7431)
This is an effort to consolidate all handling of browser binaries in a single place.
This commit is contained in:
parent
e19d509c32
commit
4c7343fe96
|
|
@ -31,8 +31,7 @@ import { Page } from '../client/page';
|
||||||
import { BrowserType } from '../client/browserType';
|
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 { allBrowserNames, BrowserName, Registry } from '../utils/registry';
|
||||||
import { allBrowserNames, BrowserName } from '../utils/registry';
|
|
||||||
import * as utils from '../utils/utils';
|
import * as utils from '../utils/utils';
|
||||||
|
|
||||||
const SCRIPTS_DIRECTORY = path.join(__dirname, '..', '..', 'bin');
|
const SCRIPTS_DIRECTORY = path.join(__dirname, '..', '..', 'bin');
|
||||||
|
|
@ -182,9 +181,10 @@ async function installBrowserChannel(channel: BrowserChannel) {
|
||||||
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)')
|
||||||
.action(async function(browserType) {
|
.action(async function(browserTypes) {
|
||||||
try {
|
try {
|
||||||
await installDeps(browserType);
|
// TODO: verify the list and print supported browserTypes in the error message.
|
||||||
|
await Registry.currentPackageRegistry().installDeps(browserTypes);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(`Failed to install browser dependencies\n${e}`);
|
console.log(`Failed to install browser dependencies\n${e}`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import childProcess from 'child_process';
|
|
||||||
import os from 'os';
|
|
||||||
import path from 'path';
|
|
||||||
import { getUbuntuVersion } from '../utils/ubuntuVersion';
|
|
||||||
import * as utils from '../utils/utils';
|
|
||||||
|
|
||||||
const { deps } = require('../nativeDeps');
|
|
||||||
|
|
||||||
const SCRIPTS_DIRECTORY = path.join(__dirname, '..', '..', 'bin');
|
|
||||||
|
|
||||||
export async function installDeps(browserTypes: string[]) {
|
|
||||||
if (!browserTypes.length)
|
|
||||||
browserTypes = ['chromium', 'firefox', 'webkit'];
|
|
||||||
if (os.platform() === 'win32') {
|
|
||||||
if (browserTypes.includes('chromium')) {
|
|
||||||
const {code} = await utils.spawnAsync('powershell.exe', [path.join(SCRIPTS_DIRECTORY, 'install_media_pack.ps1')], { cwd: SCRIPTS_DIRECTORY, stdio: 'inherit' });
|
|
||||||
if (code !== 0)
|
|
||||||
throw new Error('Failed to install windows dependencies!');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (os.platform() !== 'linux')
|
|
||||||
return;
|
|
||||||
browserTypes.push('tools');
|
|
||||||
|
|
||||||
const ubuntuVersion = await getUbuntuVersion();
|
|
||||||
if (ubuntuVersion !== '18.04' && ubuntuVersion !== '20.04' && ubuntuVersion !== '21.04') {
|
|
||||||
console.warn('Cannot install dependencies for this linux distribution!'); // eslint-disable-line no-console
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const libraries: string[] = [];
|
|
||||||
for (const browserType of browserTypes) {
|
|
||||||
if (ubuntuVersion === '18.04')
|
|
||||||
libraries.push(...deps['bionic'][browserType]);
|
|
||||||
else if (ubuntuVersion === '20.04')
|
|
||||||
libraries.push(...deps['focal'][browserType]);
|
|
||||||
else if (ubuntuVersion === '21.04')
|
|
||||||
libraries.push(...deps['hirsute'][browserType]);
|
|
||||||
}
|
|
||||||
const uniqueLibraries = Array.from(new Set(libraries));
|
|
||||||
console.log('Installing Ubuntu dependencies...'); // eslint-disable-line no-console
|
|
||||||
const commands: string[] = [];
|
|
||||||
commands.push('apt-get update');
|
|
||||||
commands.push(['apt-get', 'install', '-y', '--no-install-recommends',
|
|
||||||
...uniqueLibraries,
|
|
||||||
].join(' '));
|
|
||||||
const isRoot = (process.getuid() === 0);
|
|
||||||
const child = isRoot ?
|
|
||||||
childProcess.spawn('sh', ['-c', `${commands.join('; ')}`], { stdio: 'inherit' }) :
|
|
||||||
childProcess.spawn('sudo', ['--', 'sh', '-c', `${commands.join('; ')}`], { stdio: 'inherit' });
|
|
||||||
await new Promise(f => child.on('exit', f));
|
|
||||||
}
|
|
||||||
|
|
@ -17,9 +17,12 @@
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
|
import childProcess from 'child_process';
|
||||||
import { getUbuntuVersion } from './ubuntuVersion';
|
import { getUbuntuVersion } from './ubuntuVersion';
|
||||||
import * as utils from './utils';
|
import * as utils from './utils';
|
||||||
|
|
||||||
|
const BIN_DIRECTORY = path.join(__dirname, '..', '..', 'bin');
|
||||||
|
|
||||||
const checkExecutable = (filePath: string) => fs.promises.access(filePath, fs.constants.X_OK).then(() => true).catch(e => false);
|
const checkExecutable = (filePath: string) => fs.promises.access(filePath, fs.constants.X_OK).then(() => true).catch(e => false);
|
||||||
|
|
||||||
function isSupportedWindowsVersion(): boolean {
|
function isSupportedWindowsVersion(): boolean {
|
||||||
|
|
@ -32,6 +35,45 @@ function isSupportedWindowsVersion(): boolean {
|
||||||
return major > 6 || (major === 6 && minor > 1);
|
return major > 6 || (major === 6 && minor > 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function installDependenciesWindows(targets: Set<'chromium' | 'firefox' | 'webkit' | 'tools'>) {
|
||||||
|
if (targets.has('chromium')) {
|
||||||
|
const {code} = await utils.spawnAsync('powershell.exe', [path.join(BIN_DIRECTORY, 'install_media_pack.ps1')], { cwd: BIN_DIRECTORY, stdio: 'inherit' });
|
||||||
|
if (code !== 0)
|
||||||
|
throw new Error('Failed to install windows dependencies!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function installDependenciesLinux(targets: Set<'chromium' | 'firefox' | 'webkit' | 'tools'>) {
|
||||||
|
const ubuntuVersion = await getUbuntuVersion();
|
||||||
|
if (ubuntuVersion !== '18.04' && ubuntuVersion !== '20.04' && ubuntuVersion !== '21.04') {
|
||||||
|
console.warn('Cannot install dependencies for this linux distribution!'); // eslint-disable-line no-console
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const libraries: string[] = [];
|
||||||
|
const { deps } = require('../nativeDeps');
|
||||||
|
for (const target of targets) {
|
||||||
|
if (ubuntuVersion === '18.04')
|
||||||
|
libraries.push(...deps['bionic'][target]);
|
||||||
|
else if (ubuntuVersion === '20.04')
|
||||||
|
libraries.push(...deps['focal'][target]);
|
||||||
|
else if (ubuntuVersion === '21.04')
|
||||||
|
libraries.push(...deps['hirsute'][target]);
|
||||||
|
}
|
||||||
|
const uniqueLibraries = Array.from(new Set(libraries));
|
||||||
|
console.log('Installing Ubuntu dependencies...'); // eslint-disable-line no-console
|
||||||
|
const commands: string[] = [];
|
||||||
|
commands.push('apt-get update');
|
||||||
|
commands.push(['apt-get', 'install', '-y', '--no-install-recommends',
|
||||||
|
...uniqueLibraries,
|
||||||
|
].join(' '));
|
||||||
|
const isRoot = (process.getuid() === 0);
|
||||||
|
const child = isRoot ?
|
||||||
|
childProcess.spawn('sh', ['-c', `${commands.join('; ')}`], { stdio: 'inherit' }) :
|
||||||
|
childProcess.spawn('sudo', ['--', 'sh', '-c', `${commands.join('; ')}`], { stdio: 'inherit' });
|
||||||
|
await new Promise(f => child.on('exit', f));
|
||||||
|
}
|
||||||
|
|
||||||
export async function validateDependenciesWindows(windowsExeAndDllDirectories: string[]) {
|
export async function validateDependenciesWindows(windowsExeAndDllDirectories: string[]) {
|
||||||
const directoryPaths = windowsExeAndDllDirectories;
|
const directoryPaths = windowsExeAndDllDirectories;
|
||||||
const lddPaths: string[] = [];
|
const lddPaths: string[] = [];
|
||||||
|
|
@ -20,7 +20,7 @@ import path from 'path';
|
||||||
import * as util from 'util';
|
import * as util from 'util';
|
||||||
import { getUbuntuVersion, getUbuntuVersionSync } from './ubuntuVersion';
|
import { getUbuntuVersion, getUbuntuVersionSync } from './ubuntuVersion';
|
||||||
import { assert, getFromENV, getAsBooleanFromENV } from './utils';
|
import { assert, getFromENV, getAsBooleanFromENV } from './utils';
|
||||||
import { validateDependenciesLinux, validateDependenciesWindows } from './validateDependencies';
|
import { installDependenciesLinux, installDependenciesWindows, validateDependenciesLinux, validateDependenciesWindows } from './dependencies';
|
||||||
|
|
||||||
export type BrowserName = 'chromium'|'chromium-with-symbols'|'webkit'|'firefox'|'firefox-beta'|'ffmpeg';
|
export type BrowserName = 'chromium'|'chromium-with-symbols'|'webkit'|'firefox'|'firefox-beta'|'ffmpeg';
|
||||||
export const allBrowserNames: Set<BrowserName> = new Set(['chromium', 'chromium-with-symbols', 'webkit', 'firefox', 'ffmpeg', 'firefox-beta']);
|
export const allBrowserNames: Set<BrowserName> = new Set(['chromium', 'chromium-with-symbols', 'webkit', 'firefox', 'ffmpeg', 'firefox-beta']);
|
||||||
|
|
@ -374,4 +374,23 @@ export class Registry {
|
||||||
return await validateDependenciesWindows(windowsExeAndDllDirectories);
|
return await validateDependenciesWindows(windowsExeAndDllDirectories);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async installDeps(browserNames: BrowserName[]) {
|
||||||
|
const targets = new Set<'chromium' | 'firefox' | 'webkit' | 'tools'>();
|
||||||
|
if (!browserNames.length)
|
||||||
|
browserNames = this.installByDefault();
|
||||||
|
for (const browserName of browserNames) {
|
||||||
|
if (browserName === 'chromium' || browserName === 'chromium-with-symbols')
|
||||||
|
targets.add('chromium');
|
||||||
|
if (browserName === 'firefox' || browserName === 'firefox-beta')
|
||||||
|
targets.add('firefox');
|
||||||
|
if (browserName === 'webkit')
|
||||||
|
targets.add('webkit');
|
||||||
|
}
|
||||||
|
targets.add('tools');
|
||||||
|
if (os.platform() === 'win32')
|
||||||
|
return await installDependenciesWindows(targets);
|
||||||
|
if (os.platform() === 'linux')
|
||||||
|
return await installDependenciesLinux(targets);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,21 @@
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
|
|
||||||
|
let ubuntuVersionCached: string | undefined;
|
||||||
|
|
||||||
export async function getUbuntuVersion(): Promise<string> {
|
export async function getUbuntuVersion(): Promise<string> {
|
||||||
|
if (ubuntuVersionCached === undefined)
|
||||||
|
ubuntuVersionCached = await getUbuntuVersionAsyncInternal();
|
||||||
|
return ubuntuVersionCached;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUbuntuVersionSync(): string {
|
||||||
|
if (ubuntuVersionCached === undefined)
|
||||||
|
ubuntuVersionCached = getUbuntuVersionSyncInternal();
|
||||||
|
return ubuntuVersionCached;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getUbuntuVersionAsyncInternal(): Promise<string> {
|
||||||
if (os.platform() !== 'linux')
|
if (os.platform() !== 'linux')
|
||||||
return '';
|
return '';
|
||||||
let osReleaseText = await fs.promises.readFile('/etc/upstream-release/lsb-release', 'utf8').catch(e => '');
|
let osReleaseText = await fs.promises.readFile('/etc/upstream-release/lsb-release', 'utf8').catch(e => '');
|
||||||
|
|
@ -26,10 +40,10 @@ export async function getUbuntuVersion(): Promise<string> {
|
||||||
osReleaseText = await fs.promises.readFile('/etc/os-release', 'utf8').catch(e => '');
|
osReleaseText = await fs.promises.readFile('/etc/os-release', 'utf8').catch(e => '');
|
||||||
if (!osReleaseText)
|
if (!osReleaseText)
|
||||||
return '';
|
return '';
|
||||||
return getUbuntuVersionInternal(osReleaseText);
|
return parseUbuntuVersion(osReleaseText);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUbuntuVersionSync(): string {
|
function getUbuntuVersionSyncInternal(): string {
|
||||||
if (os.platform() !== 'linux')
|
if (os.platform() !== 'linux')
|
||||||
return '';
|
return '';
|
||||||
try {
|
try {
|
||||||
|
|
@ -40,13 +54,13 @@ export function getUbuntuVersionSync(): string {
|
||||||
osReleaseText = fs.readFileSync('/etc/os-release', 'utf8');
|
osReleaseText = fs.readFileSync('/etc/os-release', 'utf8');
|
||||||
if (!osReleaseText)
|
if (!osReleaseText)
|
||||||
return '';
|
return '';
|
||||||
return getUbuntuVersionInternal(osReleaseText);
|
return parseUbuntuVersion(osReleaseText);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUbuntuVersionInternal(osReleaseText: string): string {
|
function parseUbuntuVersion(osReleaseText: string): string {
|
||||||
const fields = new Map();
|
const fields = new Map();
|
||||||
for (const line of osReleaseText.split('\n')) {
|
for (const line of osReleaseText.split('\n')) {
|
||||||
const tokens = line.split('=');
|
const tokens = line.split('=');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue