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

Chromium reports via puppeteer #21788

Merged
merged 44 commits into from
Aug 30, 2018
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
af57568
First stab at using puppeteer to run Chromium reports
chrisdavies Aug 8, 2018
319df86
Merge branch 'master' of github.com:elastic/kibana into reporting/pup…
chrisdavies Aug 8, 2018
e962e8d
Attempt to test chromium w/ puppeteer
chrisdavies Aug 8, 2018
4f2567b
Get puppeteer + chromium reports working
chrisdavies Aug 8, 2018
86d460d
Turn on all Chromium tests and duplicate them
chrisdavies Aug 8, 2018
d6bfcb0
Temporary: link to 3rd party Chromium build to try to test Puppeteer
chrisdavies Aug 10, 2018
564e634
Remove all but Linux Chromium packages
chrisdavies Aug 10, 2018
fb47ae3
Merge branch 'master' of github.com:elastic/kibana into reporting/pup…
chrisdavies Aug 10, 2018
01b0ed3
Attempt to get Puppeteer tests to run
chrisdavies Aug 10, 2018
a78668f
Merge branch 'master' of github.com:elastic/kibana into reporting/pup…
chrisdavies Aug 13, 2018
3a6f58d
Revert chromium reporting to refer to our custom Chromium build
chrisdavies Aug 15, 2018
e74ff8a
Update Chromium build scripts to support reproducible builds.
chrisdavies Aug 17, 2018
70ddaf2
Fix typo in Chromium windows args.gn
chrisdavies Aug 17, 2018
ade46e9
Fix Chromium build scripts
chrisdavies Aug 20, 2018
ae325eb
Merge master
chrisdavies Aug 20, 2018
e8bb074
Attempt to run Chromium + puppeteer
chrisdavies Aug 20, 2018
407a708
Fix build scripts, adjust win / mac args in an
chrisdavies Aug 22, 2018
3fa402a
Add note about diagnosing Chromium runtime failures
chrisdavies Aug 22, 2018
0925740
Fix the windows args. The icu_use_data_file flag
chrisdavies Aug 22, 2018
8a30325
Add note about the Chromium build artifacts
chrisdavies Aug 22, 2018
c4370d2
Fix build.py optimize step for Chromium
chrisdavies Aug 22, 2018
105a18e
Switch to puppeteer core
chrisdavies Aug 23, 2018
9de5acb
Stripping out reporting code that has been replaced by puppeteer
chrisdavies Aug 23, 2018
98b30dd
Upgrade PDFImage remove unused chromium driver prop
chrisdavies Aug 23, 2018
579d5ab
Merge branch 'master' of github.com:elastic/kibana into reporting/pup…
chrisdavies Aug 23, 2018
f7f3483
Convert args.js to args.ts to get x-pack tsconfig to stop complaining
chrisdavies Aug 23, 2018
5ac4f14
Remove record calls since no browser drivers currently support it
chrisdavies Aug 23, 2018
71a9064
Tweak chromium build script comments and clean up
chrisdavies Aug 23, 2018
16ad83b
Change comments to doc strings
chrisdavies Aug 23, 2018
1f2fe32
Fix Linux environment init script
chrisdavies Aug 23, 2018
94fa33b
Move chromium binaries to prodcution s3 bucket, tweak windows build args
chrisdavies Aug 23, 2018
aa3446d
Merge branch 'master' of github.com:elastic/kibana into reporting/pup…
chrisdavies Aug 24, 2018
78bcba6
Fix bug w/ reporting tests where the previous tests's
chrisdavies Aug 27, 2018
14e448a
Use PDFJS to determine how many pages are in our test PDFs
chrisdavies Aug 27, 2018
d20760c
Ensure reporting tests clear all toast notifications prior to running
chrisdavies Aug 28, 2018
0c1c9f7
Fix bug where reporting viewport resizes and the screenshot capture
chrisdavies Aug 28, 2018
c9ba80e
Merge branch 'master' of github.com:elastic/kibana into reporting/pup…
chrisdavies Aug 28, 2018
c5d947e
Add note to Chromium build readme to remind us to turn of the VMs whe…
chrisdavies Aug 28, 2018
e88a447
Fix the Linux gcloud readme instructions.
chrisdavies Aug 28, 2018
71d099d
Add Linux Chromium tmux instructions
chrisdavies Aug 29, 2018
610a9b6
Remove dependency on chrome-remote-interface
chrisdavies Aug 29, 2018
ba2f7af
Merge branch 'reporting/puppeteer' of github.com:chrisdavies/kibana i…
chrisdavies Aug 29, 2018
4e7c2b0
Merge branch 'master' of github.com:elastic/kibana into reporting/pup…
chrisdavies Aug 29, 2018
6679d81
Merge branch 'master' of github.com:elastic/kibana into reporting/pup…
chrisdavies Aug 29, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions x-pack/build_chromium/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.pyc
127 changes: 119 additions & 8 deletions x-pack/build_chromium/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,123 @@
# Building on Linux
The following script will run in the elastic/ubuntu-16.04-x86_64 virtual machine. It should be noted that the harddisk of the Virtual Machine should be resized to at least 40GB.
# Chromium build

