Fix formatting.
[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 data
14 from buildfarm.sqldb import StormCachingBuildFarm
15 from email.mime.text import MIMEText
16 import logging
17 import optparse
18 import smtplib
19
20 parser = optparse.OptionParser("import-and-analyse [options]")
21 parser.add_option("--dry-run", help="Will cause the script to send output to stdout instead of to sendmail.", action="store_true")
22 parser.add_option("--verbose", help="Be verbose", action="count")
23
24 (opts, args) = parser.parse_args()
25
26 buildfarm = StormCachingBuildFarm()
27
28 smtp = smtplib.SMTP()
29 smtp.connect()
30
31 def check_and_send_mails(tree, host, compiler, cur, old):
32     t = buildfarm.trees[tree]
33
34     (cur_rev, cur_rev_timestamp) = cur.revision_details()
35     cur_status = cur.status()
36
37     (old_rev, old_rev_timestamp) = old.revision_details()
38     old_status = old.status()
39
40     if not cur_status.regressed_since(old_status):
41         if opts.verbose >= 3:
42             print "... hasn't regressed since %s: %s" % (old_rev, old_status)
43         return
44
45     recipients = set()
46     change_log = ""
47
48     for rev in t.get_branch().log(from_rev=cur.rev, exclude_revs=set([old.rev])):
49         recipients.add(rev.author)
50         recipients.add(rev.committer)
51         change_log += """
52 revision: %s
53 author: %s
54 committer: %s
55 message:
56     %s
57 """ % (rev.revision, rev.author, rev.committer, rev.message)
58
59     body = """
60 Broken build for tree %(tree)s on host %(host)s with compiler %(compiler)s
61
62 Tree %(tree)s is %(scm)s branch %(branch)s.
63
64 Build status for new revision %(cur_rev)s is %(cur_status)s
65 Build status for old revision %(old_rev)s was %(old_status)s
66
67 See http://build.samba.org/?function=View+Build;host=%(host)s;tree=%(tree)s;compiler=%(compiler)s
68
69 The build may have been broken by one of the following commits:
70
71 %(change_log)s
72     """ % {"tree": tree, "host": host, "compiler": compiler, "change_log": change_log, "scm": t.scm, "branch": t.branch,
73             "cur_rev": cur_rev, "old_rev": old_rev, "cur_status": cur_status, "old_status": old_status }
74
75     msg = MIMEText(body)
76     msg["Subject"] = "BUILD of %s:%s BROKEN on %s with %s AT REVISION %s" % (tree, t.branch, host, compiler, cur_rev)
77     msg["From"] = "\"Build Farm\" <build@samba.org>"
78     msg["To"] = ",".join(recipients.keys())
79     if not opts.dry_run:
80         smtp.send(msg["From"], [msg["To"]], msg.as_string())
81     else:
82         print msg.as_string()
83
84
85 for build in buildfarm.get_new_builds():
86     if build in buildfarm.builds:
87         continue
88
89     if not opts.dry_run:
90         try:
91             build = buildfarm.builds.upload_build(build)
92         except data.MissingRevisionInfo:
93             print "No revision info in %r, skipping" % build
94             continue
95
96     try:
97         (rev, rev_timestamp) = build.revision_details()
98     except data.MissingRevisionInfo:
99         print "No revision info in %r, skipping" % build
100         continue
101
102     if opts.verbose >= 2:
103         print "%s... " % build,
104         print str(build.status())
105
106     try:
107         if opts.dry_run:
108             # Perhaps this is a dry run and rev is not in the database yet?
109             prev_rev = buildfarm.builds.get_latest_revision(build.tree, build.host, build.compiler)
110         else:
111             prev_rev = buildfarm.builds.get_previous_revision(build.tree, build.host, build.compiler, rev)
112     except data.NoSuchBuildError:
113         if opts.verbose >= 1:
114             print "Unable to find previous build for %s,%s,%s" % (build.tree, build.host, build.compiler)
115         # Can't send a nastygram until there are 2 builds..
116     else:
117         try:
118             prev_build = buildfarm.get_build(build.tree, build.host, build.compiler, prev_rev)
119         except data.NoSuchBuildError:
120             if opts.verbose >= 1:
121                 print "Previous build %s has disappeared" % prev_build
122         else:
123             check_and_send_mails(build.tree, build.host, build.compiler, build, prev_build)
124
125     if not opts.dry_run:
126         # When the new web script is introduced, kill the build here:
127         # build.remove()
128         buildfarm.commit()
129
130 smtp.quit()