feat: add support for Apple Silicon chromium builds (#7546)

Google has published Chromium builds for Apple Silicon so we can fetch it now

Related to #6622
This commit is contained in:
Valentin Semirulnik 2022-05-05 10:33:19 +03:00 committed by GitHub
parent 2804ae8cdb
commit baa017db92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 39 additions and 20 deletions

View File

@ -253,6 +253,13 @@ PUPPETEER_PRODUCT=firefox node install.js
PUPPETEER_PRODUCT=firefox npm run unit PUPPETEER_PRODUCT=firefox npm run unit
``` ```
- To run experimental Chromium MacOS ARM tests, firstly ensure you have correct Chromium version installed locally (you only need to do this once, not on every test run) and then you can run the tests:
```bash
PUPPETEER_EXPERIMENTAL_CHROMIUM_MAC_ARM=1 node install.js
PUPPETEER_EXPERIMENTAL_CHROMIUM_MAC_ARM=1 npm run unit
```
- To run tests with custom browser executable: - To run tests with custom browser executable:
```bash ```bash

View File

@ -487,6 +487,7 @@ If Puppeteer doesn't find them in the environment during the installation step,
- `PUPPETEER_CHROMIUM_REVISION` - specify a certain version of Chromium you'd like Puppeteer to use. See [puppeteer.launch([options])](#puppeteerlaunchoptions) on how executable path is inferred. **BEWARE**: Puppeteer is only [guaranteed to work](https://github.com/puppeteer/puppeteer/#q-why-doesnt-puppeteer-vxxx-work-with-chromium-vyyy) with the bundled Chromium, use at your own risk. - `PUPPETEER_CHROMIUM_REVISION` - specify a certain version of Chromium you'd like Puppeteer to use. See [puppeteer.launch([options])](#puppeteerlaunchoptions) on how executable path is inferred. **BEWARE**: Puppeteer is only [guaranteed to work](https://github.com/puppeteer/puppeteer/#q-why-doesnt-puppeteer-vxxx-work-with-chromium-vyyy) with the bundled Chromium, use at your own risk.
- `PUPPETEER_EXECUTABLE_PATH` - specify an executable path to be used in `puppeteer.launch`. See [puppeteer.launch([options])](#puppeteerlaunchoptions) on how the executable path is inferred. **BEWARE**: Puppeteer is only [guaranteed to work](https://github.com/puppeteer/puppeteer/#q-why-doesnt-puppeteer-vxxx-work-with-chromium-vyyy) with the bundled Chromium, use at your own risk. - `PUPPETEER_EXECUTABLE_PATH` - specify an executable path to be used in `puppeteer.launch`. See [puppeteer.launch([options])](#puppeteerlaunchoptions) on how the executable path is inferred. **BEWARE**: Puppeteer is only [guaranteed to work](https://github.com/puppeteer/puppeteer/#q-why-doesnt-puppeteer-vxxx-work-with-chromium-vyyy) with the bundled Chromium, use at your own risk.
- `PUPPETEER_PRODUCT` - specify which browser you'd like Puppeteer to use. Must be one of `chrome` or `firefox`. This can also be used during installation to fetch the recommended browser binary. Setting `product` programmatically in [puppeteer.launch([options])](#puppeteerlaunchoptions) supersedes this environment variable. The product is exposed in [`puppeteer.product`](#puppeteerproduct) - `PUPPETEER_PRODUCT` - specify which browser you'd like Puppeteer to use. Must be one of `chrome` or `firefox`. This can also be used during installation to fetch the recommended browser binary. Setting `product` programmatically in [puppeteer.launch([options])](#puppeteerlaunchoptions) supersedes this environment variable. The product is exposed in [`puppeteer.product`](#puppeteerproduct)
- `PUPPETEER_EXPERIMENTAL_CHROMIUM_MAC_ARM` — specify Puppeteer download Chromium for Apple M1. On Apple M1 devices Puppeteer by default downloads the version for Intel's processor which runs via Rosetta. It works without any problems, however, with this option, you should get more efficient resource usage (CPU and RAM) that could lead to a faster execution time. **BEWARE**: it's an experimental option that makes sense only if you have an Apple M1 device, use at your own risk.
> **NOTE** `PUPPETEER_*` env variables are not accounted for in the [`puppeteer-core`](https://www.npmjs.com/package/puppeteer-core) package. > **NOTE** `PUPPETEER_*` env variables are not accounted for in the [`puppeteer-core`](https://www.npmjs.com/package/puppeteer-core) package.

View File

@ -35,12 +35,15 @@ import createHttpsProxyAgent, {
import { getProxyForUrl } from 'proxy-from-env'; import { getProxyForUrl } from 'proxy-from-env';
import { assert } from '../common/assert.js'; import { assert } from '../common/assert.js';
const { PUPPETEER_EXPERIMENTAL_CHROMIUM_MAC_ARM } = process.env;
const debugFetcher = debug('puppeteer:fetcher'); const debugFetcher = debug('puppeteer:fetcher');
const downloadURLs = { const downloadURLs = {
chrome: { chrome: {
linux: '%s/chromium-browser-snapshots/Linux_x64/%d/%s.zip', linux: '%s/chromium-browser-snapshots/Linux_x64/%d/%s.zip',
mac: '%s/chromium-browser-snapshots/Mac/%d/%s.zip', mac: '%s/chromium-browser-snapshots/Mac/%d/%s.zip',
mac_arm: '%s/chromium-browser-snapshots/Mac_Arm/%d/%s.zip',
win32: '%s/chromium-browser-snapshots/Win/%d/%s.zip', win32: '%s/chromium-browser-snapshots/Win/%d/%s.zip',
win64: '%s/chromium-browser-snapshots/Win_x64/%d/%s.zip', win64: '%s/chromium-browser-snapshots/Win_x64/%d/%s.zip',
}, },
@ -67,7 +70,7 @@ const browserConfig = {
* Supported platforms. * Supported platforms.
* @public * @public
*/ */
export type Platform = 'linux' | 'mac' | 'win32' | 'win64'; export type Platform = 'linux' | 'mac' | 'mac_arm' | 'win32' | 'win64';
function archiveName( function archiveName(
product: Product, product: Product,
@ -76,7 +79,7 @@ function archiveName(
): string { ): string {
if (product === 'chrome') { if (product === 'chrome') {
if (platform === 'linux') return 'chrome-linux'; if (platform === 'linux') return 'chrome-linux';
if (platform === 'mac') return 'chrome-mac'; if (platform === 'mac' || platform === 'mac_arm') return 'chrome-mac';
if (platform === 'win32' || platform === 'win64') { if (platform === 'win32' || platform === 'win64') {
// Windows archive name changed at r591479. // Windows archive name changed at r591479.
return parseInt(revision, 10) > 591479 ? 'chrome-win' : 'chrome-win32'; return parseInt(revision, 10) > 591479 ? 'chrome-win' : 'chrome-win32';
@ -200,22 +203,33 @@ export class BrowserFetcher {
options.path || options.path ||
path.join(projectRoot, browserConfig[this._product].destination); path.join(projectRoot, browserConfig[this._product].destination);
this._downloadHost = options.host || browserConfig[this._product].host; this._downloadHost = options.host || browserConfig[this._product].host;
this.setPlatform(options.platform); this.setPlatform(options.platform, this._product);
assert( assert(
downloadURLs[this._product][this._platform], downloadURLs[this._product][this._platform],
'Unsupported platform: ' + this._platform 'Unsupported platform: ' + this._platform
); );
} }
private setPlatform(platformFromOptions?: Platform): void { private setPlatform(
platformFromOptions?: Platform,
productFromOptions?: Product
): void {
if (platformFromOptions) { if (platformFromOptions) {
this._platform = platformFromOptions; this._platform = platformFromOptions;
return; return;
} }
const platform = os.platform(); const platform = os.platform();
if (platform === 'darwin') this._platform = 'mac'; if (platform === 'darwin') {
else if (platform === 'linux') this._platform = 'linux'; if (productFromOptions === 'chrome') {
this._platform =
os.arch() === 'arm64' && PUPPETEER_EXPERIMENTAL_CHROMIUM_MAC_ARM
? 'mac_arm'
: 'mac';
} else if (productFromOptions === 'firefox') {
this._platform = 'mac';
}
} else if (platform === 'linux') this._platform = 'linux';
else if (platform === 'win32') else if (platform === 'win32')
this._platform = os.arch() === 'x64' ? 'win64' : 'win32'; this._platform = os.arch() === 'x64' ? 'win64' : 'win32';
else assert(this._platform, 'Unsupported platform: ' + platform); else assert(this._platform, 'Unsupported platform: ' + platform);
@ -297,8 +311,7 @@ export class BrowserFetcher {
if (!(await existsAsync(this._downloadsFolder))) if (!(await existsAsync(this._downloadsFolder)))
await mkdirAsync(this._downloadsFolder); await mkdirAsync(this._downloadsFolder);
// Use Intel x86 builds on Apple M1 until native macOS arm64 // Use system Chromium builds on Linux ARM devices
// Chromium builds are available.
if (os.platform() !== 'darwin' && os.arch() === 'arm64') { if (os.platform() !== 'darwin' && os.arch() === 'arm64') {
handleArm64(); handleArm64();
return; return;
@ -353,7 +366,7 @@ export class BrowserFetcher {
const folderPath = this._getFolderPath(revision); const folderPath = this._getFolderPath(revision);
let executablePath = ''; let executablePath = '';
if (this._product === 'chrome') { if (this._product === 'chrome') {
if (this._platform === 'mac') if (this._platform === 'mac' || this._platform === 'mac_arm')
executablePath = path.join( executablePath = path.join(
folderPath, folderPath,
archiveName(this._product, this._platform, revision), archiveName(this._product, this._platform, revision),
@ -376,7 +389,7 @@ export class BrowserFetcher {
); );
else throw new Error('Unsupported platform: ' + this._platform); else throw new Error('Unsupported platform: ' + this._platform);
} else if (this._product === 'firefox') { } else if (this._product === 'firefox') {
if (this._platform === 'mac') if (this._platform === 'mac' || this._platform === 'mac_arm')
executablePath = path.join( executablePath = path.join(
folderPath, folderPath,
'Firefox Nightly.app', 'Firefox Nightly.app',

View File

@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
import os from 'os';
import https, { RequestOptions } from 'https'; import https, { RequestOptions } from 'https';
import ProgressBar from 'progress'; import ProgressBar from 'progress';
import URL from 'url'; import URL from 'url';
@ -103,13 +102,9 @@ export async function downloadBrowser(): Promise<void> {
if (NPM_NO_PROXY) process.env.NO_PROXY = NPM_NO_PROXY; if (NPM_NO_PROXY) process.env.NO_PROXY = NPM_NO_PROXY;
function onSuccess(localRevisions: string[]): void { function onSuccess(localRevisions: string[]): void {
// Use Intel x86 builds on Apple M1 until native macOS arm64 logPolitely(
// Chromium builds are available. `${supportedProducts[product]} (${revisionInfo.revision}) downloaded to ${revisionInfo.folderPath}`
if (os.platform() !== 'darwin' && os.arch() !== 'arm64') { );
logPolitely(
`${supportedProducts[product]} (${revisionInfo.revision}) downloaded to ${revisionInfo.folderPath}`
);
}
localRevisions = localRevisions.filter( localRevisions = localRevisions.filter(
(revision) => revision !== revisionInfo.revision (revision) => revision !== revisionInfo.revision
); );

View File

@ -21,7 +21,7 @@ const https = require('https');
const BrowserFetcher = const BrowserFetcher =
require('../lib/cjs/puppeteer/node/BrowserFetcher.js').BrowserFetcher; require('../lib/cjs/puppeteer/node/BrowserFetcher.js').BrowserFetcher;
const SUPPORTED_PLATFORMS = ['linux', 'mac', 'win32', 'win64']; const SUPPORTED_PLATFORMS = ['linux', 'mac', 'mac_arm', 'win32', 'win64'];
const fetchers = SUPPORTED_PLATFORMS.map( const fetchers = SUPPORTED_PLATFORMS.map(
(platform) => new BrowserFetcher('', { platform }) (platform) => new BrowserFetcher('', { platform })
); );
@ -139,6 +139,9 @@ async function checkOmahaProxyAvailability() {
fetch( fetch(
'https://storage.googleapis.com/chromium-browser-snapshots/Mac/LAST_CHANGE' 'https://storage.googleapis.com/chromium-browser-snapshots/Mac/LAST_CHANGE'
), ),
fetch(
'https://storage.googleapis.com/chromium-browser-snapshots/Mac_Arm/LAST_CHANGE'
),
fetch( fetch(
'https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/LAST_CHANGE' 'https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/LAST_CHANGE'
), ),
@ -191,7 +194,7 @@ async function checkRangeAvailability({
toRevision, toRevision,
stopWhenAllAvailable, stopWhenAllAvailable,
}) { }) {
const table = new Table([10, 7, 7, 7, 7]); const table = new Table([10, 7, 7, 7, 7, 7]);
table.drawRow([''].concat(SUPPORTED_PLATFORMS)); table.drawRow([''].concat(SUPPORTED_PLATFORMS));
const inc = fromRevision < toRevision ? 1 : -1; const inc = fromRevision < toRevision ? 1 : -1;