3 A script for reporting the results of an invirtibuild. Supports any
4 combination of the following reporting mechanisms.
6 Note that all strings are interpolated with a dictionary containing
9 build_id, commit, failed_stage, inserted_at, package,
10 pocket, principal, result, short_commit, traceback, version
14 To configure zephyr, add something like the following to your invirt config:
19 zephyr: &post_build_zepyhr
20 class: myclass [required]
21 instance: myinstance [optional]
22 zsig: myzsig [optional]
24 zephyr: *post_build_zephyr
28 To configure email notifications, add something like the following to your invirt config:
33 mail: &post_build_mail
34 to: myemail@example.com [required]
35 from: myemail@example.com [required]
36 subject: My Subject [optional]
38 mail: *post_build_mail
40 post_build values will be used when this script is invoked as
41 post-build, while failed_build values will be used when it is invoked
51 from email.mime import text
53 from invirt import common, database, builder
54 from invirt.config import structs as config
56 def make_msg(build, values, verbose=True, success=lambda x: x, failure=lambda x: x):
58 if not verbose and values['traceback'] is not None:
59 # TODO: better heuristic
60 values['traceback'] = textwrap.fill('\n'.join(values['traceback'].split('\n')[-2:]))
63 values['result'] = success(values['result'])
64 msg = """Build of %(package)s %(version)s in %(pocket)s %(result)s.
66 Branch %(pocket)s has been advanced to %(short_commit)s.
68 (Build %(build_id)s was submitted by %(principal)s at %(inserted_at)s.)""" % values
70 values['result'] = failure(values['result'])
71 msg = """Build of %(package)s %(version)s in %(pocket)s %(result)s while %(failed_stage)s.
75 (Build %(build_id)s was submitted by %(principal)s at %(inserted_at)s.)""" % values
79 m = re.sub('@', '@@', m)
80 m = re.sub('}', '@(})', m)
83 def zephyr_success(m):
84 return '}@{@color(green)%s}@{' % zephyr_escape(m)
86 def zephyr_failure(m):
87 return '}@{@color(red)%s}@{' % zephyr_escape(m)
90 parser = optparse.OptionParser('Usage: %prog build_id')
91 opts, args = parser.parse_args()
95 prog = os.path.basename(sys.argv[0])
98 build = database.Build.query().get(args[0])
99 short_commit = builder.canonicalize_commit(build.package, build.commit, shorten=True)
100 values = { 'build_id' : build.build_id,
101 'commit' : build.commit,
102 'failed_stage' : build.failed_stage,
103 'inserted_at' : build.inserted_at,
104 'package' : build.package,
105 'pocket' : build.pocket,
106 'principal' : build.principal,
107 'short_commit' : short_commit,
108 'traceback' : build.traceback,
109 'version' : build.version }
111 values['result'] = 'succeeded'
113 values['result'] = 'failed'
116 if prog == 'post-build':
117 hook_config = config.build.hooks.post_build
118 elif prog == 'failed-build':
119 hook_config = config.build.hooks.failed_build
121 print >>sys.stderr, '{post,failed}-build invoke with unrecognized name %s' % prog
123 except common.InvirtConfigError:
124 print >>sys.stderr, 'No hook configuration found for %s.' % prog
128 zephyr_config = hook_config.zephyr
129 klass = zephyr_config['class'] % values
130 except common.InvirtConfigError:
131 print >>sys.stderr, 'No zephyr configuration specified for %s.' % prog
133 msg = '@{%s}' % make_msg(build, values, verbose=False,
134 success=zephyr_success, failure=zephyr_failure)
135 instance = zephyr_config.get('instance', 'build_%(build_id)s') % values
136 zsig = zephyr_config.get('zsig', 'XVM Buildbot') % values
137 common.captureOutput(['zwrite', '-c', klass, '-i', instance, '-s',
138 zsig, '-d', '-m', msg],
139 stdout=None, stderr=None)
142 mail_config = hook_config.mail
143 to = mail_config.to % values
144 sender = mail_config['from'] % values
145 except common.InvirtConfigError:
146 print >>sys.stderr, 'No email configuration specified for %s.' % prog
148 msg = make_msg(build, values)
149 email = text.MIMEText(msg)
150 email['To'] = to % values
151 email['From'] = sender % values
152 email['Subject'] = mail_config.get('subject', 'XVM build %(result)s: %(package)s %(version)s in %(pocket)s') % values
153 common.captureOutput(['sendmail', '-t'], email.as_string(),
154 stdout=None, stderr=None)
156 if __name__ == '__main__':