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

Side by Side Diff: appengine/findit/waterfall/flake/recursive_flake_pipeline.py

Issue 2369333002: [Findit] Capture versionized metadata for master_flake_analysis (Closed)
Patch Set: Created 4 years, 2 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 from common import appengine_util 5 from common import appengine_util
6 from common import constants 6 from common import constants
7 from common import time_util
7 from common.pipeline_wrapper import BasePipeline 8 from common.pipeline_wrapper import BasePipeline
8 9
10
chanli 2016/09/27 22:15:24 Romove this line?
lijeffrey 2016/09/28 03:12:31 Done.
9 from model import analysis_status 11 from model import analysis_status
10 from model.flake.flake_swarming_task import FlakeSwarmingTask 12 from model.flake.flake_swarming_task import FlakeSwarmingTask
11 from model.flake.master_flake_analysis import MasterFlakeAnalysis 13 from model.flake.master_flake_analysis import MasterFlakeAnalysis
12 from waterfall import waterfall_config 14 from waterfall import waterfall_config
13 from waterfall.process_flake_swarming_task_result_pipeline import ( 15 from waterfall.process_flake_swarming_task_result_pipeline import (
14 ProcessFlakeSwarmingTaskResultPipeline) 16 ProcessFlakeSwarmingTaskResultPipeline)
15 from waterfall.trigger_flake_swarming_task_pipeline import ( 17 from waterfall.trigger_flake_swarming_task_pipeline import (
16 TriggerFlakeSwarmingTaskPipeline) 18 TriggerFlakeSwarmingTaskPipeline)
17 19
18 20
21 def _UpdateAnalysisStatusUponCompletion(master_flake_analysis, status, error):
22 master_flake_analysis.completed_time = time_util.GetUTCNow()
23 master_flake_analysis.status = status
24
25 if error:
26 master_flake_analysis.error = error
27
28 master_flake_analysis.put()
29
30
19 class RecursiveFlakePipeline(BasePipeline): 31 class RecursiveFlakePipeline(BasePipeline):
20 32
21 # Arguments number differs from overridden method - pylint: disable=W0221 33 # Arguments number differs from overridden method - pylint: disable=W0221
22 def run(self, master_name, builder_name, run_build_number, step_name, 34 def run(self, master_name, builder_name, run_build_number, step_name,
23 test_name, master_build_number, flakiness_algorithm_results_dict, 35 test_name, master_build_number, flakiness_algorithm_results_dict,
24 queue_name=constants.DEFAULT_QUEUE): 36 queue_name=constants.DEFAULT_QUEUE):
25 """Pipeline to determine the regression range of a flaky test. 37 """Pipeline to determine the regression range of a flaky test.
26 38
27 Args: 39 Args:
28 master_name (str): The master name. 40 master_name (str): The master name.
29 builder_name (str): The builder name. 41 builder_name (str): The builder name.
30 run_build_number (int): The build number of the current swarming rerun. 42 run_build_number (int): The build number of the current swarming rerun.
31 step_name (str): The step name. 43 step_name (str): The step name.
32 test_name (str): The test name. 44 test_name (str): The test name.
33 master_build_number (int): The build number of the Master_Flake_analysis. 45 master_build_number (int): The build number of the Master_Flake_analysis.
34 flakiness_algorithm_results_dict (dict): A dictionary used by 46 flakiness_algorithm_results_dict (dict): A dictionary used by
35 NextBuildNumberPipeline 47 NextBuildNumberPipeline
36 queue_name (str): Which queue to run on. 48 queue_name (str): Which queue to run on.
37 49
38 Returns: 50 Returns:
39 A dict of lists for reliable/flaky tests. 51 A dict of lists for reliable/flaky tests.
40 """ 52 """
41 master = MasterFlakeAnalysis.Get(master_name, builder_name, 53 analysis = MasterFlakeAnalysis.GetVersion(
chanli 2016/09/27 22:15:24 Nit: maybe a longer name so we don't confuse it wi
lijeffrey 2016/09/28 03:12:31 Unfortunately it seems the #pragma: no branch does
42 master_build_number, step_name, test_name) 54 master_name, builder_name, master_build_number, step_name, test_name)
43 if master.status != analysis_status.RUNNING: # pragma: no branch 55
44 master.status = analysis_status.RUNNING 56 if analysis.status != analysis_status.RUNNING: # pragma: no branch
45 master.put() 57 analysis.status = analysis_status.RUNNING
58 analysis.put()
46 59
47 # Call trigger pipeline (flake style). 60 # Call trigger pipeline (flake style).
48 task_id = yield TriggerFlakeSwarmingTaskPipeline( 61 task_id = yield TriggerFlakeSwarmingTaskPipeline(
49 master_name, builder_name, run_build_number, step_name, [test_name]) 62 master_name, builder_name, run_build_number, step_name, [test_name])
50 # Pass the trigger pipeline into a process pipeline. 63 # Pass the trigger pipeline into a process pipeline.
51 test_result_future = yield ProcessFlakeSwarmingTaskResultPipeline( 64 test_result_future = yield ProcessFlakeSwarmingTaskResultPipeline(
52 master_name, builder_name, run_build_number, 65 master_name, builder_name, run_build_number,
53 step_name, task_id, master_build_number, test_name) 66 step_name, task_id, master_build_number, test_name)
54 yield NextBuildNumberPipeline( 67 yield NextBuildNumberPipeline(
55 master_name, builder_name, master_build_number, run_build_number, 68 master_name, builder_name, master_build_number, run_build_number,
56 step_name, test_name, test_result_future, queue_name, 69 step_name, test_name, test_result_future, queue_name,
57 flakiness_algorithm_results_dict) 70 flakiness_algorithm_results_dict)
58 71
59 72
60 def get_next_run(master, flakiness_algorithm_results_dict): 73 def get_next_run(master_flake_analysis, flakiness_algorithm_results_dict):
61 # A description of this algorithm can be found at: 74 # A description of this algorithm can be found at:
62 # https://docs.google.com/document/d/1wPYFZ5OT998Yn7O8wGDOhgfcQ98mknoX13AesJaS 6ig/edit 75 # https://docs.google.com/document/d/1wPYFZ5OT998Yn7O8wGDOhgfcQ98mknoX13AesJaS 6ig/edit
63 # Get the last result. 76 # Get the last result.
64 last_result = master.success_rates[-1] 77 last_result = master_flake_analysis.pass_rates[-1]
65 cur_run = min(master.build_numbers) 78 cur_run = min(master_flake_analysis.build_numbers)
66 flake_settings = waterfall_config.GetCheckFlakeSettings() 79 flake_settings = waterfall_config.GetCheckFlakeSettings()
67 lower_flake_threshold = flake_settings.get('lower_flake_threshold') 80 lower_flake_threshold = flake_settings.get('lower_flake_threshold')
68 upper_flake_threshold = flake_settings.get('upper_flake_threshold') 81 upper_flake_threshold = flake_settings.get('upper_flake_threshold')
69 max_stable_in_a_row = flake_settings.get('max_stable_in_a_row') 82 max_stable_in_a_row = flake_settings.get('max_stable_in_a_row')
70 max_flake_in_a_row = flake_settings.get('max_flake_in_a_row') 83 max_flake_in_a_row = flake_settings.get('max_flake_in_a_row')
71 84
72 if last_result < 0: # Test doesn't exist in the current build number. 85 if last_result < 0: # Test doesn't exist in the current build number.
73 flakiness_algorithm_results_dict['stable_in_a_row'] += 1 86 flakiness_algorithm_results_dict['stable_in_a_row'] += 1
74 flakiness_algorithm_results_dict['stabled_out'] = True 87 flakiness_algorithm_results_dict['stabled_out'] = True
75 flakiness_algorithm_results_dict['flaked_out'] = True 88 flakiness_algorithm_results_dict['flaked_out'] = True
76 flakiness_algorithm_results_dict['lower_boundary_result'] = 'STABLE' 89 flakiness_algorithm_results_dict['lower_boundary_result'] = 'STABLE'
77 90
78 lower_boundary = master.build_numbers[ 91 lower_boundary = master_flake_analysis.build_numbers[
79 -flakiness_algorithm_results_dict['stable_in_a_row']] 92 -flakiness_algorithm_results_dict['stable_in_a_row']]
80 93
81 flakiness_algorithm_results_dict['lower_boundary'] = lower_boundary 94 flakiness_algorithm_results_dict['lower_boundary'] = lower_boundary
82 flakiness_algorithm_results_dict['sequential_run_index'] += 1 95 flakiness_algorithm_results_dict['sequential_run_index'] += 1
83 return lower_boundary + 1 96 return lower_boundary + 1
84 elif (last_result < lower_flake_threshold or 97 elif (last_result < lower_flake_threshold or
85 last_result > upper_flake_threshold): # Stable result. 98 last_result > upper_flake_threshold): # Stable result.
86 flakiness_algorithm_results_dict['stable_in_a_row'] += 1 99 flakiness_algorithm_results_dict['stable_in_a_row'] += 1
87 if (flakiness_algorithm_results_dict['stable_in_a_row'] > 100 if (flakiness_algorithm_results_dict['stable_in_a_row'] >
88 max_stable_in_a_row): # Identified a stable region. 101 max_stable_in_a_row): # Identified a stable region.
89 flakiness_algorithm_results_dict['stabled_out'] = True 102 flakiness_algorithm_results_dict['stabled_out'] = True
90 if (flakiness_algorithm_results_dict['stabled_out'] and 103 if (flakiness_algorithm_results_dict['stabled_out'] and
91 not flakiness_algorithm_results_dict['flaked_out']): 104 not flakiness_algorithm_results_dict['flaked_out']):
92 # Identified a candidate for the upper boundary. 105 # Identified a candidate for the upper boundary.
93 # Earliest stable point to the right of a flaky region. 106 # Earliest stable point to the right of a flaky region.
94 flakiness_algorithm_results_dict['upper_boundary'] = cur_run 107 flakiness_algorithm_results_dict['upper_boundary'] = cur_run
95 flakiness_algorithm_results_dict['lower_boundary'] = None 108 flakiness_algorithm_results_dict['lower_boundary'] = None
(...skipping 24 matching lines...) Expand all
120 not flakiness_algorithm_results_dict['lower_boundary']): 133 not flakiness_algorithm_results_dict['lower_boundary']):
121 # Identified a candidate for the lower boundary. 134 # Identified a candidate for the lower boundary.
122 # Latest flaky point to the left of a stable region. 135 # Latest flaky point to the left of a stable region.
123 flakiness_algorithm_results_dict['lower_boundary'] = cur_run 136 flakiness_algorithm_results_dict['lower_boundary'] = cur_run
124 flakiness_algorithm_results_dict['lower_boundary_result'] = 'FLAKE' 137 flakiness_algorithm_results_dict['lower_boundary_result'] = 'FLAKE'
125 flakiness_algorithm_results_dict['stable_in_a_row'] = 0 138 flakiness_algorithm_results_dict['stable_in_a_row'] = 0
126 step_size = flakiness_algorithm_results_dict['flakes_in_a_row'] + 1 139 step_size = flakiness_algorithm_results_dict['flakes_in_a_row'] + 1
127 return cur_run - step_size 140 return cur_run - step_size
128 141
129 142
130 def sequential_next_run(master, flakiness_algorithm_results_dict): 143 def sequential_next_run(
131 last_result = master.success_rates[-1] 144 master_flake_analysis, flakiness_algorithm_results_dict):
145 last_result = master_flake_analysis.pass_rates[-1]
132 last_result_status = 'FLAKE' 146 last_result_status = 'FLAKE'
133 flake_settings = waterfall_config.GetCheckFlakeSettings() 147 flake_settings = waterfall_config.GetCheckFlakeSettings()
134 lower_flake_threshold = flake_settings.get('lower_flake_threshold') 148 lower_flake_threshold = flake_settings.get('lower_flake_threshold')
135 upper_flake_threshold = flake_settings.get('upper_flake_threshold') 149 upper_flake_threshold = flake_settings.get('upper_flake_threshold')
136 150
137 if (last_result < lower_flake_threshold or 151 if (last_result < lower_flake_threshold or
138 last_result > upper_flake_threshold): 152 last_result > upper_flake_threshold):
139 last_result_status = 'STABLE' 153 last_result_status = 'STABLE'
140 if flakiness_algorithm_results_dict['sequential_run_index'] > 0: 154 if flakiness_algorithm_results_dict['sequential_run_index'] > 0:
141 if (last_result_status != 155 if (last_result_status !=
142 flakiness_algorithm_results_dict['lower_boundary_result']): 156 flakiness_algorithm_results_dict['lower_boundary_result']):
143 master.suspected_flake_build_number = ( 157 master_flake_analysis.suspected_flake_build_number = (
144 flakiness_algorithm_results_dict['lower_boundary'] + 158 flakiness_algorithm_results_dict['lower_boundary'] +
145 flakiness_algorithm_results_dict['sequential_run_index']) 159 flakiness_algorithm_results_dict['sequential_run_index'])
146 master.put() 160 master_flake_analysis.put()
147 return 0 161 return 0
148 flakiness_algorithm_results_dict['sequential_run_index'] += 1 162 flakiness_algorithm_results_dict['sequential_run_index'] += 1
149 return (flakiness_algorithm_results_dict['lower_boundary'] + 163 return (flakiness_algorithm_results_dict['lower_boundary'] +
150 flakiness_algorithm_results_dict['sequential_run_index']) 164 flakiness_algorithm_results_dict['sequential_run_index'])
151 165
152 166
153 class NextBuildNumberPipeline(BasePipeline): 167 class NextBuildNumberPipeline(BasePipeline):
154 168
155 # Arguments number differs from overridden method - pylint: disable=W0221 169 # Arguments number differs from overridden method - pylint: disable=W0221
156 # Unused argument - pylint: disable=W0613 170 # Unused argument - pylint: disable=W0613
157 def run(self, master_name, builder_name, master_build_number, 171 def run(self, master_name, builder_name, master_build_number,
158 run_build_number, step_name, test_name, test_result_future, 172 run_build_number, step_name, test_name, test_result_future,
159 queue_name, flakiness_algorithm_results_dict): 173 queue_name, flakiness_algorithm_results_dict):
160 174
161 # Get MasterFlakeAnalysis success list corresponding to parameters. 175 # Get MasterFlakeAnalysis success list corresponding to parameters.
162 master = MasterFlakeAnalysis.Get(master_name, builder_name, 176 master_flake_analysis = MasterFlakeAnalysis.GetVersion(
163 master_build_number, step_name, test_name) 177 master_name, builder_name, master_build_number, step_name, test_name)
164 # Don't call another pipeline if we fail. 178 # Don't call another pipeline if we fail.
165 flake_swarming_task = FlakeSwarmingTask.Get( 179 flake_swarming_task = FlakeSwarmingTask.Get(
166 master_name, builder_name, run_build_number, step_name, test_name) 180 master_name, builder_name, run_build_number, step_name, test_name)
167 181
168 if flake_swarming_task.status == analysis_status.ERROR: 182 if flake_swarming_task.status == analysis_status.ERROR:
169 master.status = analysis_status.ERROR 183 # TODO(lijeffrey): Implement more detailed error detection and reporting,
170 master.put() 184 # such as timeouts, dead bots, etc.
185 error = {
186 'error': 'An error occurred',
187 'message': 'Unknown'
stgao 2016/09/28 00:03:24 Can we say "Swarming task failed" for now?
lijeffrey 2016/09/28 03:12:31 Done.
188 }
189 _UpdateAnalysisStatusUponCompletion(
190 master_flake_analysis, analysis_status.ERROR, error)
171 return 191 return
172 192
173 # Figure out what build_number we should call, if any 193 # Figure out what build_number we should call, if any
174 if (flakiness_algorithm_results_dict['stabled_out'] and 194 if (flakiness_algorithm_results_dict['stabled_out'] and
175 flakiness_algorithm_results_dict['flaked_out']): 195 flakiness_algorithm_results_dict['flaked_out']):
176 next_run = sequential_next_run(master, flakiness_algorithm_results_dict) 196 next_run = sequential_next_run(
197 master_flake_analysis, flakiness_algorithm_results_dict)
177 else: 198 else:
178 next_run = get_next_run(master, flakiness_algorithm_results_dict) 199 next_run = get_next_run(
200 master_flake_analysis, flakiness_algorithm_results_dict)
179 201
180 if next_run < flakiness_algorithm_results_dict['last_build_number']: 202 if next_run < flakiness_algorithm_results_dict['last_build_number']:
181 next_run = 0 203 next_run = 0
182 elif next_run >= master_build_number: 204 elif next_run >= master_build_number:
183 next_run = 0 205 next_run = 0
184 206
185 if next_run: 207 if next_run:
186 pipeline_job = RecursiveFlakePipeline( 208 pipeline_job = RecursiveFlakePipeline(
187 master_name, builder_name, next_run, step_name, test_name, 209 master_name, builder_name, next_run, step_name, test_name,
188 master_build_number, 210 master_build_number,
189 flakiness_algorithm_results_dict=flakiness_algorithm_results_dict) 211 flakiness_algorithm_results_dict=flakiness_algorithm_results_dict)
190 # pylint: disable=W0201 212 # pylint: disable=W0201
191 pipeline_job.target = appengine_util.GetTargetNameForModule( 213 pipeline_job.target = appengine_util.GetTargetNameForModule(
192 constants.WATERFALL_BACKEND) 214 constants.WATERFALL_BACKEND)
193 pipeline_job.start(queue_name=queue_name) 215 pipeline_job.start(queue_name=queue_name)
194 else: 216 else:
195 master.status = analysis_status.COMPLETED 217 _UpdateAnalysisStatusUponCompletion(
196 master.put() 218 master_flake_analysis, analysis_status.COMPLETED, None)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698