| 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 common.git_repository import GitRepository | 5 from common.git_repository import GitRepository |
| 6 from common.http_client_appengine import HttpClientAppengine as HttpClient | 6 from common.http_client_appengine import HttpClientAppengine as HttpClient |
| 7 from common.pipeline_wrapper import BasePipeline | 7 from common.pipeline_wrapper import BasePipeline |
| 8 from model import analysis_status | 8 from model import analysis_status |
| 9 from model import result_status | 9 from model import result_status |
| 10 from model.wf_analysis import WfAnalysis | 10 from model.wf_analysis import WfAnalysis |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 Args: | 50 Args: |
| 51 analysis: The WfAnalysis entity corresponding to this try job. | 51 analysis: The WfAnalysis entity corresponding to this try job. |
| 52 result: A result dict containing the culprit from the results of | 52 result: A result dict containing the culprit from the results of |
| 53 this try job. | 53 this try job. |
| 54 | 54 |
| 55 Returns: | 55 Returns: |
| 56 A combined list of suspected CLs from those already in analysis and those | 56 A combined list of suspected CLs from those already in analysis and those |
| 57 found by this try job. | 57 found by this try job. |
| 58 """ | 58 """ |
| 59 suspected_cls = analysis.suspected_cls[:] if analysis.suspected_cls else [] | 59 suspected_cls = analysis.suspected_cls[:] if analysis.suspected_cls else [] |
| 60 suspected_cl_revisions = [cl['revision'] for cl in suspected_cls] |
| 60 culprit = result.get('culprit') | 61 culprit = result.get('culprit') |
| 61 compile_cl_info = culprit.get('compile') | 62 compile_cl_info = culprit.get('compile') |
| 62 | 63 |
| 63 if compile_cl_info: | 64 if compile_cl_info: |
| 64 # Suspected CL is from compile failure. | 65 # Suspected CL is from compile failure. |
| 65 if compile_cl_info not in suspected_cls: | 66 revision = compile_cl_info.get('revision') |
| 67 if revision not in suspected_cl_revisions: |
| 68 suspected_cl_revisions.append(revision) |
| 66 suspected_cls.append(compile_cl_info) | 69 suspected_cls.append(compile_cl_info) |
| 67 return suspected_cls | 70 return suspected_cls |
| 68 | 71 |
| 69 # Suspected CLs are from test failures. | 72 # Suspected CLs are from test failures. |
| 70 for results in culprit.itervalues(): | 73 for results in culprit.itervalues(): |
| 71 if results.get('revision'): | 74 if results.get('revision'): |
| 72 # Non swarming test failures, only have step level failure info. | 75 # Non swarming test failures, only have step level failure info. |
| 76 revision = results.get('revision') |
| 73 cl_info = { | 77 cl_info = { |
| 74 'review_url': results.get('review_url'), | 78 'url': results.get('url'), |
| 75 'repo_name': results.get('repo_name'), | 79 'repo_name': results.get('repo_name'), |
| 76 'revision': results.get('revision'), | 80 'revision': results.get('revision'), |
| 77 'commit_position': results.get('commit_position') | 81 'commit_position': results.get('commit_position') |
| 78 } | 82 } |
| 79 if cl_info not in suspected_cls: | 83 if revision not in suspected_cl_revisions: |
| 84 suspected_cl_revisions.append(revision) |
| 80 suspected_cls.append(cl_info) | 85 suspected_cls.append(cl_info) |
| 81 else: | 86 else: |
| 82 for test_cl_info in results['tests'].values(): | 87 for test_cl_info in results['tests'].values(): |
| 83 if test_cl_info not in suspected_cls: | 88 revision = test_cl_info.get('revision') |
| 89 if revision not in suspected_cl_revisions: |
| 90 suspected_cl_revisions.append(revision) |
| 84 suspected_cls.append(test_cl_info) | 91 suspected_cls.append(test_cl_info) |
| 85 | 92 |
| 86 return suspected_cls | 93 return suspected_cls |
| 87 | 94 |
| 88 | 95 |
| 89 class IdentifyTryJobCulpritPipeline(BasePipeline): | 96 class IdentifyTryJobCulpritPipeline(BasePipeline): |
| 90 """A pipeline to identify culprit CL info based on try job compile results.""" | 97 """A pipeline to identify culprit CL info based on try job compile results.""" |
| 91 | 98 |
| 92 def _GetCulpritInfo(self, failed_revisions): | 99 def _GetCulpritInfo(self, failed_revisions): |
| 93 """Gets commit_positions and review_urls for revisions.""" | 100 """Gets commit_positions and review urls for revisions.""" |
| 94 culprits = {} | 101 culprits = {} |
| 95 # TODO(lijeffrey): remove hard-coded 'chromium' when DEPS file parsing is | 102 # TODO(lijeffrey): remove hard-coded 'chromium' when DEPS file parsing is |
| 96 # supported. | 103 # supported. |
| 97 for failed_revision in failed_revisions: | 104 for failed_revision in failed_revisions: |
| 98 culprits[failed_revision] = { | 105 culprits[failed_revision] = { |
| 99 'revision': failed_revision, | 106 'revision': failed_revision, |
| 100 'repo_name': 'chromium' | 107 'repo_name': 'chromium' |
| 101 } | 108 } |
| 102 change_log = GIT_REPO.GetChangeLog(failed_revision) | 109 change_log = GIT_REPO.GetChangeLog(failed_revision) |
| 103 if change_log: | 110 if change_log: |
| 104 culprits[failed_revision]['commit_position'] = ( | 111 culprits[failed_revision]['commit_position'] = ( |
| 105 change_log.commit_position) | 112 change_log.commit_position) |
| 106 culprits[failed_revision]['review_url'] = change_log.code_review_url | 113 culprits[failed_revision]['url'] = ( |
| 114 change_log.code_review_url or change_log.commit_url) |
| 107 | 115 |
| 108 return culprits | 116 return culprits |
| 109 | 117 |
| 110 @staticmethod | 118 @staticmethod |
| 111 def _GetFailedRevisionFromResultsDict(results_dict): | 119 def _GetFailedRevisionFromResultsDict(results_dict): |
| 112 """Finds the failed revision from the given dict of revisions. | 120 """Finds the failed revision from the given dict of revisions. |
| 113 | 121 |
| 114 Args: | 122 Args: |
| 115 results_dict: (dict) A dict that maps revisions to their results. For | 123 results_dict: (dict) A dict that maps revisions to their results. For |
| 116 example: | 124 example: |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 for failed_test in test_result['failures']: | 196 for failed_test in test_result['failures']: |
| 189 # Swarming tests, gets first failed revision for each test. | 197 # Swarming tests, gets first failed revision for each test. |
| 190 if failed_test not in culprit_map[step]['tests']: | 198 if failed_test not in culprit_map[step]['tests']: |
| 191 culprit_map[step]['tests'][failed_test] = { | 199 culprit_map[step]['tests'][failed_test] = { |
| 192 'revision': revision | 200 'revision': revision |
| 193 } | 201 } |
| 194 | 202 |
| 195 return culprit_map, failed_revisions | 203 return culprit_map, failed_revisions |
| 196 | 204 |
| 197 def _UpdateCulpritMapWithCulpritInfo(self, culprit_map, culprits): | 205 def _UpdateCulpritMapWithCulpritInfo(self, culprit_map, culprits): |
| 198 """Fills in commit_position and review_url for each failed rev in map.""" | 206 """Fills in commit_position and review url for each failed rev in map.""" |
| 199 for step_culprit in culprit_map.values(): | 207 for step_culprit in culprit_map.values(): |
| 200 if step_culprit.get('revision'): | 208 if step_culprit.get('revision'): |
| 201 culprit = culprits[step_culprit['revision']] | 209 culprit = culprits[step_culprit['revision']] |
| 202 step_culprit['commit_position'] = culprit['commit_position'] | 210 step_culprit['commit_position'] = culprit['commit_position'] |
| 203 step_culprit['review_url'] = culprit['review_url'] | 211 step_culprit['url'] = culprit['url'] |
| 204 for test_culprit in step_culprit.get('tests', {}).values(): | 212 for test_culprit in step_culprit.get('tests', {}).values(): |
| 205 test_revision = test_culprit['revision'] | 213 test_revision = test_culprit['revision'] |
| 206 test_culprit.update(culprits[test_revision]) | 214 test_culprit.update(culprits[test_revision]) |
| 207 | 215 |
| 208 def _GetCulpritDataForTest(self, culprit_map): | 216 def _GetCulpritDataForTest(self, culprit_map): |
| 209 """Gets culprit revision for each failure for try job metadata.""" | 217 """Gets culprit revision for each failure for try job metadata.""" |
| 210 culprit_data = {} | 218 culprit_data = {} |
| 211 for step, step_culprit in culprit_map.iteritems(): | 219 for step, step_culprit in culprit_map.iteritems(): |
| 212 if step_culprit['tests']: | 220 if step_culprit['tests']: |
| 213 culprit_data[step] = {} | 221 culprit_data[step] = {} |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 if (analysis.result_status != updated_result_status or | 281 if (analysis.result_status != updated_result_status or |
| 274 analysis.suspected_cls != updated_suspected_cls): | 282 analysis.suspected_cls != updated_suspected_cls): |
| 275 analysis.result_status = updated_result_status | 283 analysis.result_status = updated_result_status |
| 276 analysis.suspected_cls = updated_suspected_cls | 284 analysis.suspected_cls = updated_suspected_cls |
| 277 analysis.put() | 285 analysis.put() |
| 278 | 286 |
| 279 try_job_result.status = analysis_status.COMPLETED | 287 try_job_result.status = analysis_status.COMPLETED |
| 280 try_job_result.put() | 288 try_job_result.put() |
| 281 | 289 |
| 282 return result.get('culprit') if result else None | 290 return result.get('culprit') if result else None |
| OLD | NEW |