blob: 89d6fc75d49f9a6bbd57891b3ff152fdc70b525a [file] [log] [blame]
from recipe_engine.post_process import MustRun, DoesNotRun, SummaryMarkdown, StatusFailure, StatusSuccess
from PB.recipe_engine.result import RawResult
from PB.go.chromium.org.luci.buildbucket.proto import common
PYTHON_VERSION_COMPATIBILITY = "PY3"
# Reference: https://chromium.googlesource.com/infra/luci/recipes-py/+/HEAD/doc/
# All the deps get combined into an `api` variable passed in to RunSteps and
# GenTests. Versions and urls are specified in `recipes.cfg`.
DEPS = [
'depot_tools/gerrit',
'depot_tools/gsutil',
'infra/zip',
'fuchsia/git',
'recipe_engine/buildbucket',
'recipe_engine/context',
'recipe_engine/file',
'recipe_engine/json',
'recipe_engine/nodejs',
'recipe_engine/path',
'recipe_engine/raw_io',
'recipe_engine/step',
]
def RunSteps(api):
# Check out the change and run the frontend linter, type checker, and tests
# to verify the change as part of Change Verification (ie. CQ label). Skips
# everything if no polygerrit-ui/ files are in the change.
files = _getModifiedFiles(api)
if not [f for f in files if f.startswith("polygerrit-ui/")]:
return RawResult(
status=common.SUCCESS,
summary_markdown='No polygerrit-ui/ files found. All checks skipped.',
)
# Checkout the change into a special 'cleanup' folder that is cleared
# between runs of the recipe.
checkout_root = api.path['cleanup'].join('checkout')
api.file.ensure_directory("makedirs", checkout_root)
env = _downloadChromeAndAddToPath(api)
with api.context(env=env, cwd=checkout_root):
_downloadChange(api)
# Now run our verification in the checked out code directory.
# Current LTS for Node.js. Version must be in CIPD packages:
# https://chrome-infra-packages.appspot.com/p/infra/3pp/tools/nodejs/linux-amd64/+/bfm5RWHxZDS1NBdMuNLvXZUq4ULnf_Ho5OzhI3jL_14C
with api.nodejs(version='18.11.0'):
# Named steps to test the change.
# TODO: pipe output to both LUCI UI and Gerrit checks result
api.step('install yarn', ['npm', 'install', '-g', 'yarn'])
api.step('install deps', ['yarn', 'setup'])
api.step('run type checker', ['yarn', 'compile'])
api.step('run linter', ['yarn', 'lint'])
api.step('run tests', ['yarn', 'test'])
return RawResult(
status=common.SUCCESS,
summary_markdown='All checks pass!',
)
def _getModifiedFiles(api):
# Type: https://chromium.googlesource.com/infra/luci/luci-go/+/refs/heads/main/buildbucket/proto/common.proto#179
gerrit_change = api.buildbucket.build.input.gerrit_changes[0]
# Endpoint: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#list-changes
changeInfo = api.gerrit.get_changes(
'https://gerrit-review.googlesource.com',
query_params=[('change', gerrit_change.change)],
o_params=['ALL_REVISIONS', 'ALL_FILES'],
limit=1
)[0]
return _filesFromChangeInfo(changeInfo, gerrit_change.patchset)
def _filesFromChangeInfo(changeInfo, patchset):
return [
file
for revision in changeInfo['revisions'].values()
if revision['_number'] == patchset
for file in revision['files']
]
def _downloadChange(api):
gerrit_change = api.buildbucket.build.input.gerrit_changes[0]
remote = "https://gerrit.googlesource.com/gerrit"
change_ref = "refs/changes/%02d/%d/%d" % (
gerrit_change.change % 100,
gerrit_change.change,
gerrit_change.patchset,
)
api.git.init()
api.git.remote_add("origin", remote)
api.git.fetch(
repository="origin",
refspec=change_ref,
tags=True,
recurse_submodules=True,
)
api.git.raw_checkout(ref="FETCH_HEAD", force=True)
api.git.sync_submodule(recursive=True)
api.git.update_submodule(recursive=True)
def _downloadChromeAndAddToPath(api):
# Download and unzip Chrome from a cloud storage bucket, then add it to the PATH
# and rename it for compatibility with our test runner:
# https://github.com/GoogleChrome/chrome-launcher#launch-options
# Adapted from:
# https://chromium.googlesource.com/infra/infra/+/refs/heads/main/recipes/recipes/gerrit_plugins.py
with api.step.nest('get chrome'):
chrome = api.path.mkdtemp(prefix='chrome')
gs_bucket = 'chromium-browser-snapshots'
gs_path = 'Linux_x64'
version_file = 'LAST_CHANGE'
chrome_zip = 'chrome-linux.zip'
api.gsutil.download(gs_bucket, '%s/%s' %
(gs_path, version_file), chrome)
version = api.file.read_text('read latest chrome version',
chrome.join(version_file))
api.gsutil.download(gs_bucket, '%s/%s/%s' %
(gs_path, version, chrome_zip), chrome)
api.zip.unzip('unzip chrome', chrome.join(
chrome_zip), chrome.join('zip'))
chrome_path = chrome.join('zip', 'chrome-linux')
# The chrome-launcher package expects a binary named "google-chrome" rather
# than "chrome":
# https://github.com/GoogleChrome/chrome-launcher/blob/c753ba083c43a90d98b682bf9ffdfe21680e6208/src/chrome-finder.ts#L133
chrome_bin = chrome_path.join('chrome')
google_chrome_bin = chrome_path.join('google-chrome')
api.step('rename to google-chrome',
['mv', chrome_bin, google_chrome_bin])
env = {
'PATH': api.path.pathsep.join([str(chrome_path), '%(PATH)s']),
}
return env
def GenTests(api):
# Test the recipe and generate the expect json file.
yield api.test(
'polygerrit-ui_changes',
api.buildbucket.try_build(
project="gerrit",
git_repo="https://gerrit.googlesource.com/gerrit",
change_number=123,
patch_set=4
),
api.override_step_data(
'gerrit changes',
api.json.output([{
'_number': 123,
'revisions': {
'a1b2c3': {
'_number': 4,
'files': {"polygerrit-ui/app/foo.ts": {}}
}
}
}])
),
api.post_process(MustRun, 'run type checker'),
api.post_process(MustRun, 'run linter'),
api.post_process(MustRun, 'run tests'),
api.post_process(StatusSuccess),
api.post_process(SummaryMarkdown, 'All checks pass!'),
)
yield api.test(
'polygerrit-ui_changes with failed step',
api.buildbucket.try_build(
project="gerrit",
git_repo="https://gerrit.googlesource.com/gerrit",
change_number=123,
patch_set=4
),
api.override_step_data(
'gerrit changes',
api.json.output([{
'_number': 123,
'revisions': {
'a1b2c3': {
'_number': 4,
'files': {"polygerrit-ui/app/foo.ts": {}}
}
}
}])
),
api.override_step_data(
'run linter',
retcode=1,
stdout=api.raw_io.output('Linter fail: xyz')
),
api.post_process(MustRun, 'run type checker'),
api.post_process(MustRun, 'run linter'),
api.post_process(DoesNotRun, 'run tests'),
api.post_process(StatusFailure),
api.post_process(SummaryMarkdown, 'Step(\'run linter\') (retcode: 1)'),
)
yield api.test(
'no_polygerrit-ui_changes skips tests',
api.buildbucket.try_build(
project="gerrit",
git_repo="https://gerrit.googlesource.com/gerrit",
change_number=123,
patch_set=4
),
api.override_step_data(
'gerrit changes',
api.json.output([{
'_number': 123,
'revisions': {
'a1b2c3': {
'_number': 4,
'files': {"java/com/gerrit/Foo.java": {}}
}
}
}])
),
api.post_process(DoesNotRun, 'run type checker'),
api.post_process(DoesNotRun, 'run linter'),
api.post_process(DoesNotRun, 'run tests'),
api.post_process(StatusSuccess),
api.post_process(
SummaryMarkdown,
'No polygerrit-ui/ files found. All checks skipped.'),
)