fix: print all missing libraries when used on unsupported linux distro (#12966)

This patch:
- Adds 3 new host platform types:
  * `generic-linux` and `generic-linux-arm64` for the unsupported
    linux distributions
  * `<unknown>` for non-supported OS versions
- Prints a warning when downloading Ubuntu browser builds on
  unsupported Linux distribution
- Makes sure launch doctor prints all missing shared libraries
  on unknown Linux distributions
- Also prints an `apt` command as an alternative to Playwright CLI
  dependency installation.
This commit is contained in:
Andrey Lushnikov 2022-03-23 15:06:14 -06:00 committed by GitHub
parent 4d41e51ee5
commit bbc1a4fea0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 32 deletions

View file

@ -155,9 +155,9 @@ export async function validateDependenciesLinux(sdkLanguage: string, linuxLddDir
const lddPaths: string[] = [];
for (const directoryPath of directoryPaths)
lddPaths.push(...(await executablesOrSharedLibraries(directoryPath)));
const allMissingDeps = await Promise.all(lddPaths.map(lddPath => missingFileDependencies(lddPath, directoryPaths)));
const missingDepsPerFile = await Promise.all(lddPaths.map(lddPath => missingFileDependencies(lddPath, directoryPaths)));
const missingDeps: Set<string> = new Set();
for (const deps of allMissingDeps) {
for (const deps of missingDepsPerFile) {
for (const dep of deps)
missingDeps.add(dep);
}
@ -165,6 +165,7 @@ export async function validateDependenciesLinux(sdkLanguage: string, linuxLddDir
missingDeps.add(dep);
if (!missingDeps.size)
return;
const allMissingDeps = new Set(missingDeps);
// Check Ubuntu version.
const missingPackages = new Set();
@ -182,41 +183,33 @@ export async function validateDependenciesLinux(sdkLanguage: string, linuxLddDir
}
const maybeSudo = (process.getuid() !== 0) && os.platform() !== 'win32' ? 'sudo ' : '';
// Happy path: known dependencies are missing for browsers.
// Suggest installation with a Playwright CLI.
const errorLines = [
`Host system is missing dependencies to run browsers.`,
];
if (missingPackages.size && !missingDeps.size) {
throw new Error('\n' + utils.wrapInASCIIBox([
`Host system is missing a few dependencies to run browsers.`,
// Happy path: known dependencies are missing for browsers.
// Suggest installation with a Playwright CLI.
errorLines.push(...[
`Please install them with the following command:`,
``,
` ${maybeSudo}${buildPlaywrightCLICommand(sdkLanguage, 'install-deps')}`,
``,
`Alternatively, use Aptitude:`,
` ${maybeSudo}apt-get install ${[...missingPackages].join('\\\n ')}`,
``,
`<3 Playwright Team`,
].join('\n'), 1));
]);
} else {
// Unhappy path: we either run on unknown distribution, or we failed to resolve all missing
// libraries to package names.
// Print missing libraries only:
errorLines.push(...[
`Missing libraries:`,
...[...allMissingDeps].map(dep => ' ' + dep),
]);
}
// Unhappy path - unusual distribution configuration.
let missingPackagesMessage = '';
if (missingPackages.size) {
missingPackagesMessage = [
` Install missing packages with:`,
` ${maybeSudo}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);
throw new Error('\n' + utils.wrapInASCIIBox(errorLines.join('\n'), 1));
}
function isSharedLib(basename: string) {

View file

@ -53,6 +53,9 @@ const EXECUTABLE_PATHS = {
const DOWNLOAD_PATHS = {
'chromium': {
'<unknown>': undefined,
'generic-linux': 'builds/chromium/%s/chromium-linux.zip',
'generic-linux-arm64': 'builds/chromium/%s/chromium-linux-arm64.zip',
'ubuntu18.04': 'builds/chromium/%s/chromium-linux.zip',
'ubuntu20.04': 'builds/chromium/%s/chromium-linux.zip',
'ubuntu18.04-arm64': 'builds/chromium/%s/chromium-linux-arm64.zip',
@ -67,6 +70,9 @@ const DOWNLOAD_PATHS = {
'win64': 'builds/chromium/%s/chromium-win64.zip',
},
'chromium-with-symbols': {
'<unknown>': undefined,
'generic-linux': 'builds/chromium/%s/chromium-with-symbols-linux.zip',
'generic-linux-arm64': 'builds/chromium/%s/chromium-with-symbols-linux-arm64.zip',
'ubuntu18.04': 'builds/chromium/%s/chromium-with-symbols-linux.zip',
'ubuntu20.04': 'builds/chromium/%s/chromium-with-symbols-linux.zip',
'ubuntu18.04-arm64': 'builds/chromium/%s/chromium-with-symbols-linux-arm64.zip',
@ -81,6 +87,9 @@ const DOWNLOAD_PATHS = {
'win64': 'builds/chromium/%s/chromium-with-symbols-win64.zip',
},
'firefox': {
'<unknown>': undefined,
'generic-linux': 'builds/firefox/%s/firefox-ubuntu-20.04.zip',
'generic-linux-arm64': 'builds/firefox/%s/firefox-ubuntu-20.04-arm64.zip',
'ubuntu18.04': 'builds/firefox/%s/firefox-ubuntu-18.04.zip',
'ubuntu20.04': 'builds/firefox/%s/firefox-ubuntu-20.04.zip',
'ubuntu18.04-arm64': undefined,
@ -95,6 +104,9 @@ const DOWNLOAD_PATHS = {
'win64': 'builds/firefox/%s/firefox-win64.zip',
},
'firefox-beta': {
'<unknown>': undefined,
'generic-linux': 'builds/firefox-beta/%s/firefox-beta-ubuntu-20.04.zip',
'generic-linux-arm64': undefined,
'ubuntu18.04': 'builds/firefox-beta/%s/firefox-beta-ubuntu-18.04.zip',
'ubuntu20.04': 'builds/firefox-beta/%s/firefox-beta-ubuntu-20.04.zip',
'ubuntu18.04-arm64': undefined,
@ -109,6 +121,9 @@ const DOWNLOAD_PATHS = {
'win64': 'builds/firefox-beta/%s/firefox-beta-win64.zip',
},
'webkit': {
'<unknown>': undefined,
'generic-linux': 'builds/webkit/%s/webkit-ubuntu-20.04.zip',
'generic-linux-arm64': 'builds/webkit/%s/webkit-ubuntu-20.04-arm64.zip',
'ubuntu18.04': 'builds/webkit/%s/webkit-ubuntu-18.04.zip',
'ubuntu20.04': 'builds/webkit/%s/webkit-ubuntu-20.04.zip',
'ubuntu18.04-arm64': undefined,
@ -123,6 +138,9 @@ const DOWNLOAD_PATHS = {
'win64': 'builds/webkit/%s/webkit-win64.zip',
},
'ffmpeg': {
'<unknown>': undefined,
'generic-linux': 'builds/ffmpeg/%s/ffmpeg-linux.zip',
'generic-linux-arm64': 'builds/ffmpeg/%s/ffmpeg-linux-arm64.zip',
'ubuntu18.04': 'builds/ffmpeg/%s/ffmpeg-linux.zip',
'ubuntu20.04': 'builds/ffmpeg/%s/ffmpeg-linux.zip',
'ubuntu18.04-arm64': 'builds/ffmpeg/%s/ffmpeg-linux-arm64.zip',
@ -593,6 +611,8 @@ export class Registry {
private async _downloadExecutable(descriptor: BrowsersJSONDescriptor, executablePath: string | undefined, downloadPathTemplate: string | undefined, downloadHostEnv: string) {
if (!downloadPathTemplate || !executablePath)
throw new Error(`ERROR: Playwright does not support ${descriptor.name} on ${hostPlatform}`);
if (hostPlatform === 'generic-linux' || hostPlatform === 'generic-linux-arm64')
logPolitely('BEWARE: your OS is not officially supported by Playwright; downloading Ubuntu build as a fallback.');
const downloadHost =
(downloadHostEnv && getFromENV(downloadHostEnv)) ||
getFromENV('PLAYWRIGHT_DOWNLOAD_HOST') ||

View file

@ -508,7 +508,9 @@ export type HostPlatform = 'win64' |
'mac11' | 'mac11-arm64' |
'mac12' | 'mac12-arm64' |
'ubuntu18.04' | 'ubuntu18.04-arm64' |
'ubuntu20.04' | 'ubuntu20.04-arm64';
'ubuntu20.04' | 'ubuntu20.04-arm64' |
'generic-linux' | 'generic-linux-arm64' |
'<unknown>';
export const hostPlatform = ((): HostPlatform => {
const platform = os.platform();
@ -534,15 +536,17 @@ export const hostPlatform = ((): HostPlatform => {
return macVersion as HostPlatform;
}
if (platform === 'linux') {
const ubuntuVersion = getUbuntuVersionSync();
const archSuffix = os.arch() === 'arm64' ? '-arm64' : '';
const ubuntuVersion = getUbuntuVersionSync();
if (!ubuntuVersion)
return ('generic-linux' + archSuffix) as HostPlatform;
if (parseInt(ubuntuVersion, 10) <= 19)
return ('ubuntu18.04' + archSuffix) as HostPlatform;
return ('ubuntu20.04' + archSuffix) as HostPlatform;
}
if (platform === 'win32')
return 'win64';
return platform as HostPlatform;
return '<unknown>';
})();
export function wrapInASCIIBox(text: string, padding = 0): string {