mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-18 08:41:49 +03:00
devops: show package names instead of missing libs on Ubuntu 18.04 (#3013)
This patch starts putting package names to install on Ubuntu instead of missing dependencies list. The mapping of library to package name is obtained using the following script: https://gist.github.com/aslushnikov/2766200430228c3700537292fccad064 References #2745
This commit is contained in:
parent
ef2a6522b8
commit
9a2245d30a
@ -24,6 +24,7 @@ const accessAsync = util.promisify(fs.access.bind(fs));
|
||||
const checkExecutable = (filePath: string) => accessAsync(filePath, fs.constants.X_OK).then(() => true).catch(e => false);
|
||||
const statAsync = util.promisify(fs.stat.bind(fs));
|
||||
const readdirAsync = util.promisify(fs.readdir.bind(fs));
|
||||
const readFileAsync = util.promisify(fs.readFile.bind(fs));
|
||||
|
||||
export async function validateDependencies(browserPath: string, browser: BrowserDescriptor) {
|
||||
// We currently only support Linux.
|
||||
@ -34,15 +35,49 @@ export async function validateDependencies(browserPath: string, browser: Browser
|
||||
for (const directoryPath of directoryPaths)
|
||||
lddPaths.push(...(await executablesOrSharedLibraries(directoryPath)));
|
||||
const allMissingDeps = await Promise.all(lddPaths.map(lddPath => missingFileDependencies(lddPath)));
|
||||
const missingDeps = new Set();
|
||||
const missingDeps: Set<string> = new Set();
|
||||
for (const deps of allMissingDeps) {
|
||||
for (const dep of deps)
|
||||
missingDeps.add(dep);
|
||||
}
|
||||
if (!missingDeps.size)
|
||||
return;
|
||||
const deps = [...missingDeps].sort().map(dep => ' ' + dep).join('\n');
|
||||
throw new Error('Host system is missing the following dependencies to run browser\n' + deps);
|
||||
// Check Ubuntu version.
|
||||
const missingPackages = new Set();
|
||||
|
||||
const ubuntuVersion = await getUbuntuVersion();
|
||||
if (ubuntuVersion === '18.04') {
|
||||
// Translate missing dependencies to package names to install with apt.
|
||||
for (const missingDep of missingDeps) {
|
||||
const packageName = LIBRARY_TO_PACKAGE_NAME_UBUNTU_18_04[missingDep];
|
||||
if (packageName) {
|
||||
missingPackages.add(packageName);
|
||||
missingDeps.delete(missingDep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let missingPackagesMessage = '';
|
||||
if (missingPackages.size) {
|
||||
missingPackagesMessage = [
|
||||
` Install missing packages with:`,
|
||||
` apt-get install ${[...missingPackages].join('\\\n ')}`,
|
||||
``,
|
||||
``,
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
let missingDependenciesMessage = '';
|
||||
if (missingDeps.size) {
|
||||
const header = missingPackages.size ? `Missing libraries we didn't find packages for:` : `Missing libraries are:`;
|
||||
missingDependenciesMessage = [
|
||||
` ${header}`,
|
||||
` ${[...missingDeps].join('\n ')}`,
|
||||
``,
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
throw new Error('Host system is missing dependencies!\n\n' + missingPackagesMessage + missingDependenciesMessage);
|
||||
}
|
||||
|
||||
async function executablesOrSharedLibraries(directoryPath: string): Promise<string[]> {
|
||||
@ -86,3 +121,109 @@ function lddAsync(filePath: string): Promise<{stdout: string, stderr: string, co
|
||||
ldd.on('close', code => resolve({stdout, stderr, code}));
|
||||
});
|
||||
}
|
||||
|
||||
async function getUbuntuVersion(): Promise<string> {
|
||||
const osRelease = await readFileAsync('/etc/os-release', 'utf8').catch(e => '');
|
||||
if (!osRelease)
|
||||
return '';
|
||||
const fields = new Map();
|
||||
for (const line of osRelease.split('\n')) {
|
||||
const tokens = line.split('=');
|
||||
const name = tokens.shift();
|
||||
let value = tokens.join('=').trim();
|
||||
if (value.startsWith('"') && value.endsWith('"'))
|
||||
value = value.substring(1, value.length - 1);
|
||||
if (!name)
|
||||
continue;
|
||||
fields.set(name.toLowerCase(), value);
|
||||
}
|
||||
if (!fields.get('name') || fields.get('name').toLowerCase() !== 'ubuntu')
|
||||
return '';
|
||||
return fields.get('version_id') || '';
|
||||
}
|
||||
|
||||
// This list is generated with https://gist.github.com/aslushnikov/2766200430228c3700537292fccad064
|
||||
const LIBRARY_TO_PACKAGE_NAME_UBUNTU_18_04: { [s: string]: string} = {
|
||||
'libEGL.so.1': 'libegl1',
|
||||
'libGL.so.1': 'libgl1',
|
||||
'libX11-xcb.so.1': 'libx11-xcb1',
|
||||
'libX11.so.6': 'libx11-6',
|
||||
'libXcomposite.so.1': 'libxcomposite1',
|
||||
'libXcursor.so.1': 'libxcursor1',
|
||||
'libXdamage.so.1': 'libxdamage1',
|
||||
'libXext.so.6': 'libxext6',
|
||||
'libXfixes.so.3': 'libxfixes3',
|
||||
'libXi.so.6': 'libxi6',
|
||||
'libXrandr.so.2': 'libxrandr2',
|
||||
'libXrender.so.1': 'libxrender1',
|
||||
'libXt.so.6': 'libxt6',
|
||||
'libXtst.so.6': 'libxtst6',
|
||||
'libasound.so.2': 'libasound2',
|
||||
'libatk-1.0.so.0': 'libatk1.0-0',
|
||||
'libatk-bridge-2.0.so.0': 'libatk-bridge2.0-0',
|
||||
'libatspi.so.0': 'libatspi2.0-0',
|
||||
'libbrotlidec.so.1': 'libbrotli1',
|
||||
'libcairo-gobject.so.2': 'libcairo-gobject2',
|
||||
'libcairo.so.2': 'libcairo2',
|
||||
'libcups.so.2': 'libcups2',
|
||||
'libdbus-1.so.3': 'libdbus-1-3',
|
||||
'libdbus-glib-1.so.2': 'libdbus-glib-1-2',
|
||||
'libdrm.so.2': 'libdrm2',
|
||||
'libenchant.so.1': 'libenchant1c2a',
|
||||
'libepoxy.so.0': 'libepoxy0',
|
||||
'libfontconfig.so.1': 'libfontconfig1',
|
||||
'libfreetype.so.6': 'libfreetype6',
|
||||
'libgbm.so.1': 'libgbm1',
|
||||
'libgdk-3.so.0': 'libgtk-3-0',
|
||||
'libgdk-x11-2.0.so.0': 'libgtk2.0-0',
|
||||
'libgdk_pixbuf-2.0.so.0': 'libgdk-pixbuf2.0-0',
|
||||
'libgio-2.0.so.0': 'libglib2.0-0',
|
||||
'libglib-2.0.so.0': 'libglib2.0-0',
|
||||
'libgmodule-2.0.so.0': 'libglib2.0-0',
|
||||
'libgobject-2.0.so.0': 'libglib2.0-0',
|
||||
'libgstapp-1.0.so.0': 'libgstreamer-plugins-base1.0-0',
|
||||
'libgstaudio-1.0.so.0': 'libgstreamer-plugins-base1.0-0',
|
||||
'libgstbase-1.0.so.0': 'libgstreamer1.0-0',
|
||||
'libgstcodecparsers-1.0.so.0': 'libgstreamer-plugins-bad1.0-0',
|
||||
'libgstfft-1.0.so.0': 'libgstreamer-plugins-base1.0-0',
|
||||
'libgstgl-1.0.so.0': 'libgstreamer-gl1.0-0',
|
||||
'libgstpbutils-1.0.so.0': 'libgstreamer-plugins-base1.0-0',
|
||||
'libgstreamer-1.0.so.0': 'libgstreamer1.0-0',
|
||||
'libgsttag-1.0.so.0': 'libgstreamer-plugins-base1.0-0',
|
||||
'libgstvideo-1.0.so.0': 'libgstreamer-plugins-base1.0-0',
|
||||
'libgthread-2.0.so.0': 'libglib2.0-0',
|
||||
'libgtk-3.so.0': 'libgtk-3-0',
|
||||
'libgtk-x11-2.0.so.0': 'libgtk2.0-0',
|
||||
'libharfbuzz-icu.so.0': 'libharfbuzz-icu0',
|
||||
'libharfbuzz.so.0': 'libharfbuzz0b',
|
||||
'libhyphen.so.0': 'libhyphen0',
|
||||
'libicui18n.so.60': 'libicu60',
|
||||
'libicuuc.so.60': 'libicu60',
|
||||
'libjpeg.so.8': 'libjpeg-turbo8',
|
||||
'libnotify.so.4': 'libnotify4',
|
||||
'libnspr4.so': 'libnspr4',
|
||||
'libnss3.so': 'libnss3',
|
||||
'libnssutil3.so': 'libnss3',
|
||||
'libopenjp2.so.7': 'libopenjp2-7',
|
||||
'libopus.so.0': 'libopus0',
|
||||
'libpango-1.0.so.0': 'libpango-1.0-0',
|
||||
'libpangocairo-1.0.so.0': 'libpangocairo-1.0-0',
|
||||
'libpangoft2-1.0.so.0': 'libpangoft2-1.0-0',
|
||||
'libpng16.so.16': 'libpng16-16',
|
||||
'libsecret-1.so.0': 'libsecret-1-0',
|
||||
'libsmime3.so': 'libnss3',
|
||||
'libssl3.so': 'libnss3',
|
||||
'libwayland-client.so.0': 'libwayland-client0',
|
||||
'libwayland-egl.so.1': 'libwayland-egl1',
|
||||
'libwayland-server.so.0': 'libwayland-server0',
|
||||
'libwebp.so.6': 'libwebp6',
|
||||
'libwebpdemux.so.2': 'libwebpdemux2',
|
||||
'libwoff2dec.so.1.0.2': 'libwoff1',
|
||||
'libxcb-dri3.so.0': 'libxcb-dri3-0',
|
||||
'libxcb-shm.so.0': 'libxcb-shm0',
|
||||
'libxcb.so.1': 'libxcb1',
|
||||
'libxkbcommon.so.0': 'libxkbcommon0',
|
||||
'libxml2.so.2': 'libxml2',
|
||||
'libxslt.so.1': 'libxslt1.1',
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user