Support removing builds.
[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 import (
14     BuildFarm,
15     hostdb,
16     )
17 from email.mime.text import MIMEText
18 import logging
19 import optparse
20 import smtplib
21
22 parser = optparse.OptionParser("import-and-analyse [options]")
23 parser.add_option("--dry-run", help="Will cause the script to send output to stdout instead of to sendmail.", action="store_true")
24 parser.add_option("--verbose", help="Be verbose", action="count")
25
26 (opts, args) = parser.parse_args()
27
28 # we open readonly here as only apache(www-run) has write access
29 buildfarm = BuildFarm()
30
31 smtp = smtplib.SMTP()
32 smtp.connect()
33
34 def check_and_send_mails(tree, host, compiler, cur, old):
35     t = buildfarm.trees[tree]
36
37     (cur_rev, cur_rev_timestamp) = cur.revision_details()
38     cur_status = cur.status()
39
40     (old_rev, old_rev_timestamp) = old.revision_details()
41     old_status = old.status()
42
43     if opts.dry_run:
44         print "rev=%s status=%s" % (cur_rev, cur_status)
45         print "old rev=%s status=%s" % (old_rev, old_status)
46
47     if not cur_status.regressed_since(old_status):
48         if opts.dry_run:
49             print "the build didn't get worse since %r" % old_status
50         return
51
52     recipients = set()
53     change_log = ""
54
55     for rev in t.get_branch().log(from_rev=cur.rev, exclude_revs=set([old.rev])):
56         recipients.add(rev.author)
57         recipients.add(rev.committer)
58         change_log += """
59 revision: %s
60 author: %s
61 committer: %s
62 message:
63     %s
64 """ % (rev.revision, rev.author, rev.committer, rev.message)
65
66     body = """
67 Broken build for tree %(tree)s on host %(host)s with compiler %(compiler)s
68
69 Tree %(tree)s is %(scm)s branch %(branch)s.
70
71 Build status for new revision %(cur_rev)s is %(cur_status)s
72 Build status for old revision %(old_rev)s was %(old_status)s
73
74 See http://build.samba.org/?function=View+Build;host=%(host)s;tree=%(tree)s;compiler=%(compiler)s
75
76 The build may have been broken by one of the following commits:
77
78 %(change_log)s
79     """ % {"tree": tree, "host": host, "compiler": compiler, "change_log": change_log, "scm": t.scm, "branch": t.branch,
80             "cur_rev": cur_rev, "old_rev": old_rev, "cur_status": cur_status, "old_status": old_status }
81
82     msg = MIMEText(body)
83     msg["Subject"] = "BUILD of %s:%s BROKEN on %s with %s AT REVISION %s" % (tree, t.branch, host, compiler, cur_rev)
84     msg["From"] = "\"Build Farm\" <build@samba.org>"
85     msg["To"] = ",".join(recipients.keys())
86     smtp.send(msg["From"], [msg["To"]], msg.as_string())
87
88
89 for build in buildfarm.get_new_builds():
90     if opts.verbose >= 2:
91         print "Processing %s..." % build
92
93     buildfarm.builds.upload_build(build)
94
95     (rev, commit_rev, rev_timestamp) = build.revision_details()
96
97     try:
98         prev_rev = buildfarm.builds.get_previous_revision(build.tree, build.host, build.compiler, rev)
99     except hostdb.NoSuchBuild:
100         # Can't send a nastygram until there are 2 builds..
101         continue
102     else:
103         prev_build = buildfarm.get_build(build.tree, build.host, build.compiler, prev_rev)
104         check_and_send_mails(build.tree, build.host, build.compiler, build, prev_build)
105
106     build.remove()
107
108 smtp.quit()