| 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 from datetime import datetime |
| 6 import logging |
| 7 import textwrap |
| 8 |
| 9 from google.appengine.ext import ndb |
| 10 |
| 11 from common.git_repository import GitRepository |
| 12 from common.http_client_appengine import HttpClientAppengine as HttpClient |
| 13 from common.pipeline_wrapper import BasePipeline |
| 14 from common.rietveld import Rietveld |
| 15 from model import analysis_status as status |
| 16 from model.wf_culprit import WfCulprit |
| 17 |
| 18 |
| 19 @ndb.transactional |
| 20 def _ShouldSendNotification( |
| 21 master_name, builder_name, build_number, repo_name, revision): |
| 22 """Returns True if a notification for the culprit should be sent.""" |
| 23 culprit = (WfCulprit.Get(repo_name, revision) or |
| 24 WfCulprit.Create(repo_name, revision)) |
| 25 if [master_name, builder_name, build_number] in culprit.builds: |
| 26 return False |
| 27 |
| 28 culprit.builds.append([master_name, builder_name, build_number]) |
| 29 # Send notification when the culprit is for 2+ failures in two different |
| 30 # builds to avoid false positive due to flakiness. |
| 31 # TODO(stgao): move to config. |
| 32 should_send = not (culprit.cr_notification_processed or |
| 33 len(culprit.builds) < 2) |
| 34 if should_send: |
| 35 culprit.cr_notification_status = status.RUNNING |
| 36 culprit.put() |
| 37 return should_send |
| 38 |
| 39 |
| 40 @ndb.transactional |
| 41 def _UpdateNotificationStatus(repo_name, revision, new_status): |
| 42 culprit = WfCulprit.Get(repo_name, revision) |
| 43 culprit.cr_notification_status = new_status |
| 44 if culprit.cr_notified: |
| 45 culprit.cr_notification_time = datetime.utcnow() |
| 46 culprit.put() |
| 47 |
| 48 |
| 49 def _SendNotificationForCulprit(repo_name, revision): |
| 50 # TODO(stgao): get repo url at runtime based on the given repo name. |
| 51 repo = GitRepository( |
| 52 'https://chromium.googlesource.com/chromium/src.git', HttpClient()) |
| 53 change_log = repo.GetChangeLog(revision) |
| 54 sent = False |
| 55 if change_log.code_review_url: |
| 56 # Occasionally, a commit was not uploaded for code-review. |
| 57 culprit = WfCulprit.Get(repo_name, revision) |
| 58 rietveld = Rietveld() |
| 59 message = textwrap.dedent(""" |
| 60 Findit Try-job identified this CL (revision %s) as the culprit for failures |
| 61 in the build cycle(s) as shown on: |
| 62 https://findit-for-me.appspot.com/waterfall/culprit?key=%s |
| 63 """) % (revision, culprit.key.urlsafe()) |
| 64 sent = rietveld.PostMessage(change_log.code_review_url, message) |
| 65 else: |
| 66 logging.error('Can not get code-review url for %s/%s', repo_name, revision) |
| 67 |
| 68 _UpdateNotificationStatus(repo_name, revision, |
| 69 status.COMPLETED if sent else status.ERROR) |
| 70 return sent |
| 71 |
| 72 |
| 73 class SendNotificationForCulpritPipeline(BasePipeline): |
| 74 |
| 75 # Arguments number differs from overridden method - pylint: disable=W0221 |
| 76 def run(self, master_name, builder_name, build_number, repo_name, revision): |
| 77 if not _ShouldSendNotification( |
| 78 master_name, builder_name, build_number, repo_name, revision): |
| 79 return False |
| 80 return _SendNotificationForCulprit(repo_name, revision) |
| OLD | NEW |