don't send emails about samba_3_waf builds yet
[amitay/build-farm.git] / import-and-analyse.py
1 #!/usr/bin/python
2 # Write sqlite entries for test reports in the build farm
3 # Copyright (C) 2007-2010 Jelmer Vernooij <jelmer@samba.org>
4 # Copyright (C) 2007-2010 Andrew Bartlett <abartlet@samba.org>
5 # Published under the GNU GPL
6
7 """Script to parse build farm log files from the data directory, import
8 them into the database, add links to the oldrevs/ directory and send
9 some mail chastising the possible culprits when the build fails, based
10 on recent commits.
11 """
12
13 from buildfarm.build import (
14     BuildDiff,
15     MissingRevisionInfo,
16     NoSuchBuildError,
17     )
18 from buildfarm import BuildFarm
19 from buildfarm.web import build_uri
20 from email.mime.text import MIMEText
21 import optparse
22 import resource
23 import smtplib
24
25 parser = optparse.OptionParser("import-and-analyse [options]")
26 parser.add_option("--dry-run", help="Will cause the script to send output to stdout instead of to sendmail.", action="store_true")
27 parser.add_option("--verbose", help="Be verbose", action="count")
28
29 (opts, args) = parser.parse_args()
30
31 resource.setrlimit(resource.RLIMIT_RSS, (300000, 300000))
32 resource.setrlimit(resource.RLIMIT_DATA, (300000, 300000))
33
34 buildfarm = BuildFarm(timeout=40.0)
35
36 smtp = smtplib.SMTP()
37 smtp.connect()
38
39 def check_and_send_mails(cur, old):
40
41     if cur.tree is "waf-svn":
42         # no point sending emails, as the email addresses are invalid
43         # from git svn
44         return
45
46     if cur.tree is "samba_3_waf":
47         # no emails for this until it stabilises a bit
48         return
49
50     t = buildfarm.trees[cur.tree]
51     diff = BuildDiff(t, old, cur)
52
53     if not diff.is_regression():
54         if opts.verbose >= 3:
55             print "... hasn't regressed since %s: %s" % (diff.old_rev, diff.old_status)
56         return
57
58     recipients = set()
59     change_log = ""
60
61     for rev in diff.revisions():
62         recipients.add(rev.author)
63         recipients.add(rev.committer)
64         change_log += """
65 revision: %s
66 author: %s
67 committer: %s
68 message:
69     %s
70 """ % (rev.revision, rev.author, rev.committer, rev.message)
71
72     body = """
73 Broken build for tree %(tree)s on host %(host)s with compiler %(compiler)s
74
75 Tree %(tree)s is %(scm)s branch %(branch)s.
76
77 Build status for new revision %(cur_rev)s is %(cur_status)s
78 Build status for old revision %(old_rev)s was %(old_status)s
79
80 See %(build_link)s
81
82 The build may have been broken by one of the following commits:
83
84 %(change_log)s
85     """ % {
86         "tree": cur.tree, "host": cur.host, "compiler": cur.compiler,
87         "change_log": change_log,
88         "scm": t.scm,
89         "branch": t.branch,
90         "cur_rev": diff.new_rev,
91         "old_rev": diff.old_rev,
92         "cur_status": diff.new_status,
93         "old_status": diff.old_status,
94         "build_link": build_uri("http://build.samba.org/build.cgi", cur)
95         }
96
97     msg = MIMEText(body)
98     msg["Subject"] = "BUILD of %s:%s BROKEN on %s with %s AT REVISION %s" % (cur.tree, t.branch, cur.host, cur.compiler, diff.new_rev)
99     msg["From"] = "\"Build Farm\" <build@samba.org>"
100     msg["To"] = ",".join(recipients)
101     if not opts.dry_run:
102         smtp.sendmail(msg["From"], [msg["To"]], msg.as_string())
103     else:
104         print msg.as_string()
105
106
107 for build in buildfarm.get_new_builds():
108     if build in buildfarm.builds:
109         continue
110
111     if not opts.dry_run:
112         old_build = build
113         try:
114             build = buildfarm.builds.upload_build(old_build)
115         except MissingRevisionInfo:
116             print "No revision info in %r, skipping" % build
117             continue
118
119     try:
120         rev = build.revision_details()
121     except MissingRevisionInfo:
122         print "No revision info in %r, skipping" % build
123         continue
124
125     if opts.verbose >= 2:
126         print "%s... " % build,
127         print str(build.status())
128
129     try:
130         if opts.dry_run:
131             # Perhaps this is a dry run and rev is not in the database yet?
132             prev_build = buildfarm.builds.get_latest_build(build.tree, build.host, build.compiler)
133         else:
134             prev_build = buildfarm.builds.get_previous_build(build.tree, build.host, build.compiler, rev)
135     except NoSuchBuildError:
136         if opts.verbose >= 1:
137             print "Unable to find previous build for %s,%s,%s" % (build.tree, build.host, build.compiler)
138         # Can't send a nastygram until there are 2 builds..
139     else:
140         check_and_send_mails(build, prev_build)
141
142     if not opts.dry_run:
143         old_build.remove()
144         buildfarm.commit()
145
146 smtp.quit()