53841ce521
Now that bitbake supports masking events for event handlers, lets use this so event handlers are only called for events they care about. This lets us simplify the code indentation a bit at least as well as mildly improving the event handling performance. (From OE-Core rev: bff73743280f9eafebe4591f7368ead91a4eb74d) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
188 lines
7.3 KiB
Text
188 lines
7.3 KiB
Text
#
|
|
# Small event handler to automatically open URLs and file
|
|
# bug reports at a bugzilla of your choiche
|
|
# it uses XML-RPC interface, so you must have it enabled
|
|
#
|
|
# Before using you must define BUGZILLA_USER, BUGZILLA_PASS credentials,
|
|
# BUGZILLA_XMLRPC - uri of xmlrpc.cgi,
|
|
# BUGZILLA_PRODUCT, BUGZILLA_COMPONENT - a place in BTS for build bugs
|
|
# BUGZILLA_VERSION - version against which to report new bugs
|
|
#
|
|
|
|
def bugzilla_find_bug_report(debug_file, server, args, bugname):
|
|
args['summary'] = bugname
|
|
bugs = server.Bug.search(args)
|
|
if len(bugs['bugs']) == 0:
|
|
print >> debug_file, "Bugs not found"
|
|
return (False,None)
|
|
else: # silently pick the first result
|
|
print >> debug_file, "Result of bug search is "
|
|
print >> debug_file, bugs
|
|
status = bugs['bugs'][0]['status']
|
|
id = bugs['bugs'][0]['id']
|
|
return (not status in ["CLOSED", "RESOLVED", "VERIFIED"],id)
|
|
|
|
def bugzilla_file_bug(debug_file, server, args, name, text, version):
|
|
args['summary'] = name
|
|
args['comment'] = text
|
|
args['version'] = version
|
|
args['op_sys'] = 'Linux'
|
|
args['platform'] = 'Other'
|
|
args['severity'] = 'normal'
|
|
args['priority'] = 'Normal'
|
|
try:
|
|
return server.Bug.create(args)['id']
|
|
except Exception, e:
|
|
print >> debug_file, repr(e)
|
|
return None
|
|
|
|
def bugzilla_reopen_bug(debug_file, server, args, bug_number):
|
|
args['ids'] = [bug_number]
|
|
args['status'] = "CONFIRMED"
|
|
try:
|
|
server.Bug.update(args)
|
|
return True
|
|
except Exception, e:
|
|
print >> debug_file, repr(e)
|
|
return False
|
|
|
|
def bugzilla_create_attachment(debug_file, server, args, bug_number, text, file_name, log, logdescription):
|
|
args['ids'] = [bug_number]
|
|
args['file_name'] = file_name
|
|
args['summary'] = logdescription
|
|
args['content_type'] = "text/plain"
|
|
args['data'] = log
|
|
args['comment'] = text
|
|
try:
|
|
server.Bug.add_attachment(args)
|
|
return True
|
|
except Exception, e:
|
|
print >> debug_file, repr(e)
|
|
return False
|
|
|
|
def bugzilla_add_comment(debug_file, server, args, bug_number, text):
|
|
args['id'] = bug_number
|
|
args['comment'] = text
|
|
try:
|
|
server.Bug.add_comment(args)
|
|
return True
|
|
except Exception, e:
|
|
print >> debug_file, repr(e)
|
|
return False
|
|
|
|
addhandler bugzilla_eventhandler
|
|
bugzilla_eventhandler[eventmask] = "bb.event.MsgNote bb.build.TaskFailed"
|
|
python bugzilla_eventhandler() {
|
|
import glob
|
|
import xmlrpclib, httplib
|
|
|
|
class ProxiedTransport(xmlrpclib.Transport):
|
|
def __init__(self, proxy, use_datetime = 0):
|
|
xmlrpclib.Transport.__init__(self, use_datetime)
|
|
self.proxy = proxy
|
|
self.user = None
|
|
self.password = None
|
|
|
|
def set_user(self, user):
|
|
self.user = user
|
|
|
|
def set_password(self, password):
|
|
self.password = password
|
|
|
|
def make_connection(self, host):
|
|
self.realhost = host
|
|
return httplib.HTTP(self.proxy)
|
|
|
|
def send_request(self, connection, handler, request_body):
|
|
connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler))
|
|
if self.user != None:
|
|
if self.password != None:
|
|
auth = "%s:%s" % (self.user, self.password)
|
|
else:
|
|
auth = self.user
|
|
connection.putheader("Proxy-authorization", "Basic " + base64.encodestring(auth))
|
|
|
|
event = e
|
|
data = e.data
|
|
name = bb.event.getName(event)
|
|
if name == "MsgNote":
|
|
# avoid recursion
|
|
return
|
|
|
|
if name == "TaskFailed":
|
|
xmlrpc = data.getVar("BUGZILLA_XMLRPC", True)
|
|
user = data.getVar("BUGZILLA_USER", True)
|
|
passw = data.getVar("BUGZILLA_PASS", True)
|
|
product = data.getVar("BUGZILLA_PRODUCT", True)
|
|
compon = data.getVar("BUGZILLA_COMPONENT", True)
|
|
version = data.getVar("BUGZILLA_VERSION", True)
|
|
|
|
proxy = data.getVar('http_proxy', True )
|
|
if (proxy):
|
|
import urllib2
|
|
s, u, p, hostport = urllib2._parse_proxy(proxy)
|
|
transport = ProxiedTransport(hostport)
|
|
else:
|
|
transport = None
|
|
|
|
server = xmlrpclib.ServerProxy(xmlrpc, transport=transport, verbose=0)
|
|
args = {
|
|
'Bugzilla_login': user,
|
|
'Bugzilla_password': passw,
|
|
'product': product,
|
|
'component': compon}
|
|
|
|
# evil hack to figure out what is going on
|
|
debug_file = open(os.path.join(data.getVar("TMPDIR", True),"..","bugzilla-log"),"a")
|
|
|
|
file = None
|
|
bugname = "%(package)s-%(pv)s-autobuild" % { "package" : data.getVar("PN", True),
|
|
"pv" : data.getVar("PV", True),
|
|
}
|
|
log_file = glob.glob("%s/log.%s.*" % (event.data.getVar('T', True), event.task))
|
|
text = "The %s step in %s failed at %s for machine %s" % (e.task, data.getVar("PN", True), data.getVar('DATETIME', True), data.getVar( 'MACHINE', True ) )
|
|
if len(log_file) != 0:
|
|
print >> debug_file, "Adding log file %s" % log_file[0]
|
|
file = open(log_file[0], 'r')
|
|
log = file.read()
|
|
file.close();
|
|
else:
|
|
print >> debug_file, "No log file found for the glob"
|
|
log = None
|
|
|
|
(bug_open, bug_number) = bugzilla_find_bug_report(debug_file, server, args.copy(), bugname)
|
|
print >> debug_file, "Bug is open: %s and bug number: %s" % (bug_open, bug_number)
|
|
|
|
# The bug is present and still open, attach an error log
|
|
if not bug_number:
|
|
bug_number = bugzilla_file_bug(debug_file, server, args.copy(), bugname, text, version)
|
|
if not bug_number:
|
|
print >> debug_file, "Couldn't acquire a new bug_numer, filing a bugreport failed"
|
|
else:
|
|
print >> debug_file, "The new bug_number: '%s'" % bug_number
|
|
elif not bug_open:
|
|
if not bugzilla_reopen_bug(debug_file, server, args.copy(), bug_number):
|
|
print >> debug_file, "Failed to reopen the bug #%s" % bug_number
|
|
else:
|
|
print >> debug_file, "Reopened the bug #%s" % bug_number
|
|
|
|
if bug_number and log:
|
|
print >> debug_file, "The bug is known as '%s'" % bug_number
|
|
desc = "Build log for machine %s" % (data.getVar('MACHINE', True))
|
|
if not bugzilla_create_attachment(debug_file, server, args.copy(), bug_number, text, log_file[0], log, desc):
|
|
print >> debug_file, "Failed to attach the build log for bug #%s" % bug_number
|
|
else:
|
|
print >> debug_file, "Created an attachment for '%s' '%s' '%s'" % (product, compon, bug_number)
|
|
else:
|
|
print >> debug_file, "Not trying to create an attachment for bug #%s" % bug_number
|
|
if not bugzilla_add_comment(debug_file, server, args.copy(), bug_number, text, ):
|
|
print >> debug_file, "Failed to create a comment the build log for bug #%s" % bug_number
|
|
else:
|
|
print >> debug_file, "Created an attachment for '%s' '%s' '%s'" % (product, compon, bug_number)
|
|
|
|
# store bug number for oestats-client
|
|
if bug_number:
|
|
data.setVar('OESTATS_BUG_NUMBER', bug_number)
|
|
}
|
|
|