blob: deb3c7afdefdc30c7573b093a2cabfc9f80e7ad9 [file] [log] [blame]
# Copyright 2020 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 for engine repository tests."""
import contextlib
import copy
from recipe_engine import recipe_api
from PB.recipes.flutter.engine import InputProperties
from PB.recipes.flutter.engine import EnvProperties
DEPS = [
'depot_tools/bot_update',
'depot_tools/depot_tools',
'depot_tools/gclient',
'depot_tools/git',
'depot_tools/gsutil',
'depot_tools/osx_sdk',
'flutter/os_utils',
'flutter/json_util',
'flutter/repo_util',
'flutter/yaml',
'fuchsia/goma',
'recipe_engine/buildbucket',
'recipe_engine/cipd',
'recipe_engine/context',
'recipe_engine/file',
'recipe_engine/json',
'recipe_engine/path',
'recipe_engine/platform',
'recipe_engine/properties',
'recipe_engine/runtime',
'recipe_engine/step',
]
GIT_REPO = (
'https://chromium.googlesource.com/external/github.com/flutter/engine')
PROPERTIES = InputProperties
ENV_PROPERTIES = EnvProperties
@contextlib.contextmanager
def SetupXcode(api):
# See cr-buildbucket.cfg for how the version is passed in.
# https://github.com/flutter/infra/blob/master/config/cr-buildbucket.cfg#L148
with api.osx_sdk('ios'):
yield
def Build(api, config, *targets):
checkout = GetCheckoutPath(api)
build_dir = checkout.join('out/%s' % config)
goma_jobs = api.properties['goma_jobs']
ninja_args = [api.depot_tools.ninja_path, '-j', goma_jobs, '-C', build_dir]
ninja_args.extend(targets)
with api.goma.build_with_goma():
name = 'build %s' % ' '.join([config] + list(targets))
api.step(name, ninja_args)
def FormatAndDartTest(api):
checkout = GetCheckoutPath(api)
with api.context(cwd=checkout.join('flutter')):
format_cmd = checkout.join('flutter', 'ci', 'format.sh')
api.step('format and dart test', [format_cmd])
def Lint(api):
checkout = GetCheckoutPath(api)
with api.context(cwd=checkout):
lint_cmd = checkout.join('flutter', 'ci', 'lint.sh')
api.step('lint test', [lint_cmd])
def RunGN(api, *args):
checkout = GetCheckoutPath(api)
gn_cmd = ['python', checkout.join('flutter/tools/gn'), '--goma']
gn_cmd.extend(args)
api.step('gn %s' % ' '.join(args), gn_cmd)
def GetCheckoutPath(api):
return api.path['cache'].join('builder', 'src')
def DownloadFirefoxDriver(api):
checkout = GetCheckoutPath(api)
# Download the driver for Firefox.
firefox_driver_path = checkout.join('flutter', 'lib', 'web_ui', '.dart_tool',
'drivers', 'firefox')
pkgdriver = api.cipd.EnsureFile()
pkgdriver.add_package('flutter_internal/browser-drivers/firefoxdriver-linux',
'latest')
api.cipd.ensure(firefox_driver_path, pkgdriver)
def DownloadChromeAndDriver(api, chrome_path_84):
checkout = GetCheckoutPath(api)
# Download a specific version of chrome-linux before running Flutter Web
# tests.
# Please make sure at least one of the versions in this method is this file:
# flutter/engine/blob/master/lib/web_ui/dev/browser_lock.yaml#L4
# Chrome uses binary numbers for archiving different versions of the browser.
chrome_pkg_84 = api.cipd.EnsureFile()
chrome_pkg_84.add_package('flutter_internal/browsers/chrome/${platform}',
'latest-84')
api.cipd.ensure(chrome_path_84, chrome_pkg_84)
# Download the driver for Chrome 84.
chrome_driver_84_path = checkout.join('flutter', 'lib', 'web_ui',
'.dart_tool', 'drivers', 'chrome', '84')
chrome_pkgdriver_84 = api.cipd.EnsureFile()
chrome_pkgdriver_84.add_package(
'flutter_internal/browser-drivers/chrome/${platform}', 'latest-84')
api.cipd.ensure(chrome_driver_84_path, chrome_pkgdriver_84)
# Chrome uses binary numbers for archiving different versions of the browser.
# The binary 741412 has major version 82.
# TODO: remove this version once 84 start working with no issues.
chrome_path_82 = checkout.join('flutter', 'lib', 'web_ui', '.dart_tool',
'chrome', '741412')
chrome_pkg_82 = api.cipd.EnsureFile()
chrome_pkg_82.add_package('flutter_internal/browsers/chrome-linux', 'latest')
api.cipd.ensure(chrome_path_82, chrome_pkg_82)
# Download the driver for Chrome 82.
# TODO: remove this version once 84 start working with no issues.
chrome_driver_82_path = checkout.join('flutter', 'lib', 'web_ui',
'.dart_tool', 'drivers', 'chrome')
chrome_pkgdriver_82 = api.cipd.EnsureFile()
chrome_pkgdriver_82.add_package(
'flutter_internal/browser-drivers/chromedriver-linux', 'latest')
api.cipd.ensure(chrome_driver_82_path, chrome_pkgdriver_82)
def CloneGoldens(api):
builder_root = api.path['cache'].join('builder')
goldens = builder_root.join('goldens')
api.file.ensure_directory('mkdir goldens', goldens)
checkout = GetCheckoutPath(api)
golden_yaml_file = checkout.join('flutter', 'lib', 'web_ui', 'dev',
'goldens_lock.yaml')
with api.context(cwd=builder_root):
# Use golden_lock.yaml file to read url of the goldens repository and
# the revision number to checkout.
# https://github.com/flutter/engine/blob/master/lib/web_ui/dev/goldens_lock.yaml
# This file is used by web engine developers. The engine developers update
# the flutter/goldens.git repo when they need changes. Later change the
# revision number on this file.
result = api.yaml.read(
'read yaml',
golden_yaml_file,
api.json.output(),
)
# The content of the file is expected to be:
#
# repository: https://github.com/flutter/goldens.git
# revision: b6efc75885c23f0b5c485d8bd659ed339feec9ec
golden_lock_content = result.json.output
repo = golden_lock_content['repository']
revision_number = golden_lock_content['revision']
with api.context(cwd=goldens):
api.git.checkout(
repo,
dir_path=goldens,
ref=revision_number,
recursive=True,
set_got_revision=True)
golden_files = checkout.join('flutter', 'lib', 'web_ui', '.dart_tool',
'goldens')
api.file.copytree('copy goldens', goldens, golden_files)
def UploadFailingGoldens(api, checkout, browser):
logs_path = checkout.join('flutter', 'lib', 'web_ui', '.dart_tool',
'test_results')
tests_info_file_path = logs_path.join('info.txt')
api.file.write_text(
'write info file',
tests_info_file_path,
'tests for %s' % api.platform.name,
'tests for windows',
)
if api.properties.get('gcs_goldens_bucket'):
if browser == 'chrome':
bucket_id = api.buildbucket.build.id
else:
bucket_id = str(api.buildbucket.build.id) + browser
api.gsutil.upload(
bucket=api.properties['gcs_goldens_bucket'],
source=logs_path,
dest='%s/%s' % ('web_engine', bucket_id),
link_name='archive goldens',
args=['-r'],
multithreaded=True,
name='upload goldens %s' % bucket_id,
unauthenticated_url=True)
html_files = api.file.glob_paths(
'html goldens',
source=logs_path,
pattern='*.html',
test_data=('a.html',)).get_result()
with api.step.nest('Failed golden links') as presentation:
for html_file in html_files:
base_name = api.path.basename(html_file)
url = 'https://storage.googleapis.com/%s/web_engine/%s/%s' % (
api.properties['gcs_goldens_bucket'], bucket_id, base_name)
presentation.links[base_name] = url
def RunSteps(api, properties, env_properties):
"""Steps to checkout flutter engine and execute web tests."""
cache_root = api.path['cache'].join('builder')
checkout = GetCheckoutPath(api)
if properties.clobber:
api.file.rmtree('Clobber cache', cache_root)
api.file.rmtree('Clobber build output', checkout.join('out'))
# Collect memory/cpu/process before task execution.
api.os_utils.collect_os_info()
api.file.ensure_directory('Ensure checkout cache', cache_root)
api.goma.ensure()
dart_bin = checkout.join('third_party', 'dart', 'tools', 'sdks', 'dart-sdk',
'bin')
android_home = checkout.join('third_party', 'android_tools', 'sdk')
env = {
'GOMA_DIR': api.goma.goma_dir,
'ANDROID_HOME': str(android_home),
'CHROME_NO_SANDBOX': 'true',
'ENGINE_PATH': cache_root
}
env_prefixes = {'PATH': [dart_bin]}
# Checkout source code and build
api.repo_util.engine_checkout(cache_root, env, env_prefixes)
if api.platform.is_mac:
CloneGoldens(api)
with api.context(
cwd=cache_root, env=env,
env_prefixes=env_prefixes), api.depot_tools.on_path():
# Checks before building the engine. Only run on Linux.
if api.platform.is_linux:
api.json_util.validate_json(checkout.join('flutter', 'ci'))
FormatAndDartTest(api)
Lint(api)
# Presence of tags in git repo is critical for determining dart version.
dart_sdk_dir = GetCheckoutPath(api).join('third_party', 'dart')
with api.context(cwd=dart_sdk_dir):
# The default fetch remote is a local dir, so explicitly fetch from
# upstream remote
api.step(
'Fetch dart tags',
['git', 'fetch', 'https://dart.googlesource.com/sdk.git', '--tags'])
api.step('List all tags', ['git', 'tag', '--list'])
api.gclient.runhooks()
target_name = 'host_debug_unopt'
gn_flags = ['--unoptimized', '--full-dart-sdk']
# Mac needs to install xcode as part of the building process.
additional_args = []
felt_cmd = [
checkout.join('out', target_name, 'dart-sdk', 'bin', 'dart'),
'dev/felt.dart'
]
if api.platform.is_mac:
with SetupXcode(api):
RunGN(api, *gn_flags)
Build(api, target_name)
additional_args = ['--browser', 'ios-safari']
else:
RunGN(api, *gn_flags)
Build(api, target_name)
if api.platform.is_win:
felt_cmd = [
checkout.join('flutter', 'lib', 'web_ui', 'dev', 'felt_windows.bat')
]
# Update dart packages and run tests.
local_pub = checkout.join('out', target_name, 'dart-sdk', 'bin', 'pub')
with api.context(
cwd=checkout.join('flutter', 'web_sdk', 'web_engine_tester')):
api.step('pub get in web_engine_tester', [local_pub, 'get'])
with api.context(cwd=checkout.join('flutter', 'lib', 'web_ui')):
api.step('pub get in web_engine_tester', [local_pub, 'get'])
felt_licenses = copy.deepcopy(felt_cmd)
felt_licenses.append('check-licenses')
api.step('felt licenses', felt_licenses)
if api.platform.is_win:
chrome_path = checkout.join('flutter', 'lib', 'web_ui', '.dart_tool',
'chrome', '768975')
if api.platform.is_mac:
chrome_path = checkout.join('flutter', 'lib', 'web_ui', '.dart_tool',
'chrome', '768985')
additional_args_safari_desktop = ['--browser', 'safari']
felt_test_safari_desktop = copy.deepcopy(felt_cmd)
felt_test_safari_desktop.append('test')
felt_test_safari_desktop.extend(additional_args_safari_desktop)
api.step('felt test safari desktop', felt_test_safari_desktop)
if api.platform.is_linux:
web_engine_analysis_cmd = [
checkout.join('flutter', 'lib', 'web_ui', 'dev',
'web_engine_analysis.sh'),
]
api.step('web engine analysis', web_engine_analysis_cmd)
DownloadFirefoxDriver(api)
additional_args_firefox = ['--browser', 'firefox']
felt_test_firefox = copy.deepcopy(felt_cmd)
felt_test_firefox.append('test')
felt_test_firefox.extend(additional_args_firefox)
with recipe_api.defer_results():
api.step('felt test firefox', felt_test_firefox)
UploadFailingGoldens(api, checkout, 'firefox')
chrome_path = checkout.join('flutter', 'lib', 'web_ui', '.dart_tool',
'chrome', '768968')
DownloadChromeAndDriver(api, chrome_path)
felt_test = copy.deepcopy(felt_cmd)
felt_test.append('test')
felt_test.extend(additional_args)
if api.platform.is_mac:
with SetupXcode(api):
with recipe_api.defer_results():
api.step('felt ios-safari test', felt_test)
UploadFailingGoldens(api, checkout, 'ios-safari')
else:
with recipe_api.defer_results():
api.step('felt test chrome', felt_test)
UploadFailingGoldens(api, checkout, 'chrome')
# Collect memory/cpu/process after task execution.
api.os_utils.collect_os_info()
def GenTests(api):
golden_yaml_file = {'repository': 'repo', 'revision': 'b6efc758'}
yield api.test('linux-post-submit') + api.properties(
goma_jobs='200') + api.platform('linux', 64)
yield api.test('windows-post-submit') + api.properties(
goma_jobs='200') + api.platform('win', 32)
yield api.test(
'mac-post-submit',
api.step_data('read yaml.parse', api.json.output(golden_yaml_file)),
api.properties(goma_jobs='200'), api.platform('mac', 64))
yield api.test('linux-pre-submit') + api.properties(
goma_jobs='200',
git_url='https://mygitrepo',
git_ref='refs/pull/1/head',
gcs_goldens_bucket='mybucket',
clobber=True) + api.platform('linux', 64)