Skip to content

Commit

Permalink
devops: show package names instead of missing libs on Ubuntu 18.04
Browse files Browse the repository at this point in the history
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 microsoft#2745
  • Loading branch information
aslushnikov committed Jul 17, 2020
1 parent 056f0e2 commit f1b6970
Showing 1 changed file with 123 additions and 3 deletions.
126 changes: 123 additions & 3 deletions src/server/validateDependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 osRelease = await readFileAsync('/etc/os-release', 'utf8').catch(e => '');
const [ubuntuName = '', ubuntuVersion = ''] = osRelease.trim().split('\n');
if (ubuntuName.toLowerCase().includes('ubuntu') && ubuntuVersion.includes('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 -y ${[...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[]> {
Expand Down Expand Up @@ -86,3 +121,88 @@ function lddAsync(filePath: string): Promise<{stdout: string, stderr: string, co
ldd.on('close', code => resolve({stdout, stderr, code}));
});
}

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',
};

0 comments on commit f1b6970

Please sign in to comment.