Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 base64 | 5 import base64 |
| 6 import logging | |
| 6 | 7 |
| 7 from google.appengine.ext import ndb | 8 from google.appengine.ext import ndb |
| 8 | 9 |
| 10 from gae_libs.http.http_client_appengine import HttpClientAppengine | |
| 11 from gae_libs.gitiles.cached_gitiles_repository import CachedGitilesRepository | |
| 9 from gae_libs.model.versioned_model import VersionedModel | 12 from gae_libs.model.versioned_model import VersionedModel |
| 10 from model import result_status | 13 from model import result_status |
| 11 from model import triage_status | 14 from model import triage_status |
| 12 from model.base_analysis import BaseAnalysis | 15 from model.base_analysis import BaseAnalysis |
| 13 from model.base_build_model import BaseBuildModel | 16 from model.base_build_model import BaseBuildModel |
| 14 from model.base_triaged_model import TriagedModel | 17 from model.base_triaged_model import TriagedModel |
| 18 from model.flake.flake_suspected_cl import FlakeSuspectedCL | |
| 15 from model.flake.flake_swarming_task import FlakeSwarmingTaskData | 19 from model.flake.flake_swarming_task import FlakeSwarmingTaskData |
| 16 | 20 |
| 17 | 21 |
| 18 class DataPoint(ndb.Model): | 22 class DataPoint(ndb.Model): |
| 19 build_number = ndb.IntegerProperty(indexed=False) | 23 build_number = ndb.IntegerProperty(indexed=False) |
| 20 pass_rate = ndb.FloatProperty(indexed=False) | 24 pass_rate = ndb.FloatProperty(indexed=False) |
| 21 task_id = ndb.StringProperty(indexed=False) | 25 task_id = ndb.StringProperty(indexed=False) |
| 22 commit_position = ndb.IntegerProperty(indexed=False) | 26 commit_position = ndb.IntegerProperty(indexed=False) |
| 23 git_hash = ndb.StringProperty(indexed=False) | 27 git_hash = ndb.StringProperty(indexed=False) |
| 24 previous_build_commit_position = ndb.IntegerProperty(indexed=False) | 28 previous_build_commit_position = ndb.IntegerProperty(indexed=False) |
| 25 previous_build_git_hash = ndb.StringProperty(indexed=False) | 29 previous_build_git_hash = ndb.StringProperty(indexed=False) |
| 26 blame_list = ndb.StringProperty(repeated=True) | 30 blame_list = ndb.StringProperty(repeated=True) |
| 27 | 31 |
| 28 | 32 |
| 29 class MasterFlakeAnalysis( | 33 class MasterFlakeAnalysis( |
| 30 BaseAnalysis, BaseBuildModel, VersionedModel, TriagedModel): | 34 BaseAnalysis, BaseBuildModel, VersionedModel, TriagedModel): |
| 31 """Represents an analysis of a flaky test on a Waterfall test cycle.""" | 35 """Represents an analysis of a flaky test on a Waterfall test cycle.""" |
| 32 | 36 |
| 37 GIT_REPO = CachedGitilesRepository( | |
| 38 HttpClientAppengine(), | |
| 39 'https://chromium.googlesource.com/chromium/src.git') | |
| 40 | |
| 33 @ndb.ComputedProperty | 41 @ndb.ComputedProperty |
| 34 def step_name(self): | 42 def step_name(self): |
| 35 return self.key.pairs()[0][1].split('/')[3] | 43 return self.key.pairs()[0][1].split('/')[3] |
| 36 | 44 |
| 37 @ndb.ComputedProperty | 45 @ndb.ComputedProperty |
| 38 def test_name(self): | 46 def test_name(self): |
| 39 return base64.urlsafe_b64decode(self.key.pairs()[0][1].split('/')[4]) | 47 return base64.urlsafe_b64decode(self.key.pairs()[0][1].split('/')[4]) |
| 40 | 48 |
| 41 @property | 49 @property |
| 42 def error_message(self): | 50 def error_message(self): |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 88 def UpdateTriageResult(self, triage_result, suspect_info, user_name, | 96 def UpdateTriageResult(self, triage_result, suspect_info, user_name, |
| 89 version_number=None): | 97 version_number=None): |
| 90 super(MasterFlakeAnalysis, self).UpdateTriageResult( | 98 super(MasterFlakeAnalysis, self).UpdateTriageResult( |
| 91 triage_result, suspect_info, user_name, version_number=version_number) | 99 triage_result, suspect_info, user_name, version_number=version_number) |
| 92 | 100 |
| 93 if triage_result == triage_status.TRIAGED_CORRECT: | 101 if triage_result == triage_status.TRIAGED_CORRECT: |
| 94 self.result_status = result_status.FOUND_CORRECT | 102 self.result_status = result_status.FOUND_CORRECT |
| 95 else: | 103 else: |
| 96 self.result_status = result_status.FOUND_INCORRECT | 104 self.result_status = result_status.FOUND_INCORRECT |
| 97 | 105 |
| 106 def UpdateSuspectedCL(self, repo_name, revision): | |
| 107 """Sets suspected_cl information.""" | |
| 108 change_log = self.GIT_REPO.GetChangeLog(revision) | |
|
stgao
2017/01/05 21:28:03
It seems better to move this out to the caller cod
lijeffrey
2017/01/06 05:18:16
Sounds good, by moving change_log outside to the c
| |
| 109 | |
| 110 if change_log: | |
| 111 code_review_url = change_log.code_review_url or change_log.commit_url | |
|
stgao
2017/01/05 21:28:03
See comment above.
lijeffrey
2017/01/06 05:18:16
Done.
| |
| 112 suspected_cl = FlakeSuspectedCL.Create( | |
| 113 repo_name, revision, change_log.commit_position, code_review_url) | |
| 114 self.suspected_cl = suspected_cl | |
| 115 else: # pragma: no cover | |
| 116 logging.error('Unable to retrieve change logs for %s', revision) | |
| 117 | |
| 118 def GetSuspectedFlakeDataPoint(self): | |
| 119 """Gets the corresponding data point to the suspected flake build.""" | |
| 120 if self.suspected_flake_build_number is not None: | |
| 121 for data_point in self.data_points: | |
| 122 if data_point.build_number == self.suspected_flake_build_number: | |
| 123 return data_point | |
| 124 | |
| 125 return None | |
| 126 | |
| 98 def Reset(self): | 127 def Reset(self): |
| 99 super(MasterFlakeAnalysis, self).Reset() | 128 super(MasterFlakeAnalysis, self).Reset() |
| 100 self.original_master_name = None | 129 self.original_master_name = None |
| 101 self.original_builder_name = None | 130 self.original_builder_name = None |
| 102 self.original_build_number = None | 131 self.original_build_number = None |
| 103 self.original_step_name = None | 132 self.original_step_name = None |
| 104 self.original_test_name = None | 133 self.original_test_name = None |
| 105 self.bug_id = None | 134 self.bug_id = None |
| 106 self.swarming_rerun_results = [] | 135 self.swarming_rerun_results = [] |
| 107 self.error = None | 136 self.error = None |
| 108 self.correct_regression_range = None | 137 self.correct_regression_range = None |
| 109 self.correct_culprit = None | 138 self.correct_culprit = None |
| 110 self.algorithm_parameters = None | 139 self.algorithm_parameters = None |
| 111 self.suspected_flake_build_number = None | 140 self.suspected_flake_build_number = None |
| 141 self.suspected_cl = None | |
| 142 self.try_job_status = None | |
| 112 self.data_points = [] | 143 self.data_points = [] |
| 113 self.result_status = None | 144 self.result_status = None |
| 114 | 145 |
| 115 # The original build/step/test in which a flake actually occurred. | 146 # The original build/step/test in which a flake actually occurred. |
| 116 # A CQ trybot step has to be mapped to a Waterfall buildbot step. | 147 # A CQ trybot step has to be mapped to a Waterfall buildbot step. |
| 117 # A gtest suite.PRE_PRE_test has to be normalized to suite.test. | 148 # A gtest suite.PRE_PRE_test has to be normalized to suite.test. |
| 118 original_master_name = ndb.StringProperty(indexed=True) | 149 original_master_name = ndb.StringProperty(indexed=True) |
| 119 original_builder_name = ndb.StringProperty(indexed=True) | 150 original_builder_name = ndb.StringProperty(indexed=True) |
| 120 original_build_number = ndb.IntegerProperty(indexed=True) | 151 original_build_number = ndb.IntegerProperty(indexed=True) |
| 121 original_step_name = ndb.StringProperty(indexed=True) | 152 original_step_name = ndb.StringProperty(indexed=True) |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 151 # 'max_build_numbers_to_look_back': 500, | 182 # 'max_build_numbers_to_look_back': 500, |
| 152 # 'max_flake_in_a_row': 4, | 183 # 'max_flake_in_a_row': 4, |
| 153 # 'max_stable_in_a_row': 4, | 184 # 'max_stable_in_a_row': 4, |
| 154 # 'upper_flake_threshold': 0.98 | 185 # 'upper_flake_threshold': 0.98 |
| 155 # } | 186 # } |
| 156 algorithm_parameters = ndb.JsonProperty(indexed=False) | 187 algorithm_parameters = ndb.JsonProperty(indexed=False) |
| 157 | 188 |
| 158 # The suspected build number to have introduced the flakiness. | 189 # The suspected build number to have introduced the flakiness. |
| 159 suspected_flake_build_number = ndb.IntegerProperty() | 190 suspected_flake_build_number = ndb.IntegerProperty() |
| 160 | 191 |
| 192 # The suspected CL associated with the try job results, if any. | |
| 193 suspected_cl = ndb.LocalStructuredProperty(FlakeSuspectedCL) | |
| 194 | |
| 195 # The status of the try job, if any. None if no suspected flake build number | |
| 196 # yet. | |
| 197 try_job_status = ndb.IntegerProperty(indexed=False) | |
| 198 | |
| 161 # The data points used to plot the flakiness graph build over build. | 199 # The data points used to plot the flakiness graph build over build. |
| 162 data_points = ndb.LocalStructuredProperty( | 200 data_points = ndb.LocalStructuredProperty( |
| 163 DataPoint, repeated=True, compressed=True) | 201 DataPoint, repeated=True, compressed=True) |
| 164 | 202 |
| 165 # Whether the analysis was triggered by a manual request through check flake, | 203 # Whether the analysis was triggered by a manual request through check flake, |
| 166 # Findit's automatic analysis upon detection, or Findit API. | 204 # Findit's automatic analysis upon detection, or Findit API. |
| 167 triggering_source = ndb.IntegerProperty(default=None, indexed=True) | 205 triggering_source = ndb.IntegerProperty(default=None, indexed=True) |
| 168 | 206 |
| 169 # Who triggered the analysis. Used for differentiating between manual and | 207 # Who triggered the analysis. Used for differentiating between manual and |
| 170 # automatic runs, and determining the most active users to gather feedback. | 208 # automatic runs, and determining the most active users to gather feedback. |
| 171 triggering_user_email = ndb.StringProperty(default=None, indexed=False) | 209 triggering_user_email = ndb.StringProperty(default=None, indexed=False) |
| 172 | 210 |
| 173 # Overall conclusion of analysis result for the flake. Found untriaged, Found | 211 # Overall conclusion of analysis result for the flake. Found untriaged, Found |
| 174 # Correct, etc. used to filter what is displayed on the check flake dashboard. | 212 # Correct, etc. used to filter what is displayed on the check flake dashboard. |
| 175 result_status = ndb.IntegerProperty(indexed=True) | 213 result_status = ndb.IntegerProperty(indexed=True) |
| OLD | NEW |