fix: always use ENV executable path when present (#7985)
Some recent changes to allow arm64 environments (including M1 macs) to launch a chromium installation successfully before arm-compatible builds were downloadable prevented the usage of PUPPETEER_EXECUTABLE_PATH in some environments. Currently, when the platform is not darwin and the arch is arm64, an executable cannot be specified using the environment variable. Generally speaking, environment variables have highest precedence for options such as this since they depend on system configuration. These change: 1. allow the ENV variable to always be used when defined and not specified in LaunchOptions (and when not puppeteer-core) 2. Retain the existing behavior of assuming /usr/bin/chromium-browser on platforms like Ubuntu (exact if-conditions preserved to avoid any breaking changes) 3. Add some tests for this particular portion of the code.
This commit is contained in:
parent
7e2b47c974
commit
6d6ea9bf59
@ -146,16 +146,10 @@ class ChromeLauncher implements ProductLauncher {
|
||||
|
||||
chromeExecutable = executablePathForChannel(channel);
|
||||
} else if (!executablePath) {
|
||||
// Use Intel x86 builds on Apple M1 until native macOS arm64
|
||||
// Chromium builds are available.
|
||||
if (os.platform() !== 'darwin' && os.arch() === 'arm64') {
|
||||
chromeExecutable = '/usr/bin/chromium-browser';
|
||||
} else {
|
||||
const { missingText, executablePath } = resolveExecutablePath(this);
|
||||
if (missingText) throw new Error(missingText);
|
||||
chromeExecutable = executablePath;
|
||||
}
|
||||
}
|
||||
|
||||
if (!chromeExecutable) {
|
||||
throw new Error('chromeExecutable is not found.');
|
||||
@ -799,9 +793,11 @@ function resolveExecutablePath(launcher: ChromeLauncher | FirefoxLauncher): {
|
||||
executablePath: string;
|
||||
missingText?: string;
|
||||
} {
|
||||
const { product, _isPuppeteerCore, _projectRoot, _preferredRevision } =
|
||||
launcher;
|
||||
let downloadPath: string | undefined;
|
||||
// puppeteer-core doesn't take into account PUPPETEER_* env variables.
|
||||
if (!launcher._isPuppeteerCore) {
|
||||
if (!_isPuppeteerCore) {
|
||||
const executablePath =
|
||||
process.env.PUPPETEER_EXECUTABLE_PATH ||
|
||||
process.env.npm_config_puppeteer_executable_path ||
|
||||
@ -813,22 +809,31 @@ function resolveExecutablePath(launcher: ChromeLauncher | FirefoxLauncher): {
|
||||
: undefined;
|
||||
return { executablePath, missingText };
|
||||
}
|
||||
const ubuntuChromiumPath = '/usr/bin/chromium-browser';
|
||||
if (
|
||||
product === 'chrome' &&
|
||||
os.platform() !== 'darwin' &&
|
||||
os.arch() === 'arm64' &&
|
||||
fs.existsSync(ubuntuChromiumPath)
|
||||
) {
|
||||
return { executablePath: ubuntuChromiumPath, missingText: undefined };
|
||||
}
|
||||
downloadPath =
|
||||
process.env.PUPPETEER_DOWNLOAD_PATH ||
|
||||
process.env.npm_config_puppeteer_download_path ||
|
||||
process.env.npm_package_config_puppeteer_download_path;
|
||||
}
|
||||
if (!launcher._projectRoot) {
|
||||
if (!_projectRoot) {
|
||||
throw new Error(
|
||||
'_projectRoot is undefined. Unable to create a BrowserFetcher.'
|
||||
);
|
||||
}
|
||||
const browserFetcher = new BrowserFetcher(launcher._projectRoot, {
|
||||
product: launcher.product,
|
||||
const browserFetcher = new BrowserFetcher(_projectRoot, {
|
||||
product: product,
|
||||
path: downloadPath,
|
||||
});
|
||||
|
||||
if (!launcher._isPuppeteerCore && launcher.product === 'chrome') {
|
||||
if (!_isPuppeteerCore && product === 'chrome') {
|
||||
const revision = process.env['PUPPETEER_CHROMIUM_REVISION'];
|
||||
if (revision) {
|
||||
const revisionInfo = browserFetcher.revisionInfo(revision);
|
||||
@ -839,13 +844,13 @@ function resolveExecutablePath(launcher: ChromeLauncher | FirefoxLauncher): {
|
||||
return { executablePath: revisionInfo.executablePath, missingText };
|
||||
}
|
||||
}
|
||||
const revisionInfo = browserFetcher.revisionInfo(launcher._preferredRevision);
|
||||
const revisionInfo = browserFetcher.revisionInfo(_preferredRevision);
|
||||
|
||||
const firefoxHelp = `Run \`PUPPETEER_PRODUCT=firefox npm install\` to download a supported Firefox browser binary.`;
|
||||
const chromeHelp = `Run \`npm install\` to download the correct Chromium revision (${launcher._preferredRevision}).`;
|
||||
const missingText = !revisionInfo.local
|
||||
? `Could not find expected browser (${launcher.product}) locally. ${
|
||||
launcher.product === 'chrome' ? chromeHelp : firefoxHelp
|
||||
? `Could not find expected browser (${product}) locally. ${
|
||||
product === 'chrome' ? chromeHelp : firefoxHelp
|
||||
}`
|
||||
: undefined;
|
||||
return { executablePath: revisionInfo.executablePath, missingText };
|
||||
|
@ -733,6 +733,88 @@ describe('Launcher specs', function () {
|
||||
const executablePath = puppeteer.executablePath('chrome');
|
||||
expect(executablePath).toBeTruthy();
|
||||
});
|
||||
describe('when PUPPETEER_EXECUTABLE_PATH is set', () => {
|
||||
const sandbox = sinon.createSandbox();
|
||||
|
||||
beforeEach(() => {
|
||||
process.env.PUPPETEER_EXECUTABLE_PATH = '';
|
||||
sandbox
|
||||
.stub(process.env, 'PUPPETEER_EXECUTABLE_PATH')
|
||||
.value('SOME_CUSTOM_EXECUTABLE');
|
||||
});
|
||||
|
||||
afterEach(() => sandbox.restore());
|
||||
|
||||
it('its value is returned', async () => {
|
||||
const { puppeteer } = getTestState();
|
||||
|
||||
const executablePath = puppeteer.executablePath();
|
||||
|
||||
expect(executablePath).toEqual('SOME_CUSTOM_EXECUTABLE');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the product is chrome, platform is not darwin, and arch is arm64', () => {
|
||||
describe('and the executable exists', () => {
|
||||
itChromeOnly('returns /usr/bin/chromium-browser', async () => {
|
||||
const { puppeteer } = getTestState();
|
||||
const osPlatformStub = sinon.stub(os, 'platform').returns('linux');
|
||||
const osArchStub = sinon.stub(os, 'arch').returns('arm64');
|
||||
const fsExistsStub = sinon.stub(fs, 'existsSync');
|
||||
fsExistsStub.withArgs('/usr/bin/chromium-browser').returns(true);
|
||||
|
||||
const executablePath = puppeteer.executablePath();
|
||||
|
||||
expect(executablePath).toEqual('/usr/bin/chromium-browser');
|
||||
|
||||
osPlatformStub.restore();
|
||||
osArchStub.restore();
|
||||
fsExistsStub.restore();
|
||||
});
|
||||
describe('and PUPPETEER_EXECUTABLE_PATH is set', () => {
|
||||
const sandbox = sinon.createSandbox();
|
||||
|
||||
beforeEach(() => {
|
||||
process.env.PUPPETEER_EXECUTABLE_PATH = '';
|
||||
sandbox
|
||||
.stub(process.env, 'PUPPETEER_EXECUTABLE_PATH')
|
||||
.value('SOME_CUSTOM_EXECUTABLE');
|
||||
});
|
||||
|
||||
afterEach(() => sandbox.restore());
|
||||
|
||||
it('its value is returned', async () => {
|
||||
const { puppeteer } = getTestState();
|
||||
|
||||
const executablePath = puppeteer.executablePath();
|
||||
|
||||
expect(executablePath).toEqual('SOME_CUSTOM_EXECUTABLE');
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('and the executable does not exist', () => {
|
||||
itChromeOnly(
|
||||
'does not return /usr/bin/chromium-browser',
|
||||
async () => {
|
||||
const { puppeteer } = getTestState();
|
||||
const osPlatformStub = sinon
|
||||
.stub(os, 'platform')
|
||||
.returns('linux');
|
||||
const osArchStub = sinon.stub(os, 'arch').returns('arm64');
|
||||
const fsExistsStub = sinon.stub(fs, 'existsSync');
|
||||
fsExistsStub.withArgs('/usr/bin/chromium-browser').returns(false);
|
||||
|
||||
const executablePath = puppeteer.executablePath();
|
||||
|
||||
expect(executablePath).not.toEqual('/usr/bin/chromium-browser');
|
||||
|
||||
osPlatformStub.restore();
|
||||
osArchStub.restore();
|
||||
fsExistsStub.restore();
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user