Skip to content

Commit

Permalink
[Reporting/Build Chromium] Add a developer script to find the Chromiu…
Browse files Browse the repository at this point in the history
…m commit (#94033) (#94342)

* script that finds the chromium commit

* use run from dev-utils

* update docs and inch towards build pipeline

* more docs updates

* move the scripts the root

* review feedback
  • Loading branch information
tsullivan committed Mar 10, 2021
1 parent 255d0af commit 9891107
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 11 deletions.
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');
138 changes: 138 additions & 0 deletions src/dev/chromium_version.ts
@@ -0,0 +1,138 @@
/*
* 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 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: chalk`
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

0 comments on commit 9891107

Please sign in to comment.