Chromium Code Reviews| Index: appengine/findit/handlers/triage_suspected_cl.py |
| diff --git a/appengine/findit/handlers/triage_suspected_cl.py b/appengine/findit/handlers/triage_suspected_cl.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..e08da4d73f292d286a320db742f8a370aab9b1fb |
| --- /dev/null |
| +++ b/appengine/findit/handlers/triage_suspected_cl.py |
| @@ -0,0 +1,154 @@ |
| +# Copyright 2016 The Chromium Authors. All rights reserved. |
| +# Use of this source code is governed by a BSD-style license that can be |
| +# found in the LICENSE file. |
| + |
| +"""This module is to handle manual triage of a suspected CL. |
| + |
| +This handler will flag the suspected cl as correct or incorrect. |
| +""" |
| + |
| +from datetime import timedelta |
| + |
| +from google.appengine.api import users |
| +from google.appengine.ext import ndb |
| + |
| +from common import time_util |
| +from common.base_handler import BaseHandler |
| +from common.base_handler import Permission |
| +from model import result_status |
| +from model import suspected_cl_status |
| +from model.wf_analysis import WfAnalysis |
| +from model.wf_suspected_cl import WfSuspectedCL |
| +from waterfall import buildbot |
| + |
| + |
| +@ndb.transactional |
| +def _UpdateSuspectedCL( |
|
lijeffrey
2016/09/23 05:09:09
nit: looks like this fits on 1 line?
chanli
2016/09/24 01:09:40
Done.
|
| + repo_name, revision, build_key, cl_status): |
| + suspected_cl = WfSuspectedCL.Get(repo_name, revision) |
| + if (not suspected_cl or not suspected_cl.builds or |
| + not suspected_cl.builds.get(build_key)): |
| + return False |
| + |
| + suspected_cl.builds[build_key]['status'] = cl_status |
| + |
| + cl_correct = True |
| + cl_incorrect = True |
| + partial_triaged = False |
| + for build in suspected_cl.builds.values(): |
| + if build['status'] is None: |
| + partial_triaged = True |
| + elif build['status'] == suspected_cl_status.CORRECT: |
| + cl_incorrect = False |
| + else: |
| + cl_correct = False |
| + |
| + if partial_triaged: |
| + suspected_cl.status = suspected_cl_status.PARTIALLY_TRIAGED |
| + elif cl_correct: |
| + suspected_cl.status = suspected_cl_status.CORRECT |
| + elif cl_incorrect: |
| + suspected_cl.status = suspected_cl_status.INCORRECT |
| + else: |
| + suspected_cl.status = suspected_cl_status.PARTIALLY_CORRECT |
| + |
| + suspected_cl.put() |
| + return True |
| + |
| + |
| +@ndb.transactional |
| +def _UpdateAnalysis( |
| + master_name, builder_name, build_number, repo_name, revision, cl_status): |
| + analysis = WfAnalysis.Get(master_name, builder_name, build_number) |
| + if not analysis or not analysis.suspected_cls: |
| + return False |
| + |
| + num_correct = 0 |
| + num_incorrect = 0 |
| + for cl in analysis.suspected_cls: |
| + if cl['repo_name'] == repo_name and cl['revision'] == revision: |
| + # Updates this cl's status. |
| + cl['status'] = cl_status |
| + |
| + # Checks if all the cls have been triaged. |
| + if cl.get('status') == suspected_cl_status.CORRECT: |
| + num_correct += 1 |
| + elif cl.get('status') == suspected_cl_status.INCORRECT: |
| + num_incorrect += 1 |
| + |
| + if num_correct + num_incorrect == len(analysis.suspected_cls): # All triaged. |
| + if num_correct == 0: |
| + analysis.result_status = result_status.FOUND_INCORRECT |
| + elif num_incorrect == 0: |
| + analysis.result_status = result_status.FOUND_CORRECT |
| + else: |
| + analysis.result_status = result_status.PARTIALLY_CORRECT_FOUND |
| + |
| + analysis.put() |
| + return True |
| + |
| + |
| +def _AppendTriageHistoryRecord( |
| + master_name, builder_name, build_number, cl_info, cl_status, user_name): |
| + |
| + analysis = WfAnalysis.Get(master_name, builder_name, build_number) |
| + if not analysis: # pragma: no cover |
| + return |
| + |
| + triage_record = { |
| + 'triage_timestamp': time_util.GetUTCNowTimestamp(), |
| + 'user_name': user_name, |
| + 'cl_status': cl_status, |
| + 'version': analysis.version, |
| + 'triaged_cl': cl_info |
| + } |
| + if not analysis.triage_history: |
| + analysis.triage_history = [] |
| + analysis.triage_history.append(triage_record) |
| + |
| + analysis.put() |
| + |
| + |
| +def _UpdateSuspectedCLAndAnalysis( |
| + master_name, builder_name, build_number, cl_info, cl_status, user_name): |
| + cl_keys = cl_info.split('/') |
| + repo_name = cl_keys[0] |
| + revision = cl_keys[1] |
| + build_key = '%s/%s/%d' % (master_name, builder_name, build_number) |
| + |
| + success = ( |
| + _UpdateSuspectedCL(repo_name, revision, build_key, cl_status) and |
| + _UpdateAnalysis(master_name, builder_name, build_number, |
| + repo_name, revision, cl_status)) |
| + |
| + if success: |
| + _AppendTriageHistoryRecord( |
| + master_name, builder_name, build_number, cl_info, cl_status, user_name) |
| + |
| + return success |
| + |
| + |
| +class TriageSuspectedCl(BaseHandler): |
| + PERMISSION_LEVEL = Permission.CORP_USER |
| + |
| + def HandleGet(self): # pragma: no cover |
| + """Sets the manual triage result for the cl.""" |
| + url = self.request.get('url').strip() |
| + build_info = buildbot.ParseBuildUrl(url) |
| + if not build_info: |
| + return {'data': {'success': False}} |
| + master_name, builder_name, build_number = build_info |
| + |
| + cl_status = int(self.request.get('status')) |
| + cl_info = self.request.get('cl_info') |
| + # As the permission level is CORP_USER, we could assume the current user |
| + # already logged in. |
| + user_name = users.get_current_user().email().split('@')[0] |
| + success = _UpdateSuspectedCLAndAnalysis( |
| + master_name, builder_name, build_number, cl_info, cl_status, user_name) |
| + |
| + return {'data': {'success': success}} |
| + |
| + |
| + def HandlePost(self): # pragma: no cover |
| + return self.HandleGet() |