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:
parent
4d41e51ee5
commit
bbc1a4fea0
|
|
@ -155,9 +155,9 @@ export async function validateDependenciesLinux(sdkLanguage: string, linuxLddDir
|
||||||
const lddPaths: string[] = [];
|
const lddPaths: string[] = [];
|
||||||
for (const directoryPath of directoryPaths)
|
for (const directoryPath of directoryPaths)
|
||||||
lddPaths.push(...(await executablesOrSharedLibraries(directoryPath)));
|
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();
|
const missingDeps: Set<string> = new Set();
|
||||||
for (const deps of allMissingDeps) {
|
for (const deps of missingDepsPerFile) {
|
||||||
for (const dep of deps)
|
for (const dep of deps)
|
||||||
missingDeps.add(dep);
|
missingDeps.add(dep);
|
||||||
}
|
}
|
||||||
|
|
@ -165,6 +165,7 @@ export async function validateDependenciesLinux(sdkLanguage: string, linuxLddDir
|
||||||
missingDeps.add(dep);
|
missingDeps.add(dep);
|
||||||
if (!missingDeps.size)
|
if (!missingDeps.size)
|
||||||
return;
|
return;
|
||||||
|
const allMissingDeps = new Set(missingDeps);
|
||||||
// Check Ubuntu version.
|
// Check Ubuntu version.
|
||||||
const missingPackages = new Set();
|
const missingPackages = new Set();
|
||||||
|
|
||||||
|
|
@ -182,41 +183,33 @@ export async function validateDependenciesLinux(sdkLanguage: string, linuxLddDir
|
||||||
}
|
}
|
||||||
|
|
||||||
const maybeSudo = (process.getuid() !== 0) && os.platform() !== 'win32' ? 'sudo ' : '';
|
const maybeSudo = (process.getuid() !== 0) && os.platform() !== 'win32' ? 'sudo ' : '';
|
||||||
// Happy path: known dependencies are missing for browsers.
|
const errorLines = [
|
||||||
// Suggest installation with a Playwright CLI.
|
`Host system is missing dependencies to run browsers.`,
|
||||||
|
];
|
||||||
if (missingPackages.size && !missingDeps.size) {
|
if (missingPackages.size && !missingDeps.size) {
|
||||||
throw new Error('\n' + utils.wrapInASCIIBox([
|
// Happy path: known dependencies are missing for browsers.
|
||||||
`Host system is missing a few dependencies to run browsers.`,
|
// Suggest installation with a Playwright CLI.
|
||||||
|
errorLines.push(...[
|
||||||
`Please install them with the following command:`,
|
`Please install them with the following command:`,
|
||||||
``,
|
``,
|
||||||
` ${maybeSudo}${buildPlaywrightCLICommand(sdkLanguage, 'install-deps')}`,
|
` ${maybeSudo}${buildPlaywrightCLICommand(sdkLanguage, 'install-deps')}`,
|
||||||
``,
|
``,
|
||||||
|
`Alternatively, use Aptitude:`,
|
||||||
|
` ${maybeSudo}apt-get install ${[...missingPackages].join('\\\n ')}`,
|
||||||
|
``,
|
||||||
`<3 Playwright Team`,
|
`<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.
|
throw new Error('\n' + utils.wrapInASCIIBox(errorLines.join('\n'), 1));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSharedLib(basename: string) {
|
function isSharedLib(basename: string) {
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,9 @@ const EXECUTABLE_PATHS = {
|
||||||
|
|
||||||
const DOWNLOAD_PATHS = {
|
const DOWNLOAD_PATHS = {
|
||||||
'chromium': {
|
'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',
|
'ubuntu18.04': 'builds/chromium/%s/chromium-linux.zip',
|
||||||
'ubuntu20.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',
|
'ubuntu18.04-arm64': 'builds/chromium/%s/chromium-linux-arm64.zip',
|
||||||
|
|
@ -67,6 +70,9 @@ const DOWNLOAD_PATHS = {
|
||||||
'win64': 'builds/chromium/%s/chromium-win64.zip',
|
'win64': 'builds/chromium/%s/chromium-win64.zip',
|
||||||
},
|
},
|
||||||
'chromium-with-symbols': {
|
'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',
|
'ubuntu18.04': 'builds/chromium/%s/chromium-with-symbols-linux.zip',
|
||||||
'ubuntu20.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',
|
'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',
|
'win64': 'builds/chromium/%s/chromium-with-symbols-win64.zip',
|
||||||
},
|
},
|
||||||
'firefox': {
|
'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',
|
'ubuntu18.04': 'builds/firefox/%s/firefox-ubuntu-18.04.zip',
|
||||||
'ubuntu20.04': 'builds/firefox/%s/firefox-ubuntu-20.04.zip',
|
'ubuntu20.04': 'builds/firefox/%s/firefox-ubuntu-20.04.zip',
|
||||||
'ubuntu18.04-arm64': undefined,
|
'ubuntu18.04-arm64': undefined,
|
||||||
|
|
@ -95,6 +104,9 @@ const DOWNLOAD_PATHS = {
|
||||||
'win64': 'builds/firefox/%s/firefox-win64.zip',
|
'win64': 'builds/firefox/%s/firefox-win64.zip',
|
||||||
},
|
},
|
||||||
'firefox-beta': {
|
'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',
|
'ubuntu18.04': 'builds/firefox-beta/%s/firefox-beta-ubuntu-18.04.zip',
|
||||||
'ubuntu20.04': 'builds/firefox-beta/%s/firefox-beta-ubuntu-20.04.zip',
|
'ubuntu20.04': 'builds/firefox-beta/%s/firefox-beta-ubuntu-20.04.zip',
|
||||||
'ubuntu18.04-arm64': undefined,
|
'ubuntu18.04-arm64': undefined,
|
||||||
|
|
@ -109,6 +121,9 @@ const DOWNLOAD_PATHS = {
|
||||||
'win64': 'builds/firefox-beta/%s/firefox-beta-win64.zip',
|
'win64': 'builds/firefox-beta/%s/firefox-beta-win64.zip',
|
||||||
},
|
},
|
||||||
'webkit': {
|
'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',
|
'ubuntu18.04': 'builds/webkit/%s/webkit-ubuntu-18.04.zip',
|
||||||
'ubuntu20.04': 'builds/webkit/%s/webkit-ubuntu-20.04.zip',
|
'ubuntu20.04': 'builds/webkit/%s/webkit-ubuntu-20.04.zip',
|
||||||
'ubuntu18.04-arm64': undefined,
|
'ubuntu18.04-arm64': undefined,
|
||||||
|
|
@ -123,6 +138,9 @@ const DOWNLOAD_PATHS = {
|
||||||
'win64': 'builds/webkit/%s/webkit-win64.zip',
|
'win64': 'builds/webkit/%s/webkit-win64.zip',
|
||||||
},
|
},
|
||||||
'ffmpeg': {
|
'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',
|
'ubuntu18.04': 'builds/ffmpeg/%s/ffmpeg-linux.zip',
|
||||||
'ubuntu20.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',
|
'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) {
|
private async _downloadExecutable(descriptor: BrowsersJSONDescriptor, executablePath: string | undefined, downloadPathTemplate: string | undefined, downloadHostEnv: string) {
|
||||||
if (!downloadPathTemplate || !executablePath)
|
if (!downloadPathTemplate || !executablePath)
|
||||||
throw new Error(`ERROR: Playwright does not support ${descriptor.name} on ${hostPlatform}`);
|
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 =
|
const downloadHost =
|
||||||
(downloadHostEnv && getFromENV(downloadHostEnv)) ||
|
(downloadHostEnv && getFromENV(downloadHostEnv)) ||
|
||||||
getFromENV('PLAYWRIGHT_DOWNLOAD_HOST') ||
|
getFromENV('PLAYWRIGHT_DOWNLOAD_HOST') ||
|
||||||
|
|
|
||||||
|
|
@ -508,7 +508,9 @@ export type HostPlatform = 'win64' |
|
||||||
'mac11' | 'mac11-arm64' |
|
'mac11' | 'mac11-arm64' |
|
||||||
'mac12' | 'mac12-arm64' |
|
'mac12' | 'mac12-arm64' |
|
||||||
'ubuntu18.04' | 'ubuntu18.04-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 => {
|
export const hostPlatform = ((): HostPlatform => {
|
||||||
const platform = os.platform();
|
const platform = os.platform();
|
||||||
|
|
@ -534,15 +536,17 @@ export const hostPlatform = ((): HostPlatform => {
|
||||||
return macVersion as HostPlatform;
|
return macVersion as HostPlatform;
|
||||||
}
|
}
|
||||||
if (platform === 'linux') {
|
if (platform === 'linux') {
|
||||||
const ubuntuVersion = getUbuntuVersionSync();
|
|
||||||
const archSuffix = os.arch() === 'arm64' ? '-arm64' : '';
|
const archSuffix = os.arch() === 'arm64' ? '-arm64' : '';
|
||||||
|
const ubuntuVersion = getUbuntuVersionSync();
|
||||||
|
if (!ubuntuVersion)
|
||||||
|
return ('generic-linux' + archSuffix) as HostPlatform;
|
||||||
if (parseInt(ubuntuVersion, 10) <= 19)
|
if (parseInt(ubuntuVersion, 10) <= 19)
|
||||||
return ('ubuntu18.04' + archSuffix) as HostPlatform;
|
return ('ubuntu18.04' + archSuffix) as HostPlatform;
|
||||||
return ('ubuntu20.04' + archSuffix) as HostPlatform;
|
return ('ubuntu20.04' + archSuffix) as HostPlatform;
|
||||||
}
|
}
|
||||||
if (platform === 'win32')
|
if (platform === 'win32')
|
||||||
return 'win64';
|
return 'win64';
|
||||||
return platform as HostPlatform;
|
return '<unknown>';
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export function wrapInASCIIBox(text: string, padding = 0): string {
|
export function wrapInASCIIBox(text: string, padding = 0): string {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue