Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(97)

Side by Side Diff: appengine/findit/waterfall/start_try_job_on_demand_pipeline.py

Issue 2187763004: [Findit] Refactor Findit pipeline. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Rebase and address comments. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2016 The Chromium Authors. All rights reserved. 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 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import logging
6
5 from common.pipeline_wrapper import BasePipeline 7 from common.pipeline_wrapper import BasePipeline
6 from model.wf_analysis import WfAnalysis 8 from common.waterfall import failure_type
7 from waterfall import try_job_util 9 from waterfall import try_job_util
10 from waterfall.identify_try_job_culprit_pipeline import (
11 IdentifyTryJobCulpritPipeline)
12 from waterfall.monitor_try_job_pipeline import MonitorTryJobPipeline
13 from waterfall.process_swarming_task_result_pipeline import (
14 ProcessSwarmingTaskResultPipeline)
15 from waterfall.schedule_compile_try_job_pipeline import (
16 ScheduleCompileTryJobPipeline)
17 from waterfall.schedule_test_try_job_pipeline import (
18 ScheduleTestTryJobPipeline)
19
20
21 def _GetLastPassCompile(build_number, failed_steps):
22 if (failed_steps.get('compile') and
23 failed_steps['compile']['first_failure'] == build_number and
24 failed_steps['compile'].get('last_pass') is not None):
25 return failed_steps['compile']['last_pass']
26 return None
27
28
29 def _GetLastPassTest(build_number, failed_steps):
30 for step_failure in failed_steps.itervalues():
31 for test_failure in step_failure['tests'].itervalues():
32 if (test_failure['first_failure'] == build_number and
33 test_failure.get('last_pass') is not None):
34 return test_failure['last_pass']
35 return None
36
37
38 def _GetLastPass(build_number, failure_info, try_job_type):
39 if try_job_type == failure_type.COMPILE:
40 return _GetLastPassCompile(build_number, failure_info['failed_steps'])
41 elif try_job_type == failure_type.TEST:
42 return _GetLastPassTest(build_number, failure_info['failed_steps'])
43 else:
44 return None
45
46
47 def _GetSuspectsFromHeuristicResult(heuristic_result):
48 if not heuristic_result:
49 return []
50
51 suspected_revisions = set()
52 for failure in heuristic_result.get('failures', []):
53 for cl in failure['suspected_cls']:
54 suspected_revisions.add(cl['revision'])
55 return list(suspected_revisions)
8 56
9 57
10 class StartTryJobOnDemandPipeline(BasePipeline): 58 class StartTryJobOnDemandPipeline(BasePipeline):
11 59
12 # Arguments number differs from overridden method - pylint: disable=W0221 60 # Arguments number differs from overridden method - pylint: disable=W0221
13 def run(self, failure_info, signals, build_completed, force_try_job, 61 def run(self, master_name, builder_name, build_number, failure_info,
14 heuristic_result): 62 signals, heuristic_result, build_completed, force_try_job):
15 """Starts a try job if one is needed for the given failure.""" 63 """Starts a try job if one is needed for the given failure."""
64
16 if not build_completed: # Only start try-jobs for completed builds. 65 if not build_completed: # Only start try-jobs for completed builds.
17 return False 66 return
18 67
19 failure_result_map = try_job_util.ScheduleTryJobIfNeeded( 68 need_try_job = try_job_util.NeedANewTryJob(
20 failure_info, signals=signals, heuristic_result=heuristic_result, 69 master_name, builder_name, build_number, failure_info, signals,
21 force_try_job=force_try_job) 70 heuristic_result, force_try_job)
22 71
23 # Save reference to the try-jobs if any was scheduled. 72 if not need_try_job:
24 master_name = failure_info['master_name'] 73 return
25 builder_name = failure_info['builder_name'] 74
26 build_number = failure_info['build_number'] 75 try_job_type = failure_info['failure_type']
27 analysis = WfAnalysis.Get(master_name, builder_name, build_number) 76 last_pass = _GetLastPass(build_number, failure_info, try_job_type)
28 analysis.failure_result_map = failure_result_map 77 if last_pass is None: # pragma: no cover
29 analysis.put() 78 logging.warning('Couldn"t start try job because last_pass is not found.')
lijeffrey 2016/08/09 04:07:34 is this a normal scenario that last pass is unavai
chanli 2016/08/09 17:08:43 There are some cases: 1. If a failure has happened
30 return True 79 return
80
81 blame_list = failure_info['builds'][str(build_number)]['blame_list']
82 good_revision = failure_info['builds'][str(last_pass)]['chromium_revision']
83 bad_revision = failure_info['builds'][str(build_number)][
84 'chromium_revision']
85 suspected_revisions = _GetSuspectsFromHeuristicResult(heuristic_result)
86
87 if try_job_type == failure_type.COMPILE:
88 compile_targets = try_job_util.GetFailedTargetsFromSignals(
89 signals, master_name, builder_name)
90 try_job_id = yield ScheduleCompileTryJobPipeline(
91 master_name, builder_name, build_number, good_revision, bad_revision,
92 try_job_type, compile_targets, suspected_revisions)
93 try_job_result = yield MonitorTryJobPipeline(
94 master_name, builder_name, build_number, try_job_type, try_job_id)
95 yield IdentifyTryJobCulpritPipeline(
96 master_name, builder_name, build_number, blame_list, try_job_type,
97 try_job_id, try_job_result)
98 else:
99 # If try_job_type is other type, the pipeline has returned.
100 # So here the try_job_type is failure_type.TEST.
101
102 # Waits and gets the swarming tasks' results.
103 reliable_tests = []
104 for step_name, step_failure in failure_info['failed_steps'].iteritems():
105 step_has_first_time_failure = False
106 for test_failure in step_failure['tests'].itervalues():
lijeffrey 2016/08/09 04:07:34 I would break this part into a separate helper met
chanli 2016/08/09 17:08:42 Done.
107 if test_failure['first_failure'] == build_number:
108 step_has_first_time_failure = True
109 break
110 if not step_has_first_time_failure:
111 continue
112 task_result = yield ProcessSwarmingTaskResultPipeline(
113 master_name, builder_name, build_number, step_name)
114 reliable_tests.append(task_result)
115
116 try_job_id = yield ScheduleTestTryJobPipeline(
117 master_name, builder_name, build_number, good_revision, bad_revision,
118 try_job_type, suspected_revisions, *reliable_tests)
119 try_job_result = yield MonitorTryJobPipeline(
120 master_name, builder_name, build_number, try_job_type, try_job_id)
121 yield IdentifyTryJobCulpritPipeline(
122 master_name, builder_name, build_number, blame_list, try_job_type,
123 try_job_id, try_job_result)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698