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 |