| OLD | NEW |
| (Empty) |
| 1 # Copyright (c) 2012 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 """A StatusReceiver module to mail someone when a step warns/fails. | |
| 6 | |
| 7 Since the behavior is very similar to the MailNotifier, we simply inherit from | |
| 8 it and also reuse some of its methods to send emails. | |
| 9 """ | |
| 10 | |
| 11 # This module comes from $(TOPLEVEL_DIR)/third_party/buildbot_<VERSION> , | |
| 12 # which must be in the PYTHONPATH. | |
| 13 from buildbot.status.mail import MailNotifier | |
| 14 from buildbot.status.results import Results | |
| 15 from master.try_mail_notifier import TryMailNotifier | |
| 16 from skia_master_scripts import utils | |
| 17 | |
| 18 import builder_name_schema | |
| 19 import datetime | |
| 20 import re | |
| 21 import urllib | |
| 22 | |
| 23 | |
| 24 _COMMIT_QUEUE_AUTHOR_LINE = 'Author: ' | |
| 25 _COMMIT_QUEUE_REVIEWERS_LINE = 'R=' | |
| 26 _COMMIT_BOT = 'commit-bot@chromium.org' | |
| 27 | |
| 28 | |
| 29 class SkiaNotifier(MailNotifier): | |
| 30 """This is Skia's status notifier.""" | |
| 31 | |
| 32 def __init__(self, **kwargs): | |
| 33 MailNotifier.__init__(self, **kwargs) | |
| 34 | |
| 35 def createEmail(self, msgdict, builderName, title, results, builds=None, | |
| 36 patches=None, logs=None): | |
| 37 # Trybots have their own Notifier | |
| 38 if builder_name_schema.IsTrybot(builderName): | |
| 39 return None | |
| 40 | |
| 41 m = MailNotifier.createEmail(self, msgdict, builderName, title, | |
| 42 results, builds, patches, logs) | |
| 43 | |
| 44 if builds and builds[0].getSourceStamp().revision: | |
| 45 m.replace_header('Subject', | |
| 46 'buildbot %(result)s in %(title)s for %(revision)s' % { | |
| 47 'result': Results[results], | |
| 48 'title': title, | |
| 49 'revision': builds[0].getSourceStamp().revision, | |
| 50 }) | |
| 51 return m | |
| 52 | |
| 53 def buildMessage(self, name, builds, results): | |
| 54 if self.sendToInterestedUsers and self.lookup: | |
| 55 | |
| 56 for build in builds: # Loop through all builds we are emailing about | |
| 57 if builder_name_schema.IsTrybot(build.getBuilder().name): | |
| 58 return | |
| 59 blame_list = set(build.getResponsibleUsers()) | |
| 60 for change in build.getChanges(): # Loop through all changes in a build | |
| 61 | |
| 62 if (change.comments and | |
| 63 _COMMIT_BOT == utils.FixGitSvnEmail(change.who)): | |
| 64 # If the change has been submitted by the commit bot then find the | |
| 65 # original author and the reviewers and add them to the blame list | |
| 66 for commit_queue_line in (_COMMIT_QUEUE_AUTHOR_LINE, | |
| 67 _COMMIT_QUEUE_REVIEWERS_LINE): | |
| 68 users = re.search( | |
| 69 '%s(.*?)\n' % commit_queue_line, | |
| 70 change.comments).group(1).split(',') | |
| 71 blame_list = blame_list.union(users) | |
| 72 if change.who in blame_list: | |
| 73 # Remove the commit bot from the blame list. | |
| 74 blame_list.remove(change.who) | |
| 75 | |
| 76 # Git-svn tacks a git-svn-id onto the email addresses. Remove it. | |
| 77 new_blamelist = [utils.FixGitSvnEmail(email) for email in blame_list] | |
| 78 | |
| 79 # pylint: disable=C0301 | |
| 80 # Set the extended blamelist. It was originally set in | |
| 81 # http://buildbot.net/buildbot/docs/0.8.4/reference/buildbot.process.bui
ld-pysrc.html | |
| 82 # (line 339) | |
| 83 build.setBlamelist(new_blamelist) | |
| 84 | |
| 85 return MailNotifier.buildMessage(self, name, builds, results) | |
| 86 | |
| 87 | |
| 88 def _ParseTimeStampFromURL(url): | |
| 89 """ Parse a timestamp from a diff-file url. | |
| 90 | |
| 91 url: string; the url from which to parse the timestamp. | |
| 92 """ | |
| 93 diff_file_name = urllib.unquote(url).split('/')[-1] | |
| 94 m = re.search('\S+\.\S+\.(\d+)-(\d+)-(\d+)\s(\d+)\.(\d+)\.(\d+)\.\d+\.diff', | |
| 95 diff_file_name) | |
| 96 | |
| 97 # If there are no matches or an incorrect number of matches, use the current | |
| 98 # date as a default. We don't include the time because that would result in | |
| 99 # many try result emails being sent with different subject lines. It is | |
| 100 # preferable to group all emails for the same changelist on the same day (even | |
| 101 # if they are from separate try requests). | |
| 102 expected_num_matches = 6 | |
| 103 if not m or len(m.groups()) != expected_num_matches: | |
| 104 now = datetime.datetime.now() | |
| 105 return '%s-%s-%s' % (now.year, now.month, now.day) | |
| 106 return '%s-%s-%s %s:%s:%s' % m.groups() | |
| 107 | |
| 108 | |
| 109 class SkiaTryMailNotifier(TryMailNotifier): | |
| 110 """ The TryMailNotifier sends mail for every build by default. Since we use | |
| 111 a single build master for both try builders and regular builders, this causes | |
| 112 mail to be sent for every single build. So, we subclass TryMailNotifier here | |
| 113 and add logic to prevent sending mail on anything but a try job. """ | |
| 114 | |
| 115 def buildMessage(self, name, build, results): | |
| 116 if builder_name_schema.IsTrybot(build[0].getBuilder().name): | |
| 117 if not hasattr(build[0].source, 'timestamp'): | |
| 118 if 'patch_file_url' in build[0].getProperties(): | |
| 119 build[0].source.timestamp = _ParseTimeStampFromURL( | |
| 120 build[0].getProperty('patch_file_url')) | |
| 121 subject = ( | |
| 122 'try %(result)s for changelist "%(reason)s" at %(timestamp)s') | |
| 123 else: | |
| 124 subject = 'try %(result)s for issue-patchset "%(reason)s"' | |
| 125 # pylint: disable=W0201 | |
| 126 self.subject = subject | |
| 127 return TryMailNotifier.buildMessage(self, name, build, results) | |
| OLD | NEW |