skia2/infra/bots/recipes/bookmaker.py
Ravi Mistry edc4f3e604 Add new Bookmaker bot that runs nightly
The new bot:
1) Extracts all fiddles out of markdown files.
2) Forces fiddle.skia.org to compile all those fiddles and get output in JSON.
3) Scans the output and reports any compiletime/runtime errors.
4) Updates markdown in site/user/api/ using the new hashes (if any) from fiddle.skia.org.

To ensure the bot does not check in unexpected changes:
* upload_md.py makes sure that all modified files are under site/user/api/. It errors out if this is not the case.
* CLs with docs only changes normally have 'NoTry: true' added to their descriptions. This is not done for the new bot because we want to run it through trybots to make sure nothing unexpected snuck in.
* rmistry@ and caryclark@ are automatically CC'ed on all uploaded changes. I plan to watch the bot closely for at least a couple of weeks.


Bug: skia:7310
Change-Id: I759fc8bae1e32a6f175e3b1a895947d14ca5fe3a
Reviewed-on: https://skia-review.googlesource.com/79941
Commit-Queue: Ravi Mistry <rmistry@google.com>
Reviewed-by: Eric Boren <borenet@google.com>
2017-12-08 22:26:38 +00:00

176 lines
6.6 KiB
Python

# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Recipe which:
# 1) Extracts all fiddles out of markdown files.
# 2) Forces fiddle.skia.org to compile all those fiddles and get output in JSON.
# 3) Scans the output and reports any compiletime/runtime errors.
# 4) Updates markdown in site/user/api/ using the new hashes (if any) from
# fiddle.skia.org.
import json
DEPS = [
'recipe_engine/context',
'recipe_engine/file',
'recipe_engine/path',
'recipe_engine/properties',
'recipe_engine/step',
'core',
'infra',
'run',
'vars',
]
UPDATE_DOCS_GITCOOKIES_FILE = 'update_docs.git_cookies'
UPDATE_DOCS_GITCOOKIES_GS_PATH = (
'gs://skia-buildbots/artifacts/server/.gitcookies_update-docs')
def go_get_fiddlecli(api):
env = api.context.env
env.update(api.infra.go_env)
with api.context(env=env):
api.run.with_retry(
api.step,
'go get fiddlecli',
5, # Update attempts.
cmd=[api.infra.go_exe, 'get', '-u', '-t',
'go.skia.org/infra/fiddle/go/fiddlecli'])
def RunSteps(api):
api.vars.setup()
api.core.checkout_steps()
api.infra.go_version()
go_get_fiddlecli(api)
with api.context(cwd=api.vars.skia_dir, env=api.infra.go_env):
bookmaker_binary = api.path.join(api.vars.skia_out, api.vars.configuration,
'bookmaker')
fiddlecli_binary = api.path.join(api.infra.gopath, 'bin', 'fiddlecli')
fiddlecli_input = api.path.join(api.path['start_dir'], 'fiddle.json')
fiddlecli_output = api.path.join(api.path['start_dir'], 'fiddleout.json')
# Step 1: Extract all fiddles out of markdown files.
cmd = [bookmaker_binary,
'-b', 'docs', # Path to a *.bmh file or directory.
'-e', fiddlecli_input, # Fiddle cli input.
]
api.run(api.step, 'Extract all fiddles out of md files', cmd=cmd)
# Step 2: Forces fiddle.skia.org to compile all fiddles extracted out of
# markdown files and get output in JSON.
cmd = [fiddlecli_binary,
'--input', fiddlecli_input,
'--output', fiddlecli_output,
'--logtostderr',
'--force',
]
api.run(api.step, 'Force fiddle to compile all examples', cmd=cmd)
# Step 3: Scan the output of fiddlecli for any compiletime/runtime errors.
# Fail the recipe is there are any errors and summarize results at
# the end.
if api.path.exists(fiddlecli_output):
test_data = api.properties.get('fiddleout_test_data', '{}')
content = api.file.read_text('Read fiddleout.json',
fiddlecli_output, test_data=test_data)
out = json.loads(content)
failing_fiddles = []
for fiddle_name in out:
props = out[fiddle_name]
if props['compile_errors'] or props['runtime_error']:
failing_fiddles.append(props['fiddleHash'])
if failing_fiddles:
# create an eror message and fail the bot!
failure_msg = 'The following fiddles failed:\n\n'
for fiddle_hash in failing_fiddles:
failure_msg += 'https://fiddle.skia.org/c/%s\n' % fiddle_hash
raise api.step.StepFailure(failure_msg)
# Do a dump of fiddlecli_output. Will be useful for debugging.
print 'Dump of %s:' % fiddlecli_output
print json.dumps(out, indent=4)
# Step 4: Update docs in site/user/api/ with the output of fiddlecli.
# If there are any new changes then upload and commit the changes.
update_docs_gitcookies = api.path['start_dir'].join(
UPDATE_DOCS_GITCOOKIES_FILE)
cmd = ['python',
api.vars.skia_dir.join('infra', 'bots', 'upload_md.py'),
'--bookmaker_binary', bookmaker_binary,
'--fiddlecli_output', fiddlecli_output,
'--gitcookies', str(update_docs_gitcookies)]
with api.infra.DownloadGitCookies(
UPDATE_DOCS_GITCOOKIES_GS_PATH, update_docs_gitcookies, api):
with api.context(cwd=api.vars.skia_dir, env=api.infra.go_env):
api.run(api.step, 'Generate and Upload Markdown files', cmd=cmd)
def GenTests(api):
fiddleout_no_errors_test_data = """
{"fiddle1": {"fiddleHash": "abc",
"compile_errors": [],
"runtime_error": ""}}
"""
fiddleout_with_errors_test_data = """
{"fiddle1": {"fiddleHash": "abc",
"compile_errors": [],
"runtime_error": "runtime error"}}
"""
yield (
api.test('bookmaker') +
api.properties(buildername='Housekeeper-Nightly-Bookmaker',
repository='https://skia.googlesource.com/skia.git',
revision='abc123',
path_config='kitchen',
fiddleout_test_data=fiddleout_no_errors_test_data,
swarm_out_dir='[SWARM_OUT_DIR]') +
api.path.exists(api.path['start_dir'].join('fiddleout.json'),
api.path['start_dir'].join(UPDATE_DOCS_GITCOOKIES_FILE))
)
yield (
api.test('failed_fiddles') +
api.properties(buildername='Housekeeper-Nightly-Bookmaker',
repository='https://skia.googlesource.com/skia.git',
revision='abc123',
path_config='kitchen',
fiddleout_test_data=fiddleout_with_errors_test_data,
swarm_out_dir='[SWARM_OUT_DIR]') +
api.path.exists(api.path['start_dir'].join('fiddleout.json'))
)
yield (
api.test('failed_extract_fiddles') +
api.properties(buildername='Housekeeper-Nightly-Bookmaker',
repository='https://skia.googlesource.com/skia.git',
revision='abc123',
path_config='kitchen',
swarm_out_dir='[SWARM_OUT_DIR]') +
api.step_data('Extract all fiddles out of md files', retcode=1)
)
yield (
api.test('failed_fiddlecli') +
api.properties(buildername='Housekeeper-Nightly-Bookmaker',
repository='https://skia.googlesource.com/skia.git',
revision='abc123',
path_config='kitchen',
swarm_out_dir='[SWARM_OUT_DIR]') +
api.step_data('Force fiddle to compile all examples', retcode=1)
)
yield (
api.test('failed_upload') +
api.properties(buildername='Housekeeper-Nightly-Bookmaker',
repository='https://skia.googlesource.com/skia.git',
revision='abc123',
path_config='kitchen',
swarm_out_dir='[SWARM_OUT_DIR]') +
api.step_data('Generate and Upload Markdown files', retcode=1)
)