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