Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 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 collections import defaultdict | 5 from collections import defaultdict |
| 6 import logging | 6 import logging |
| 7 | 7 |
| 8 from google.appengine.ext import ndb | 8 from google.appengine.ext import ndb |
| 9 | 9 |
| 10 from common.git_repository import GitRepository | 10 from common.git_repository import GitRepository |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 175 for failed_test in test_result['failures']: | 175 for failed_test in test_result['failures']: |
| 176 # Swarming tests, gets first failed revision for each test. | 176 # Swarming tests, gets first failed revision for each test. |
| 177 if failed_test not in culprit_map[step]['tests']: | 177 if failed_test not in culprit_map[step]['tests']: |
| 178 culprit_map[step]['tests'][failed_test] = { | 178 culprit_map[step]['tests'][failed_test] = { |
| 179 'revision': revision | 179 'revision': revision |
| 180 } | 180 } |
| 181 | 181 |
| 182 return culprit_map, list(failed_revisions) | 182 return culprit_map, list(failed_revisions) |
| 183 | 183 |
| 184 | 184 |
| 185 def _NotifyCulprits(master_name, builder_name, build_number, culprits): | 185 def _GetSuspectedCLFoundByHeuristicForCompile(analysis): |
| 186 """For compile failure, gets the suspected revision found by heuristic.""" | |
| 187 if not analysis or not analysis.result: | |
| 188 return None | |
| 189 | |
| 190 for failure in analysis.result.get('failures', []): | |
| 191 if (failure['step_name'].lower() == 'compile' and | |
| 192 len(failure['suspected_cls']) == 1): | |
| 193 # Based on confidence calculation, suspected_cl found by heuristic for | |
| 194 # compile is very likely to be the culprit. | |
| 195 # Since the current confidence calculation is for results with single | |
| 196 # suspected_cl, we might need to have the same regulation here. | |
| 197 return failure['suspected_cls'][0] | |
| 198 return None | |
| 199 | |
| 200 | |
| 201 def _GetHeuristicSuspectedCLs(analysis): | |
| 202 """Gets revisions of suspected cls found by heuristic approach.""" | |
| 203 if analysis and analysis.suspected_cls: | |
| 204 return [(cl['repo_name'], cl['revision']) for cl in analysis.suspected_cls] | |
| 205 return [] | |
| 206 | |
| 207 | |
| 208 def _StartSendNotificationPipeline( | |
| 209 master_name, builder_name, build_number, repo_name, revision, | |
| 210 send_notification_right_now): | |
| 211 try: | |
| 212 pipeline = SendNotificationForCulpritPipeline( | |
| 213 master_name, builder_name, build_number, repo_name, revision, | |
|
lijeffrey1
2016/09/06 16:53:56
nit: 4 spaces instead of 2
chanli
2016/09/06 17:12:42
Done.
| |
| 214 send_notification_right_now) | |
| 215 pipeline.start() | |
| 216 except Exception: # pragma: no cover. | |
| 217 logging.exception( | |
| 218 'Failed to notify culprit.') | |
|
lijeffrey1
2016/09/06 16:53:56
nit: Keep this on 1 line
chanli
2016/09/06 17:12:42
Done.
| |
| 219 | |
| 220 | |
| 221 def _NotifyCulprits(master_name, builder_name, build_number, culprits, | |
| 222 heuristic_cls, compile_suspected_cl): | |
| 186 """Sends notifications to the identified culprits.""" | 223 """Sends notifications to the identified culprits.""" |
| 187 try: | 224 |
| 188 for culprit in (culprits or {}).itervalues(): | 225 if culprits: |
| 189 pipeline = SendNotificationForCulpritPipeline( | 226 # There is a try job result, so check if any of the culprits |
| 227 # was also found by heuristic analysis. | |
| 228 for culprit in culprits.itervalues(): | |
| 229 send_notification_right_now = False | |
| 230 if (culprit['repo_name'], culprit['revision']) in heuristic_cls: | |
| 231 send_notification_right_now = True | |
| 232 _StartSendNotificationPipeline( | |
| 190 master_name, builder_name, build_number, | 233 master_name, builder_name, build_number, |
| 191 culprit['repo_name'], culprit['revision']) | 234 culprit['repo_name'], culprit['revision'], |
| 192 pipeline.start() | 235 send_notification_right_now) |
| 193 except Exception: # pragma: no cover. | 236 elif compile_suspected_cl: |
| 194 logging.exception('Failed to notify culprits.') | 237 # Need to check if the failure is compile and heuristic found a culprit. |
| 238 _StartSendNotificationPipeline( | |
| 239 master_name, builder_name, build_number, | |
| 240 compile_suspected_cl['repo_name'], compile_suspected_cl['revision'], | |
| 241 send_notification_right_now=True) | |
| 195 | 242 |
| 196 | 243 |
| 197 class IdentifyTryJobCulpritPipeline(BasePipeline): | 244 class IdentifyTryJobCulpritPipeline(BasePipeline): |
| 198 """A pipeline to identify culprit CL info based on try job compile results.""" | 245 """A pipeline to identify culprit CL info based on try job compile results.""" |
| 199 | 246 |
| 200 def _GetCulpritInfo(self, failed_revisions): | 247 def _GetCulpritInfo(self, failed_revisions): |
| 201 """Gets commit_positions and review urls for revisions.""" | 248 """Gets commit_positions and review urls for revisions.""" |
| 202 culprits = {} | 249 culprits = {} |
| 203 # TODO(lijeffrey): remove hard-coded 'chromium' when DEPS file parsing is | 250 # TODO(lijeffrey): remove hard-coded 'chromium' when DEPS file parsing is |
| 204 # supported. | 251 # supported. |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 317 try_job_result.status = analysis_status.COMPLETED | 364 try_job_result.status = analysis_status.COMPLETED |
| 318 try_job_result.put() | 365 try_job_result.put() |
| 319 | 366 |
| 320 @ndb.transactional | 367 @ndb.transactional |
| 321 def UpdateWfAnalysisWithTryJobResult(): | 368 def UpdateWfAnalysisWithTryJobResult(): |
| 322 if not culprits: | 369 if not culprits: |
| 323 return | 370 return |
| 324 | 371 |
| 325 # Update analysis result and suspected CLs with results of this try job if | 372 # Update analysis result and suspected CLs with results of this try job if |
| 326 # culprits were found. | 373 # culprits were found. |
| 327 analysis = WfAnalysis.Get(master_name, builder_name, build_number) | |
| 328 updated_result_status = _GetResultAnalysisStatus(analysis, result) | 374 updated_result_status = _GetResultAnalysisStatus(analysis, result) |
| 329 updated_suspected_cls = _GetSuspectedCLs(analysis, result) | 375 updated_suspected_cls = _GetSuspectedCLs(analysis, result) |
| 330 | 376 |
| 331 if (analysis.result_status != updated_result_status or | 377 if (analysis.result_status != updated_result_status or |
| 332 analysis.suspected_cls != updated_suspected_cls): | 378 analysis.suspected_cls != updated_suspected_cls): |
| 333 analysis.result_status = updated_result_status | 379 analysis.result_status = updated_result_status |
| 334 analysis.suspected_cls = updated_suspected_cls | 380 analysis.suspected_cls = updated_suspected_cls |
| 335 analysis.put() | 381 analysis.put() |
| 336 | 382 |
| 337 # Store try-job results. | 383 # Store try-job results. |
| 338 UpdateTryJobResult() | 384 UpdateTryJobResult() |
| 385 | |
| 386 analysis = WfAnalysis.Get(master_name, builder_name, build_number) | |
| 387 heuristic_cls = _GetHeuristicSuspectedCLs(analysis) | |
| 388 compile_suspected_cl = ( | |
| 389 _GetSuspectedCLFoundByHeuristicForCompile(analysis) | |
| 390 if try_job_type == failure_type.COMPILE else None) | |
| 391 | |
| 339 # Add try-job results to WfAnalysis. | 392 # Add try-job results to WfAnalysis. |
| 340 UpdateWfAnalysisWithTryJobResult() | 393 UpdateWfAnalysisWithTryJobResult() |
| 341 | 394 |
| 342 _NotifyCulprits(master_name, builder_name, build_number, culprits) | 395 _NotifyCulprits(master_name, builder_name, build_number, culprits, |
| 343 return result.get('culprit') if result else None | 396 heuristic_cls, compile_suspected_cl) |
| 397 return result.get('culprit') if result else None | |
| OLD | NEW |