# Building on Windows
Some dependencies must be installed on the build machine to build on Windows, those are specified [here](https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md). You don't have to install the depot_tools, just Visual Studio and the Windows SDK. When building on Windows, using the `--workspace` flag is likely required because of the NTFS max paths.
We ship our own headless build of Chromium which is significantly smaller than the standard binaries shipped by Google. The scripts in this folder can be used to initialize the build environments and run the build on Mac, Windows, and Linux.

# Building on macOS
XCode and the OS X 10.10 SDK are currently required, but the full requirements are specified [here](https://chromium.googlesource.com/chromium/src/+/master/docs/mac_build_instructions.md). Also, you don't have to install the depot_tools.
The official Chromium build process is poorly documented, and seems to have breaking changes fairly regularly. The build pre-requisites, and the build flags change over time, so it is likely that the scripts in this directory will be out of date by the time we have to do another Chromium build.

This document is an attempt to note all of the gotchas we've come across while building, so that the next time we have to tinker here, we'll have a good starting point.

## Updating the revision
If you want to build the headless_shell that mirrors a specific version of the Chrome browser, you can take the version number displayed in `Chrome -> About` and plug it into the "Version" input [here](https://omahaproxy.appspot.com/) and it'll give you the Commit that you can feed into the build script using the `--git-sha` argument. It's highly recommended to update the default when you're upgrading the version.
## Build args

Chromium is built via a build tool called "ninja". The build can be configured by specifying build flags either in an "args.gn" file or via commandline args. We have an "args.gn" file per platform:

- mac: darwin/args.gn
- linux: linux/args.gn
- windows: windows/args.gn

The various build flags are not well documented. Some are documented [here](https://www.chromium.org/developers/gn-build-configuration). Some, such as `enable_basic_printing = false`, I only found by poking through 3rd party build scripts.

As of this writing, there is an officially supported headless Chromium build args file for Linux: `build/args/headless.gn`. This does not work on Windows or Mac, so we have taken that as our starting point, and modified it until the Windows / Mac builds succeeded.

## VMs

I ran Linux and Windows VMs in GCP with the following specs:

- 8 core vCPU
- 30GB RAM
- 128GB hard drive
- Ubuntu 18.04 LTS (not minimal)
- Windows Server 2016 (full, with desktop)

The more cores the better, as the build makes effective use of each. For Linux, Ubuntu is the only officially supported build target.

- Linux:
- SSH in using [gcloud](https://cloud.google.com/sdk/)
- Get the ssh command in the [GCP console](https://console.cloud.google.com/) -> VM instances -> your-vm-name -> SSH -> gcloud
Copy link
Contributor

@stacey-gammon stacey-gammon Aug 28, 2018

Choose a reason for hiding this comment

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

Should you add a step to start the vm instance if it is stopped?

Should we specifically call out the vm instance name so it matches whats on there now? chromium-build-linux I see (but it's stopped so I can't SSH in)

And maybe a step to make sure you turn it off when done building since I guess we get billed for it.

- Their in-browser UI is kinda sluggish, so use the commandline tool

- Windows:
- Install Microsoft's Remote Desktop tools
- Get the RDP file in the [GCP console](https://console.cloud.google.com/) -> VM instances -> your-vm-name -> RDP -> Download the RDP file
- Edit it in Microsoft Remote Desktop:
- Display -> Resolution (1280 x 960 or something reasonable)
- Local Resources -> Folders, then select the folder(s) you want to share, this is at least `build_chromium` folder
- Save

## Initializing each VM / environment

You only need to initialize each environment once.

Create the build folder:

- Mac / Linux: `mkdir -p ~/chromium`
- Windows: `mkdir c:\chromium`

Copy the `x-pack/build-chromium` folder to each. Replace `you@your-machine` with the correct username and VM name:

- Mac: `cp -r ~/dev/elastic/kibana/x-pack/build_chromium ~/chromium/build_chromium`
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd get rid of the dev part of the path here, since that depends on where your kibana repo is. Maybe just start with kibana. Also... the below ones doesn't seem to match up. Should ~/dev/build_chromium/ be kibana/x-pack/build_chromium/?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't copy the Kibana codebase to the build servers. Just the build_chromium folder. Really, build_chromium should probably be its own repo / project, as it's essentially independent of Kibana. So, it should probably be cp -r kibana/x-pack/build_chromium ~/chromium/build_chromium, assuming that you're wd has kibana as a child.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah. You're right. ~dev/build_chromium is wrong.

- Linux: `gcloud compute scp --recurse ~/dev/elastic/kibana/x-pack/build_chromium you@your-machine:~/chromium --zone=us-east1-b`
- Windows: Copy the `build_chromium` folder via the RDP GUI into `c:\chromium\build_chromium`

There is an init script for each platform. This downloads and installs the necessary prerequisites, sets environment variables, etc.

- Mac: `~/chromium/build_chromium/darwin/init.sh`
- Linux: `~/chromium/build_chromium/linux/init.sh`
- Windows `c:\chromium\build_chromium\windows\init.bat`

In windows, at least, you will need to do a number of extra steps:

- Follow the prompts in the Visual Studio installation process, click "Install" and wait a while
- Once it's installed, open Control Panel and turn on Debugging Tools for Windows:
- Control Panel → Programs → Programs and Features → Select the “Windows Software Development Kit” → Change → Change → Check “Debugging Tools For Windows” → Change
- Press enter in the terminal to continue running the init

## Building

Find the sha of the Chromium commit you wish to build. Most likely, you want to build the Chromium revision that is tied to the version of puppeteer that we're using.

Find the Chromium revision (modify the following command to be wherever you have the kibana source installed):

- `cat ~/dev/elastic/kibana/x-pack/node_modules/puppeteer-core/package.json | grep chromium_revision`
- Take the revision number from that, and tack it to the end of this URL: https://crrev.com
- (For example: https://crrev.com/575458)
- Grab the SHA from there
- (For example, rev 575458 has sha 4747cc23ae334a57a35ed3c8e6adcdbc8a50d479)

Note: In Linux, you should run the build command in tmux so that if your ssh session disconnects, the build can keep going. To do this, just type `tmux` into your terminal to hop into a tmux session. If you get disconnected, you can hop back in like so:

- SSH into the server
- Run `tmux list-sessions`
- Run `tmux switch -t {session_id}`, replacing {session_id} with the value from the list-sessions output

To run the build, replace the sha in the following commands with the sha that you wish to build:

- Mac: `python ~/chromium/build_chromium/build.py 4747cc23ae334a57a35ed3c8e6adcdbc8a50d479`
- Linux: `python ~/chromium/build_chromium/build.py 4747cc23ae334a57a35ed3c8e6adcdbc8a50d479`
- Windows: `python c:\chromium\build_chromium\build.py 4747cc23ae334a57a35ed3c8e6adcdbc8a50d479`

## Artifacts

After the build completes, there will be a .zip file and a .md5 file in `~/chromium/chromium/src/out/headless`. These are named like so: `chromium-{first_7_of_SHA}-{platform}`, for example: `chromium-4747cc2-linux`.

The zip files need to be deployed to s3. For testing, I drop them into `headless-shell-dev`, but for production, they need to be in `headless-shell`. And the `x-pack/plugins/reporting/server/browsers/chromium/paths.js` file needs to be upated to have the correct `archiveChecksum`, `archiveFilename` and `baseUrl`.

*If you're building in the cloud, don't forget to turn off your VM after retrieving the build artifacts!*

## Diagnosing runtime failures

After getting the build to pass, the resulting binaries often failed to run or would hang.

You can run the headless browser manually to see what errors it is generating (replace the `c:\dev\data` with the path to a dummy folder you've created on your system):

`headless_shell.exe --disable-translate --disable-extensions --disable-background-networking --safebrowsing-disable-auto-update --disable-sync --metrics-recording-only --disable-default-apps --mute-audio --no-first-run --user-data-dir=c:\dev\data --disable-gpu --no-sandbox --headless --hide-scrollbars --window-size=400,400 --remote-debugging-port=3333 about:blank`

## Resources

The following links provide helpful context about how the Chromium build works, and its prerequisites:

- https://www.chromium.org/developers/how-tos/get-the-code/working-with-release-branches
- https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md
- https://chromium.googlesource.com/chromium/src/+/master/docs/mac_build_instructions.md
- https://chromium.googlesource.com/chromium/src/+/master/docs/linux_build_instructions.md
- Some build-flag descriptions: https://www.chromium.org/developers/gn-build-configuration
- The serverless Chromium project was indispensable: https://github.com/adieuadieu/serverless-chrome/blob/b29445aa5a96d031be2edd5d1fc8651683bf262c/packages/lambda/builds/chromium/build/build.sh
148 changes: 0 additions & 148 deletions x-pack/build_chromium/build.js

This file was deleted.

92 changes: 92 additions & 0 deletions x-pack/build_chromium/build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import subprocess, os, sys, platform, zipfile, hashlib, shutil
from build_util import runcmd, mkdir, md5_file, script_dir, root_dir, configure_environment

# This file builds Chromium headless on Windows, Mac, and Linux.

# Verify that we have an argument, and if not print instructions
if (len(sys.argv) < 2):
print('Usage:')
print('python build.py {chromium_version}')
print('Example:')
print('python build.py 68.0.3440.106')
print('python build.py 4747cc23ae334a57a35ed3c8e6adcdbc8a50d479')
sys.exit(1)

# The version of Chromium we wish to build. This can be any valid git
# commit, tag, or branch, so: 68.0.3440.106 or
# 4747cc23ae334a57a35ed3c8e6adcdbc8a50d479
source_version = sys.argv[1]

print('Building Chromium ' + source_version)

# Set the environment variables required by the build tools
print('Configuring the build environment')
configure_environment()

# Sync the codebase to the correct version, syncing master first
# to ensure that we actually have all the versions we may refer to
print('Syncing source code')

os.chdir(os.path.join(root_dir, 'chromium/src'))

runcmd('git checkout master')
runcmd('git fetch origin')
runcmd('gclient sync --with_branch_heads --with_tags --jobs 16')
runcmd('git checkout ' + source_version)
runcmd('gclient sync --with_branch_heads --with_tags --jobs 16')
runcmd('gclient runhooks')

# Copy build args/{Linux | Darwin | Windows}.gn from the root of our directory to out/headless/args.gn,
platform_build_args = os.path.join(script_dir, platform.system().lower(), 'args.gn')
print('Generating platform-specific args')
print('Copying build args: ' + platform_build_args + ' to out/headless/args.gn')
mkdir('out/headless')
shutil.copyfile(platform_build_args, 'out/headless/args.gn')
runcmd('gn gen out/headless')

# Build Chromium... this takes *forever* on underpowered VMs
print('Compiling... this will take a while')
runcmd('autoninja -C out/headless headless_shell')

# Optimize the output on Linux and Mac by stripping inessentials from the binary
if platform.system() != 'Windows':
print('Optimizing headless_shell')
shutil.move('out/headless/headless_shell', 'out/headless/headless_shell_raw')
runcmd('strip -o out/headless/headless_shell out/headless/headless_shell_raw')

# Create the zip and generate the md5 hash using filenames like:
# chromium-4747cc2-linux.zip
base_filename = 'out/headless/chromium-' + source_version[:7].strip('.') + '-' + platform.system().lower()
zip_filename = base_filename + '.zip'
md5_filename = base_filename + '.md5'

print('Creating ' + zip_filename)
archive = zipfile.ZipFile(zip_filename, mode='w', compression=zipfile.ZIP_DEFLATED)

def archive_file(name):
"""A little helper function to write individual files to the zip file"""
from_path = os.path.join('out/headless', name)
to_path = os.path.join('headless_shell-' + platform.system().lower(), name)
archive.write(from_path, to_path)

# Each platform has slightly different requirements for what dependencies
# must be bundled with the Chromium executable.
if platform.system() == 'Linux':
archive_file('headless_shell')
elif platform.system() == 'Windows':
archive_file('headless_shell.exe')
archive_file('dbghelp.dll')
archive_file('icudtl.dat')
archive_file('natives_blob.bin')
archive_file('snapshot_blob.bin')
elif platform.system() == 'Darwin':
archive_file('headless_shell')
archive_file('natives_blob.bin')
archive_file('snapshot_blob.bin')
archive_file('Helpers/crashpad_handler')

archive.close()

print('Creating ' + md5_filename)
with open (md5_filename, 'w') as f:
f.write(md5_file(zip_filename))
Loading