Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 """This module is to handle manual triage of a suspected CL. | |
| 6 | |
| 7 This handler will flag the suspected cl as correct or incorrect. | |
| 8 """ | |
| 9 | |
| 10 from datetime import timedelta | |
| 11 | |
| 12 from google.appengine.api import users | |
| 13 from google.appengine.ext import ndb | |
| 14 | |
| 15 from common import time_util | |
| 16 from common.base_handler import BaseHandler | |
| 17 from common.base_handler import Permission | |
| 18 from model import result_status | |
| 19 from model import suspected_cl_status | |
| 20 from model.wf_analysis import WfAnalysis | |
| 21 from model.wf_suspected_cl import WfSuspectedCL | |
| 22 from waterfall import buildbot | |
| 23 | |
| 24 | |
| 25 @ndb.transactional | |
| 26 def _UpdateSuspectedCL( | |
| 27 repo_name, revision, build_key, cl_status): | |
|
stgao
2016/09/23 19:35:41
Mind adding comments to explain how we decide the
chanli
2016/09/24 01:09:40
Done.
| |
| 28 suspected_cl = WfSuspectedCL.Get(repo_name, revision) | |
| 29 if (not suspected_cl or not suspected_cl.builds or | |
| 30 not suspected_cl.builds.get(build_key)): | |
| 31 return False | |
| 32 | |
| 33 suspected_cl.builds[build_key]['status'] = cl_status | |
| 34 | |
| 35 cl_correct = True | |
| 36 cl_incorrect = True | |
| 37 partial_triaged = False | |
| 38 for build in suspected_cl.builds.values(): | |
| 39 if build['status'] is None: | |
| 40 partial_triaged = True | |
| 41 elif build['status'] == suspected_cl_status.CORRECT: | |
| 42 cl_incorrect = False | |
| 43 else: | |
| 44 cl_correct = False | |
| 45 | |
| 46 if partial_triaged: | |
| 47 suspected_cl.status = suspected_cl_status.PARTIALLY_TRIAGED | |
| 48 elif cl_correct: | |
| 49 suspected_cl.status = suspected_cl_status.CORRECT | |
| 50 elif cl_incorrect: | |
| 51 suspected_cl.status = suspected_cl_status.INCORRECT | |
| 52 else: | |
| 53 suspected_cl.status = suspected_cl_status.PARTIALLY_CORRECT | |
| 54 | |
| 55 suspected_cl.put() | |
| 56 return True | |
| 57 | |
| 58 | |
| 59 @ndb.transactional | |
| 60 def _UpdateAnalysis( | |
| 61 master_name, builder_name, build_number, repo_name, revision, cl_status): | |
| 62 analysis = WfAnalysis.Get(master_name, builder_name, build_number) | |
| 63 if not analysis or not analysis.suspected_cls: | |
| 64 return False | |
| 65 | |
| 66 num_correct = 0 | |
| 67 num_incorrect = 0 | |
| 68 for cl in analysis.suspected_cls: | |
| 69 if cl['repo_name'] == repo_name and cl['revision'] == revision: | |
| 70 # Updates this cl's status. | |
| 71 cl['status'] = cl_status | |
| 72 | |
| 73 # Checks if all the cls have been triaged. | |
| 74 if cl.get('status') == suspected_cl_status.CORRECT: | |
| 75 num_correct += 1 | |
| 76 elif cl.get('status') == suspected_cl_status.INCORRECT: | |
| 77 num_incorrect += 1 | |
| 78 | |
| 79 if num_correct + num_incorrect == len(analysis.suspected_cls): # All triaged. | |
| 80 if num_correct == 0: | |
| 81 analysis.result_status = result_status.FOUND_INCORRECT | |
| 82 elif num_incorrect == 0: | |
| 83 analysis.result_status = result_status.FOUND_CORRECT | |
| 84 else: | |
| 85 analysis.result_status = result_status.PARTIALLY_CORRECT_FOUND | |
| 86 | |
| 87 analysis.put() | |
| 88 return True | |
| 89 | |
| 90 | |
| 91 def _AppendTriageHistoryRecord( | |
| 92 master_name, builder_name, build_number, cl_info, cl_status, user_name): | |
| 93 | |
| 94 analysis = WfAnalysis.Get(master_name, builder_name, build_number) | |
| 95 if not analysis: # pragma: no cover | |
| 96 return | |
| 97 | |
| 98 triage_record = { | |
| 99 'triage_timestamp': time_util.GetUTCNowTimestamp(), | |
| 100 'user_name': user_name, | |
| 101 'cl_status': cl_status, | |
| 102 'version': analysis.version, | |
| 103 'triaged_cl': cl_info | |
| 104 } | |
| 105 if not analysis.triage_history: | |
| 106 analysis.triage_history = [] | |
| 107 analysis.triage_history.append(triage_record) | |
| 108 | |
| 109 analysis.put() | |
| 110 | |
| 111 | |
| 112 def _UpdateSuspectedCLAndAnalysis( | |
| 113 master_name, builder_name, build_number, cl_info, cl_status, user_name): | |
| 114 cl_keys = cl_info.split('/') | |
|
stgao
2016/09/23 19:35:41
Ditto.
chanli
2016/09/24 01:09:40
Done.
| |
| 115 repo_name = cl_keys[0] | |
| 116 revision = cl_keys[1] | |
| 117 build_key = '%s/%s/%d' % (master_name, builder_name, build_number) | |
|
stgao
2016/09/23 19:35:41
Ditto.
chanli
2016/09/24 01:09:40
Done.
| |
| 118 | |
| 119 success = ( | |
| 120 _UpdateSuspectedCL(repo_name, revision, build_key, cl_status) and | |
| 121 _UpdateAnalysis(master_name, builder_name, build_number, | |
| 122 repo_name, revision, cl_status)) | |
| 123 | |
| 124 if success: | |
| 125 _AppendTriageHistoryRecord( | |
| 126 master_name, builder_name, build_number, cl_info, cl_status, user_name) | |
| 127 | |
| 128 return success | |
| 129 | |
| 130 | |
| 131 class TriageSuspectedCl(BaseHandler): | |
| 132 PERMISSION_LEVEL = Permission.CORP_USER | |
| 133 | |
| 134 def HandleGet(self): # pragma: no cover | |
| 135 """Sets the manual triage result for the cl.""" | |
| 136 url = self.request.get('url').strip() | |
| 137 build_info = buildbot.ParseBuildUrl(url) | |
| 138 if not build_info: | |
| 139 return {'data': {'success': False}} | |
| 140 master_name, builder_name, build_number = build_info | |
| 141 | |
| 142 cl_status = int(self.request.get('status')) | |
| 143 cl_info = self.request.get('cl_info') | |
| 144 # As the permission level is CORP_USER, we could assume the current user | |
| 145 # already logged in. | |
| 146 user_name = users.get_current_user().email().split('@')[0] | |
| 147 success = _UpdateSuspectedCLAndAnalysis( | |
| 148 master_name, builder_name, build_number, cl_info, cl_status, user_name) | |
| 149 | |
| 150 return {'data': {'success': success}} | |
| 151 | |
| 152 | |
| 153 def HandlePost(self): # pragma: no cover | |
| 154 return self.HandleGet() | |
| OLD | NEW |