| # 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. |
| |
| from recipe_engine.recipe_api import Property |
| |
| DEPS = [ |
| 'flutter/bucket_util', |
| 'flutter/devicelab_osx_sdk', |
| 'flutter/flutter_deps', |
| 'flutter/logs_util', |
| 'flutter/repo_util', |
| 'flutter/os_utils', |
| 'flutter/osx_sdk', |
| 'flutter/retry', |
| 'flutter/test_utils', |
| 'recipe_engine/buildbucket', |
| 'recipe_engine/context', |
| 'recipe_engine/file', |
| 'recipe_engine/path', |
| 'recipe_engine/properties', |
| 'recipe_engine/raw_io', |
| 'recipe_engine/runtime', |
| 'recipe_engine/service_account', |
| 'recipe_engine/step', |
| 'recipe_engine/swarming', |
| ] |
| |
| # Fifteen minutes |
| MAX_TIMEOUT_SECS = 30 * 60 |
| |
| |
| def RunSteps(api): |
| task_name = api.properties.get("task_name") |
| if not task_name: |
| raise ValueError('A task_name property is required') |
| |
| api.os_utils.print_pub_certs() |
| |
| flutter_path = api.path.mkdtemp().join('flutter sdk') |
| api.repo_util.checkout( |
| 'flutter', |
| flutter_path, |
| api.properties.get('git_url'), |
| api.properties.get('git_ref'), |
| ) |
| env, env_prefixes = api.repo_util.flutter_environment(flutter_path) |
| api.logs_util.initialize_logs_collection(env) |
| with api.step.nest('Dependencies'): |
| deps = api.properties.get('dependencies', []) |
| api.flutter_deps.required_deps(env, env_prefixes, deps) |
| api.flutter_deps.vpython(env, env_prefixes, 'latest') |
| devicelab_path = flutter_path.join('dev', 'devicelab') |
| git_branch = api.buildbucket.gitiles_commit.ref.replace('refs/heads/', '') |
| # Create tmp file to store results in |
| results_path = api.path.mkstemp() |
| # Run test |
| runner_params = [ |
| '-t', task_name, '--results-file', results_path, '--luci-builder', |
| api.properties.get('buildername') |
| ] |
| # LUCI git checkouts end up in a detached HEAD state, so branch must |
| # be passed from gitiles -> test runner -> Cocoon. |
| if git_branch: |
| # git_branch is set only when the build was triggered by buildbucket. |
| runner_params.extend(['--git-branch', git_branch]) |
| with api.context(env=env, env_prefixes=env_prefixes, cwd=devicelab_path): |
| api.retry.step( |
| 'flutter doctor', |
| ['flutter', 'doctor'], |
| max_attempts=3, |
| timeout=300, |
| ) |
| api.step('pub get', ['pub', 'get'], infra_step=True) |
| dep_list = {d['dependency']: d.get('version') for d in deps} |
| if dep_list.has_key('xcode'): |
| api.os_utils.clean_derived_data() |
| if str(api.swarming.bot_id).startswith('flutter-devicelab'): |
| with api.devicelab_osx_sdk('ios'): |
| mac_test( |
| api, env, env_prefixes, flutter_path, task_name, runner_params |
| ) |
| else: |
| with api.osx_sdk('ios'): |
| mac_test( |
| api, env, env_prefixes, flutter_path, task_name, runner_params |
| ) |
| else: |
| with api.context(env=env, |
| env_prefixes=env_prefixes), api.step.defer_results(): |
| api.retry.step( |
| 'flutter doctor', |
| ['flutter', 'doctor', '--verbose'], |
| max_attempts=3, |
| timeout=300, |
| ) |
| test_runner_command = ['dart', 'bin/test_runner.dart', 'test'] |
| test_runner_command.extend(runner_params) |
| api.test_utils.run_test( |
| 'run %s' % task_name, |
| test_runner_command, |
| timeout_secs=MAX_TIMEOUT_SECS |
| ) |
| api.logs_util.upload_logs(task_name) |
| # This is to clean up leaked processes. |
| api.os_utils.kill_processes() |
| |
| with api.context(env=env, env_prefixes=env_prefixes, cwd=devicelab_path): |
| uploadMetrics(api, results_path) |
| |
| |
| def mac_test(api, env, env_prefixes, flutter_path, task_name, runner_params): |
| """Runs a devicelab mac test.""" |
| api.flutter_deps.gems( |
| env, env_prefixes, flutter_path.join('dev', 'ci', 'mac') |
| ) |
| api.retry.step( |
| 'flutter doctor', ['flutter', 'doctor', '--verbose'], |
| max_attempts=3, |
| timeout=300 |
| ) |
| api.os_utils.dismiss_dialogs() |
| api.os_utils.shutdown_simulators() |
| with api.context(env=env, |
| env_prefixes=env_prefixes), api.step.defer_results(): |
| resource_name = api.resource('runner.sh') |
| api.step('Set execute permission', ['chmod', '755', resource_name]) |
| test_runner_command = [resource_name] |
| test_runner_command.extend(runner_params) |
| api.test_utils.run_test( |
| 'run %s' % task_name, |
| test_runner_command, |
| timeout_secs=MAX_TIMEOUT_SECS |
| ) |
| api.logs_util.upload_logs(task_name) |
| # This is to clean up leaked processes. |
| api.os_utils.kill_processes() |
| |
| |
| def uploadMetrics(api, results_path): |
| """Upload DeviceLab test performance metrics to Cocoon. |
| |
| luci-auth only gurantees a service account token life of 3 minutes. To work |
| around this limitation, results uploading is separate from the the test run. |
| """ |
| if not api.properties.get('upload_metrics') or api.runtime.is_experimental: |
| return |
| with api.step.nest('Upload metrics'): |
| service_account = api.service_account.default() |
| access_token = service_account.get_access_token() |
| access_token_path = api.path.mkstemp() |
| api.file.write_text( |
| "write token", access_token_path, access_token, include_log=False |
| ) |
| upload_command = [ |
| 'dart', 'bin/test_runner.dart', 'upload-metrics', '--results-file', |
| results_path, '--service-account-token-file', access_token_path |
| ] |
| api.step('upload metrics', upload_command, infra_step=True) |
| |
| |
| def GenTests(api): |
| checkout_path = api.path['cleanup'].join('tmp_tmp_1', 'flutter sdk') |
| yield api.test( |
| "no-task-name", |
| api.expect_exception('ValueError'), |
| ) |
| yield api.test( |
| "basic", api.properties(buildername='Linux abc', task_name='abc'), |
| api.repo_util.flutter_environment_data(checkout_dir=checkout_path), |
| api.buildbucket.ci_build( |
| project='test', |
| git_repo='git.example.com/test/repo', |
| ) |
| ) |
| yield api.test( |
| "xcode-devicelab", |
| api.properties( |
| buildername='Mac abc', |
| task_name='abc', |
| dependencies=[{'dependency': 'xcode'}] |
| ), api.repo_util.flutter_environment_data(checkout_dir=checkout_path), |
| api.swarming.properties(bot_id='flutter-devicelab-mac-1') |
| ) |
| yield api.test( |
| "xcode-chromium-mac", |
| api.properties( |
| buildername='Mac abc', |
| task_name='abc', |
| dependencies=[{'dependency': 'xcode'}] |
| ), |
| api.repo_util.flutter_environment_data(checkout_dir=checkout_path), |
| ) |
| yield api.test( |
| "post-submit", |
| api.properties( |
| buildername='Linux abc', task_name='abc', upload_metrics=True |
| ), api.repo_util.flutter_environment_data(checkout_dir=checkout_path) |
| ) |
| yield api.test( |
| "upload-metrics-mac", |
| api.properties( |
| buildername='Mac abc', |
| dependencies=[{'dependency': 'xcode'}], |
| task_name='abc', |
| upload_metrics=True |
| ), api.repo_util.flutter_environment_data(checkout_dir=checkout_path) |
| ) |