| 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 from google.appengine.api import users | 5 from google.appengine.api import users |
| 6 from google.appengine.ext import ndb |
| 6 | 7 |
| 7 from common import auth_util | 8 from common import auth_util |
| 8 from common import time_util | 9 from common import time_util |
| 9 from common.base_handler import BaseHandler | 10 from common.base_handler import BaseHandler |
| 10 from common.base_handler import Permission | 11 from common.base_handler import Permission |
| 11 from model import analysis_status | 12 from model import analysis_status |
| 12 from model import triage_status | 13 from model import triage_status |
| 13 from model.flake.flake_analysis_request import FlakeAnalysisRequest | 14 from model.flake.flake_analysis_request import FlakeAnalysisRequest |
| 14 from model.flake.master_flake_analysis import MasterFlakeAnalysis | 15 from model.flake.master_flake_analysis import MasterFlakeAnalysis |
| 15 from waterfall.flake import flake_analysis_service | 16 from waterfall.flake import flake_analysis_service |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 | 62 |
| 62 if not test_name: | 63 if not test_name: |
| 63 return self.CreateError('Test name must be specified', 400) | 64 return self.CreateError('Test name must be specified', 400) |
| 64 | 65 |
| 65 if bug_id and not bug_id.isdigit(): | 66 if bug_id and not bug_id.isdigit(): |
| 66 return self.CreateError('Bug id (optional) must be an int', 400) | 67 return self.CreateError('Bug id (optional) must be an int', 400) |
| 67 | 68 |
| 68 return None | 69 return None |
| 69 | 70 |
| 70 def HandleGet(self): | 71 def HandleGet(self): |
| 71 master_name = self.request.get('master_name', '').strip() | 72 key = self.request.get('key') |
| 72 builder_name = self.request.get('builder_name', '').strip() | 73 if key: |
| 73 build_number = self.request.get('build_number', '').strip() | 74 analysis = ndb.Key(urlsafe=key).get() |
| 74 step_name = self.request.get('step_name', '').strip() | 75 if not analysis: # pragma: no cover |
| 75 test_name = self.request.get('test_name', '').strip() | 76 return self.CreateError('Analysis of flake is not found', 404) |
| 76 bug_id = self.request.get('bug_id', '').strip() | 77 else: |
| 77 # TODO(lijeffrey): Add support for force flag to trigger a rerun. | 78 master_name = self.request.get('master_name', '').strip() |
| 79 builder_name = self.request.get('builder_name', '').strip() |
| 80 build_number = self.request.get('build_number', '').strip() |
| 81 step_name = self.request.get('step_name', '').strip() |
| 82 test_name = self.request.get('test_name', '').strip() |
| 83 bug_id = self.request.get('bug_id', '').strip() |
| 84 # TODO(lijeffrey): Add support for force flag to trigger a rerun. |
| 78 | 85 |
| 79 error = self._ValidateInput( | 86 error = self._ValidateInput( |
| 80 master_name, builder_name, build_number, step_name, test_name, bug_id) | 87 master_name, builder_name, build_number, step_name, test_name, bug_id) |
| 81 | 88 |
| 82 if error: # pragma: no cover | 89 if error: # pragma: no cover |
| 83 return error | 90 return error |
| 84 | 91 |
| 85 build_number = int(build_number) | 92 build_number = int(build_number) |
| 86 bug_id = int(bug_id) if bug_id else None | 93 bug_id = int(bug_id) if bug_id else None |
| 87 user_email = auth_util.GetUserEmail() | 94 user_email = auth_util.GetUserEmail() |
| 88 is_admin = auth_util.IsCurrentUserAdmin() | 95 is_admin = auth_util.IsCurrentUserAdmin() |
| 89 | 96 |
| 90 request = FlakeAnalysisRequest.Create(test_name, False, bug_id) | 97 request = FlakeAnalysisRequest.Create(test_name, False, bug_id) |
| 91 request.AddBuildStep(master_name, builder_name, build_number, step_name, | 98 request.AddBuildStep(master_name, builder_name, build_number, step_name, |
| 92 time_util.GetUTCNow()) | 99 time_util.GetUTCNow()) |
| 93 scheduled = flake_analysis_service.ScheduleAnalysisForFlake( | 100 scheduled = flake_analysis_service.ScheduleAnalysisForFlake( |
| 94 request, user_email, is_admin, triggering_sources.FINDIT_UI) | 101 request, user_email, is_admin, triggering_sources.FINDIT_UI) |
| 95 | 102 |
| 96 analysis = MasterFlakeAnalysis.GetVersion( | 103 analysis = MasterFlakeAnalysis.GetVersion( |
| 97 master_name, builder_name, build_number, step_name, test_name) | 104 master_name, builder_name, build_number, step_name, test_name) |
| 98 | 105 |
| 99 if not analysis: | 106 if not analysis: |
| 100 if scheduled is None: | 107 if scheduled is None: |
| 101 # User does not have permission to trigger, nor was any previous | 108 # User does not have permission to trigger, nor was any previous |
| 102 # analysis triggered to view. | 109 # analysis triggered to view. |
| 103 return { | 110 return { |
| 104 'template': 'error.html', | 111 'template': 'error.html', |
| 105 'data': { | 112 'data': { |
| 106 'error_message': | 113 'error_message': |
| 107 ('You could schedule an analysis for flaky test only after ' | 114 ('You could schedule an analysis for flaky test only ' |
| 108 'you login with google.com account.'), | 115 'after you login with google.com account.'), |
| 109 'login_url': self.GetLoginUrl(), | 116 'login_url': self.GetLoginUrl(), |
| 110 }, | 117 }, |
| 111 'return_code': 401, | 118 'return_code': 401, |
| 112 } | 119 } |
| 113 | 120 |
| 114 # Check if a previous request has already covered this analysis so use the | 121 # Check if a previous request has already covered this analysis so use |
| 115 # results from that analysis. | 122 # the results from that analysis. |
| 116 request = FlakeAnalysisRequest.GetVersion(key=test_name) | 123 request = FlakeAnalysisRequest.GetVersion(key=test_name) |
| 117 | 124 |
| 118 if request and request.analyses: | 125 if request and request.analyses: |
| 119 analysis = request.analyses[-1].get() | 126 analysis = request.analyses[-1].get() |
| 120 else: | 127 else: |
| 121 return { | 128 return { |
| 122 'template': 'error.html', | 129 'template': 'error.html', |
| 123 'data': { | 130 'data': { |
| 124 'error_message': ( | 131 'error_message': ( |
| 125 'Flake analysis is not supported for this request. Either ' | 132 'Flake analysis is not supported for this request. Either' |
| 126 'the build step may not be supported or the test is not ' | 133 ' the build step may not be supported or the test is not ' |
| 127 'swarmed.'), | 134 'swarmed.'), |
| 128 }, | 135 }, |
| 129 'return_code': 401, | 136 'return_code': 400, |
| 130 } | 137 } |
| 131 | 138 |
| 132 suspected_flake = _GetSuspectedFlakeAnalysisAndTriageResult(analysis) | 139 suspected_flake = _GetSuspectedFlakeAnalysisAndTriageResult(analysis) |
| 133 | 140 |
| 134 data = { | 141 data = { |
| 142 'master_name': analysis.master_name, |
| 143 'builder_name': analysis.builder_name, |
| 144 'build_number': analysis.build_number, |
| 145 'step_name': analysis.step_name, |
| 146 'test_name': analysis.test_name, |
| 135 'pass_rates': [], | 147 'pass_rates': [], |
| 136 'analysis_status': analysis.status_description, | 148 'analysis_status': analysis.status_description, |
| 137 'master_name': master_name, | |
| 138 'builder_name': builder_name, | |
| 139 'build_number': build_number, | |
| 140 'step_name': step_name, | |
| 141 'test_name': test_name, | |
| 142 'version_number': analysis.version_number, | 149 'version_number': analysis.version_number, |
| 143 'suspected_flake': suspected_flake, | 150 'suspected_flake': suspected_flake, |
| 144 'request_time': time_util.FormatDatetime( | 151 'request_time': time_util.FormatDatetime( |
| 145 analysis.request_time), | 152 analysis.request_time), |
| 146 'task_number': len(analysis.data_points), | 153 'task_number': len(analysis.data_points), |
| 147 'error': analysis.error_message, | 154 'error': analysis.error_message, |
| 148 'iterations_to_rerun': analysis.iterations_to_rerun, | 155 'iterations_to_rerun': analysis.iterations_to_rerun, |
| 149 'show_debug_info': self._ShowDebugInfo() | 156 'show_debug_info': self._ShowDebugInfo() |
| 150 } | 157 } |
| 151 | 158 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 166 coordinates.append([data_point.build_number, data_point.pass_rate]) | 173 coordinates.append([data_point.build_number, data_point.pass_rate]) |
| 167 | 174 |
| 168 # Order by build number from earliest to latest. | 175 # Order by build number from earliest to latest. |
| 169 coordinates.sort(key=lambda x: x[0]) | 176 coordinates.sort(key=lambda x: x[0]) |
| 170 | 177 |
| 171 data['pass_rates'] = coordinates | 178 data['pass_rates'] = coordinates |
| 172 return { | 179 return { |
| 173 'template': 'flake/result.html', | 180 'template': 'flake/result.html', |
| 174 'data': data | 181 'data': data |
| 175 } | 182 } |
| OLD | NEW |