Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Reporting/Build Chromium] Add a developer script to find the Chromium commit #94033

Merged
merged 7 commits into from Mar 10, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions scripts/chromium_version.js
@@ -0,0 +1,10 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

require('../src/setup_node_env');
require('../src/dev/chromium_version');
139 changes: 139 additions & 0 deletions src/dev/chromium_version.ts
@@ -0,0 +1,139 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { run, REPO_ROOT, ToolingLog } from '@kbn/dev-utils';
import chalk from 'chalk';
import cheerio from 'cheerio';
import dedent from 'dedent';
import fs from 'fs';
import fetch from 'node-fetch';
import path from 'path';
import { PackageJson } from 'type-fest';

type PuppeteerRelease = string;
type ChromiumRevision = string;
type ChromiumCommit = string;

// We forked the Puppeteer node module for Kibana,
// So we need to translate OUR version to the official Puppeteer Release
const forkCompatibilityMap: Record<string, PuppeteerRelease> = {
'5.4.1-patch.1': '5.4.1',
};

async function getPuppeteerRelease(log: ToolingLog): Promise<PuppeteerRelease> {
// open node_modules/puppeteer/package.json
const puppeteerPackageJson: PackageJson = JSON.parse(
fs.readFileSync(path.resolve(REPO_ROOT, 'node_modules', 'puppeteer', 'package.json'), 'utf8')
);
const { version } = puppeteerPackageJson;
if (version == null) {
throw new Error(
'Could not get the Puppeteer version! Check node_modules/puppteer/package.json'
);
}
log.info(`Kibana is using Puppeteer ${version} (${forkCompatibilityMap[version]})`);
return forkCompatibilityMap[version];
}

async function getChromiumRevision(
kibanaPuppeteerVersion: PuppeteerRelease,
log: ToolingLog
): Promise<ChromiumRevision> {
const url = `https://raw.githubusercontent.com/puppeteer/puppeteer/v${kibanaPuppeteerVersion}/src/revisions.ts`;
let body: string;
try {
log.info(`Fetching code from Puppeteer source: ${url}`);
const rawSource = await fetch(url);
body = await rawSource.text();
} catch (err) {
log.error(err);
throw new Error(`Could not fetch ${url}. Check the URL in a browser and try again.`);
}

let revision: ChromiumRevision | undefined;
const lines = body.split('\n');
let cursor = lines.length;
while (--cursor >= 0) {
// look for the line of code matching ` chromium: '0123456',`
const test = lines[cursor].match(/^\s+chromium: '(\S+)',$/);
if (test != null) {
log.debug(`Parsed revision from source text: \`${lines[cursor]}\``);
[, revision] = test;
break;
}
}

if (revision == null) {
throw new Error(
`Could not find a Chromium revision listed in Puppeteer source! Check ${url} in a browser`
);
}

log.info(`Found Chromium revision ${revision} from Puppeteer ${kibanaPuppeteerVersion}`);
return revision;
}

async function getChromiumCommit(
revision: ChromiumRevision,
log: ToolingLog
): Promise<ChromiumCommit> {
const url = `https://crrev.com/${revision}`;
log.info(`Fetching ${url}`);
const pageText = await fetch(url);
const $ = cheerio.load(await pageText.text());

// get the commit from the page title
let commit: ChromiumCommit | null = null;
const matches = $('title')
.text()
.match(/\S{40}/);
if (matches != null) {
log.debug(`Parsed commit hash from page title: \`${$('title').text()}\``);
[commit] = matches;
}

if (commit == null) {
throw new Error(`Could not find a Chromium commit! Check ${url} in a browser.`);
}

log.info(`Found Chromium commit ${commit} from revision ${revision}.`);
return commit;
}

run(
async ({
log,
flags: {
_: [puppeteerVersionArg],
},
}) => {
try {
let puppeteerVersion: PuppeteerRelease;
if (puppeteerVersionArg) {
puppeteerVersion = puppeteerVersionArg;
} else {
puppeteerVersion = await getPuppeteerRelease(log);
}

const chromiumRevision = await getChromiumRevision(puppeteerVersion, log);
await getChromiumCommit(chromiumRevision, log);
} catch (err) {
log.error(err);
}
},
{
description: dedent(chalk`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we already pass the description to dedent

Display the Chromium git commit that correlates to a given Puppeteer release.

- node x-pack/dev-tools/chromium_version 5.5.0 {dim # gets the Chromium commit for Puppeteer v5.5.0}
- node x-pack/dev-tools/chromium_version {dim # gets the Chromium commit for the Kibana dependency version of Puppeteer}

You can use https://omahaproxy.appspot.com/ to look up the Chromium release that first shipped with that commit.
`),
}
);
1 change: 1 addition & 0 deletions x-pack/build_chromium/.chromium-commit
@@ -0,0 +1 @@
ef768c94bcb42dca4c27048615d07efadbb1c1c2
20 changes: 9 additions & 11 deletions x-pack/build_chromium/README.md
Expand Up @@ -44,7 +44,7 @@ gsutil cp -r gs://my-bucket/build_chromium .
# Install the OS packages, configure the environment, download the chromium source (25GB)
python ./build_chromium/init.sh [arch_name]

# Run the build script with the path to the chromium src directory, the git commit id
# Run the build script with the path to the chromium src directory, the git commit hash
python ./build_chromium/build.py <commit_id> x86

# OR You can build for ARM
Expand All @@ -55,16 +55,14 @@ python ./build_chromium/build.py <commit_id> arm64
the Chromium repo to be cloned successfully. If checking out the Chromium fails
with "early EOF" errors, the instance could be low on memory or disk space.

## Getting the Commit ID
The `build.py` script requires a commit ID of the Chromium repo. Getting `<commit_id>` can be tricky. The best technique seems to be:
1. Create a temporary working directory and intialize yarn
2. `yarn add puppeteer # install latest puppeter`
3. Look through Puppeteer documentation and Changelogs to find information
about where the "chromium revision" is located in the Puppeteer code. The code
containing it might not be distributed in the node module.
- Example: https://github.com/puppeteer/puppeteer/blob/b549256/src/revisions.ts
4. Use `https://crrev.com` and look up the revision and find the git commit info.
- Example: http://crrev.com/818858 leads to the git commit e62cb7e3fc7c40548cef66cdf19d270535d9350b
## Getting the Commit Hash
If you need to bump the version of Puppeteer, you need to get a new git commit hash for Chromium that corresponds to the Puppeteer version.
```
node x-pack/dev-tools/chromium_version.js [PuppeteerVersion]
```

When bumping the Puppeteer version, make sure you also update the `.chromium-commit` file with the commit hash
for the current Chromium build, so we'll be able to construct a build pipeline for each OS (coming soon!).

## Build args

Expand Down
Expand Up @@ -83,6 +83,12 @@ export class HeadlessChromiumDriverFactory {
} as puppeteer.LaunchOptions);

page = await browser.newPage();

// Log version info for debugging / maintenance
const client = await page.target().createCDPSession();
const versionInfo = await client.send('Browser.getVersion');
logger.debug(`Browser version: ${JSON.stringify(versionInfo)}`);

await page.emulateTimezone(browserTimezone ?? null);

// Set the default timeout for all navigation methods to the openUrl timeout (30 seconds)
Expand Down