summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2011-09-16 10:55:17 +0400
committerRichard Purdie <richard.purdie@linuxfoundation.org>2011-09-16 18:07:26 +0100
commit6be481711aa0a3782522fdd6de2e1ec52f4deed5 (patch)
treee68583d28b475e3fd9a93bd812fdc7d30bc30bdf
parent849bf66e2871d227d1028ead60d7bc76bdf7aadb (diff)
downloadpoky-6be481711aa0a3782522fdd6de2e1ec52f4deed5.tar.gz
bugzilla.bbclass: add a class to report build problems to bugzilla
Add a class to report build errors to bugzilla. Idea largely based on sepukku.bbclass, however it's rewritten nearly fully to use XML-RPC interface of bugzilla. Tested with bugzilla 4.0, other version might require some sort of adaptation. (From OE-Core rev: 20529035a4c0befb3c6bdbcb289a2de930fb143d) Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/classes/bugzilla.bbclass186
1 files changed, 186 insertions, 0 deletions
diff --git a/meta/classes/bugzilla.bbclass b/meta/classes/bugzilla.bbclass
new file mode 100644
index 0000000000..801bd66d2f
--- /dev/null
+++ b/meta/classes/bugzilla.bbclass
@@ -0,0 +1,186 @@
1#
2# Small event handler to automatically open URLs and file
3# bug reports at a bugzilla of your choiche
4# it uses XML-RPC interface, so you must have it enabled
5#
6# Before using you must define BUGZILLA_USER, BUGZILLA_PASS credentials,
7# BUGZILLA_XMLRPC - uri of xmlrpc.cgi,
8# BUGZILLA_PRODUCT, BUGZILLA_COMPONENT - a place in BTS for build bugs
9# BUGZILLA_VERSION - version against which to report new bugs
10#
11
12def bugzilla_find_bug_report(debug_file, server, args, bugname):
13 args['summary'] = bugname
14 bugs = server.Bug.search(args)
15 if len(bugs['bugs']) == 0:
16 print >> debug_file, "Bugs not found"
17 return (False,None)
18 else: # silently pick the first result
19 print >> debug_file, "Result of bug search is "
20 print >> debug_file, bugs
21 status = bugs['bugs'][0]['status']
22 id = bugs['bugs'][0]['id']
23 return (not status in ["CLOSED", "RESOLVED", "VERIFIED"],id)
24
25def bugzilla_file_bug(debug_file, server, args, name, text, version):
26 args['summary'] = name
27 args['comment'] = text
28 args['version'] = version
29 args['op_sys'] = 'Linux'
30 args['platform'] = 'Other'
31 args['severity'] = 'normal'
32 args['priority'] = 'Normal'
33 try:
34 return server.Bug.create(args)['id']
35 except Exception, e:
36 print >> debug_file, repr(e)
37 return None
38
39def bugzilla_reopen_bug(debug_file, server, args, bug_number):
40 args['ids'] = [bug_number]
41 args['status'] = "CONFIRMED"
42 try:
43 server.Bug.update(args)
44 return True
45 except Exception, e:
46 print >> debug_file, repr(e)
47 return False
48
49def bugzilla_create_attachment(debug_file, server, args, bug_number, text, file_name, log, logdescription):
50 args['ids'] = [bug_number]
51 args['file_name'] = file_name
52 args['summary'] = logdescription
53 args['content_type'] = "text/plain"
54 args['data'] = log
55 args['comment'] = text
56 try:
57 server.Bug.add_attachment(args)
58 return True
59 except Exception, e:
60 print >> debug_file, repr(e)
61 return False
62
63def bugzilla_add_comment(debug_file, server, args, bug_number, text):
64 args['id'] = bug_number
65 args['comment'] = text
66 try:
67 server.Bug.add_comment(args)
68 return True
69 except Exception, e:
70 print >> debug_file, repr(e)
71 return False
72
73addhandler bugzilla_eventhandler
74python bugzilla_eventhandler() {
75 import bb, os, glob
76 import xmlrpclib, httplib
77
78 class ProxiedTransport(xmlrpclib.Transport):
79 def __init__(self, proxy, use_datetime = 0):
80 xmlrpclib.Transport.__init__(self, use_datetime)
81 self.proxy = proxy
82 self.user = None
83 self.password = None
84
85 def set_user(self, user):
86 self.user = user
87
88 def set_password(self, password):
89 self.password = password
90
91 def make_connection(self, host):
92 self.realhost = host
93 return httplib.HTTP(self.proxy)
94
95 def send_request(self, connection, handler, request_body):
96 connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler))
97 if self.user != None:
98 if self.password != None:
99 auth = "%s:%s" % (self.user, self.password)
100 else:
101 auth = self.user
102 connection.putheader("Proxy-authorization", "Basic " + base64.encodestring(auth))
103
104 event = e
105 data = e.data
106 name = bb.event.getName(event)
107 if name == "MsgNote":
108 # avoid recursion
109 return
110
111 if name == "TaskFailed":
112 xmlrpc = bb.data.getVar("BUGZILLA_XMLRPC", data, True)
113 user = bb.data.getVar("BUGZILLA_USER", data, True)
114 passw = bb.data.getVar("BUGZILLA_PASS", data, True)
115 product = bb.data.getVar("BUGZILLA_PRODUCT", data, True)
116 compon = bb.data.getVar("BUGZILLA_COMPONENT", data, True)
117 version = bb.data.getVar("BUGZILLA_VERSION", data, True)
118
119 proxy = bb.data.getVar('http_proxy', data, True )
120 if (proxy):
121 import urllib2
122 s, u, p, hostport = urllib2._parse_proxy(proxy)
123 transport = ProxiedTransport(hostport)
124 else:
125 transport = None
126
127 server = xmlrpclib.ServerProxy(xmlrpc, transport=transport, verbose=0)
128 args = {
129 'Bugzilla_login': user,
130 'Bugzilla_password': passw,
131 'product': product,
132 'component': compon}
133
134 # evil hack to figure out what is going on
135 debug_file = open(os.path.join(bb.data.getVar("TMPDIR", data, True),"..","bugzilla-log"),"a")
136
137 file = None
138 bugname = "%(package)s-%(pv)s-autobuild" % { "package" : bb.data.getVar("PN", data, True),
139 "pv" : bb.data.getVar("PV", data, True),
140 }
141 log_file = glob.glob("%s/log.%s.*" % (bb.data.getVar('T', event.data, True), event.task))
142 text = "The %s step in %s failed at %s for machine %s" % (e.task, bb.data.getVar("PN", data, True), bb.data.getVar('DATETIME', data, True), bb.data.getVar( 'MACHINE', data, True ) )
143 if len(log_file) != 0:
144 print >> debug_file, "Adding log file %s" % log_file[0]
145 file = open(log_file[0], 'r')
146 log = file.read()
147 file.close();
148 else:
149 print >> debug_file, "No log file found for the glob"
150 log = None
151
152 (bug_open, bug_number) = bugzilla_find_bug_report(debug_file, server, args.copy(), bugname)
153 print >> debug_file, "Bug is open: %s and bug number: %s" % (bug_open, bug_number)
154
155 # The bug is present and still open, attach an error log
156 if not bug_number:
157 bug_number = bugzilla_file_bug(debug_file, server, args.copy(), bugname, text, version)
158 if not bug_number:
159 print >> debug_file, "Couldn't acquire a new bug_numer, filing a bugreport failed"
160 else:
161 print >> debug_file, "The new bug_number: '%s'" % bug_number
162 elif not bug_open:
163 if not bugzilla_reopen_bug(debug_file, server, args.copy(), bug_number):
164 print >> debug_file, "Failed to reopen the bug #%s" % bug_number
165 else:
166 print >> debug_file, "Reopened the bug #%s" % bug_number
167
168 if bug_number and log:
169 print >> debug_file, "The bug is known as '%s'" % bug_number
170 desc = "Build log for machine %s" % (bb.data.getVar('MACHINE', data, True))
171 if not bugzilla_create_attachment(debug_file, server, args.copy(), bug_number, text, log_file[0], log, desc):
172 print >> debug_file, "Failed to attach the build log for bug #%s" % bug_number
173 else:
174 print >> debug_file, "Created an attachment for '%s' '%s' '%s'" % (product, compon, bug_number)
175 else:
176 print >> debug_file, "Not trying to create an attachment for bug #%s" % bug_number
177 if not bugzilla_add_comment(debug_file, server, args.copy(), bug_number, text, ):
178 print >> debug_file, "Failed to create a comment the build log for bug #%s" % bug_number
179 else:
180 print >> debug_file, "Created an attachment for '%s' '%s' '%s'" % (product, compon, bug_number)
181
182 # store bug number for oestats-client
183 if bug_number:
184 bb.data.setVar('OESTATS_BUG_NUMBER', bug_number, data)
185}
186