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

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

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

Powered by Google App Engine
This is Rietveld 408576698