| OLD | NEW |
| (Empty) |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 from collections import defaultdict | |
| 6 import logging | |
| 7 | |
| 8 from common import appengine_util | |
| 9 from common import constants | |
| 10 from common.pipeline_wrapper import BasePipeline | |
| 11 from model import analysis_status | |
| 12 from model.wf_try_job import WfTryJob | |
| 13 from waterfall import try_job_pipeline | |
| 14 from waterfall.try_job_type import TryJobType | |
| 15 | |
| 16 | |
| 17 def _GetReliableTargetedTests(targeted_tests, classified_tests_by_step, | |
| 18 force_try_job=False): | |
| 19 """Returns a dict containing a list of reliable tests for each failed step.""" | |
| 20 reliable_tests = defaultdict(list) | |
| 21 for step_name, tests in targeted_tests.iteritems(): | |
| 22 # Skips non-swarming steps to avoid false positives. | |
| 23 # TODO(chanli): It is very unlikely for some non-swarming steps to be flaky. | |
| 24 # Need to identify those steps and add them to a whitelist. | |
| 25 if step_name in classified_tests_by_step: # Swarming step. | |
| 26 step_name_no_platform = classified_tests_by_step[step_name][0] | |
| 27 classified_tests = classified_tests_by_step[step_name][1] | |
| 28 | |
| 29 for test in tests: | |
| 30 # If the step is swarming but there is no result for it, it's highly | |
| 31 # likely that there is some error with the task. | |
| 32 # Thus skip this step for no insights from task to avoid false positive. | |
| 33 if test in classified_tests.get('reliable_tests', []): | |
| 34 reliable_tests[step_name_no_platform].append(test) | |
| 35 elif force_try_job: | |
| 36 # Try jobs were forced to be rerun regardless of being non-swarming. | |
| 37 reliable_tests[step_name] = [] | |
| 38 return reliable_tests | |
| 39 | |
| 40 | |
| 41 class RunTryJobForReliableFailurePipeline(BasePipeline): | |
| 42 """A pipeline to trigger try job for reliable failures. | |
| 43 | |
| 44 Processes result from SwarmingTaskPipeline and start TryJobPipeline if there | |
| 45 are reliable test failures. | |
| 46 Starts TryJobPipeline directly for compile failure. | |
| 47 """ | |
| 48 | |
| 49 # Arguments number differs from overridden method - pylint: disable=W0221 | |
| 50 def run( | |
| 51 self, master_name, builder_name, build_number, good_revision, | |
| 52 bad_revision, blame_list, try_job_type, compile_targets, targeted_tests, | |
| 53 suspected_revisions, force_try_job, *classified_tests_by_step): | |
| 54 """ | |
| 55 Args: | |
| 56 master_name (str): Name of the master. | |
| 57 builder_name (str): Name of the builder. | |
| 58 build_number (int): Number of the current failed build. | |
| 59 good_revision (str): Revision of last green build. | |
| 60 bad_revision (str): Revision of current build. | |
| 61 blame_list (list): A list of revisions between above 2 revisions. | |
| 62 try_job_type (str): Type of the try job ('compile' or 'test'). | |
| 63 compile_targets (list): A list of failed targets for compile failure. | |
| 64 targeted_tests (dict): A dict of failed tests for test failure. | |
| 65 suspected_revisions (list): Suspected revisions for a compile failure. | |
| 66 force_try_job (bool): Whether or not a try job should be run | |
| 67 regardless of non swarming-steps. | |
| 68 *classified_tests_by_step (list): A list of tuples of step_name and | |
| 69 classified_tests. The format is like: | |
| 70 [('step1', {'flaky_tests': ['test1', ..], ..}), | |
| 71 ..] | |
| 72 """ | |
| 73 if try_job_type == TryJobType.TEST: | |
| 74 targeted_tests = _GetReliableTargetedTests( | |
| 75 targeted_tests, dict(classified_tests_by_step), force_try_job) | |
| 76 | |
| 77 if targeted_tests or try_job_type == TryJobType.COMPILE: | |
| 78 new_try_job_pipeline = try_job_pipeline.TryJobPipeline( | |
| 79 master_name, builder_name, build_number, good_revision, | |
| 80 bad_revision, blame_list, try_job_type, compile_targets, | |
| 81 targeted_tests, suspected_revisions) | |
| 82 | |
| 83 new_try_job_pipeline.target = appengine_util.GetTargetNameForModule( | |
| 84 constants.WATERFALL_BACKEND) | |
| 85 new_try_job_pipeline.start(queue_name=constants.WATERFALL_TRY_JOB_QUEUE) | |
| 86 logging.info('Try-job was scheduled for build %s, %s, %s: %s', | |
| 87 master_name, builder_name, build_number, | |
| 88 new_try_job_pipeline.pipeline_status_path) | |
| 89 else: # pragma: no cover | |
| 90 # No need to start try job, mark it as skipped. | |
| 91 try_job_result = WfTryJob.Get( | |
| 92 master_name, builder_name, build_number) | |
| 93 if try_job_result: | |
| 94 try_job_result.status = analysis_status.SKIPPED | |
| 95 try_job_result.put() | |
| 96 return | |
| OLD | NEW |