diff options
Diffstat (limited to 'classes/seppuku.bbclass')
| -rw-r--r-- | classes/seppuku.bbclass | 180 |
1 files changed, 149 insertions, 31 deletions
diff --git a/classes/seppuku.bbclass b/classes/seppuku.bbclass index 5757df7efb..a3b8b36dd0 100644 --- a/classes/seppuku.bbclass +++ b/classes/seppuku.bbclass @@ -5,6 +5,25 @@ # This class requires python2.4 because of the urllib2 usage # +def seppuku_spliturl(url): + """ + Split GET URL to return the host base and the query + as a param dictionary + """ + import urllib + (uri,query) = urllib.splitquery(url) + param = {} + for par in query.split("&"): + (key,value) = urllib.splitvalue(par) + if not key or len(key) == 0 or not value: + continue + key = urllib.unquote(key) + value = urllib.unquote(value) + param[key] = value + + return (uri,param) + + def seppuku_login(opener, login, user, password): """ @@ -13,7 +32,7 @@ def seppuku_login(opener, login, user, password): the resulting page then @param opened = cookie enabled urllib2 opener - @param login = http://bugzilla.openmoko.org/cgi-bin/bugzilla/query.cgi? + @param login = http://bugs.openembedded.org/query.cgi? @param user = Your username @param password = Your password """ @@ -48,10 +67,13 @@ def seppuku_find_bug_report_old(): HTMLParser.__init__(self) self.state = self.STATE_NONE self.bugs = [] + self.bug = None def handle_starttag(self, tag, attr): if self.state == self.STATE_NONE and tag.lower() == "tr": - if len(attr) == 1 and attr[0] == ('class', 'bz_normal bz_P2 '): + if len(attr) == 1 and attr[0][0] == 'class' and \ + ('bz_normal' in attr[0][1] or 'bz_blocker' in attr[0][1] or 'bz_enhancement' in attr[0][1] or 'bz_major' in attr[0][1] or 'bz_minor' in attr[0][1] or 'bz_trivial' in attr[0][1] or 'bz_critical' in attr[0][1] or 'bz_wishlist' in attr[0][1]) \ + and 'bz_P' in attr[0][1]: self.state = self.STATE_FOUND_TR elif self.state == self.STATE_FOUND_TR and tag.lower() == "td": self.state += 1 @@ -61,6 +83,7 @@ def seppuku_find_bug_report_old(): if self.state != self.STATE_NONE: self.bugs.append( (self.bug,self.status) ) self.state = self.STATE_NONE + self.bug = None if self.state > 1 and tag.lower() == "td": self.state += 1 @@ -72,7 +95,11 @@ def seppuku_find_bug_report_old(): return if self.state == self.STATE_FOUND_NUMBER: - self.bug = data + """ + #1995 in bugs.oe.org has [SEC] additionally to the number and we want to ignore it + """ + if not self.bug: + self.bug = data elif self.state == self.STATE_FOUND_STATUS: self.status = data @@ -83,20 +110,25 @@ def seppuku_find_bug_report_old(): -def seppuku_find_bug_report(opener, query, product, component, bugname): +def seppuku_find_bug_report(debug_file, opener, query, product, component, bugname): """ Find a bug report with the sane name and return the bug id and the status. @param opener = urllib2 opener - @param query = e.g. https://bugzilla.openmoko.org/cgi-bin/bugzilla/query.cgi? + @param query = e.g. http://bugs.openembedded.org/query.cgi? @param product = search for this product @param component = search for this component @param bugname = the bug to search for - https://bugzilla.openmoko.org/cgi-bin/bugzilla/buglist.cgi?short_desc_type=substring&short_desc=manual+test+bug&product=OpenMoko&emailreporter2=1&emailtype2=substring&email2=freyther%40yahoo.com + http://bugs.openembedded.org/buglist.cgi?short_desc_type=substring&short_desc=manual+test+bug&product=Openembedded&emailreporter2=1&emailtype2=substring&email2=freyther%40yahoo.com but it does not support ctype=csv... """ + import urllib + product = urllib.quote(product) + component = urllib.quote(component) + bugname = urllib.quote(bugname) + result = opener.open("%(query)s?product=%(product)s&component=%(component)s&short_desc_type=substring&short_desc=%(bugname)s" % vars()) if result.code != 200: raise "Can not query the bugzilla at all" @@ -104,41 +136,58 @@ def seppuku_find_bug_report(opener, query, product, component, bugname): scanner = seppuku_find_bug_report_old() scanner.feed(txt) if len(scanner.result()) == 0: + print >> debug_file, "Scanner failed to scan the html site" + print >> debug_file, "%(query)s?product=%(product)s&component=%(component)s&short_desc_type=substring&short_desc=%(bugname)s" % vars() + print >> debug_file, txt return (False,None) else: # silently pick the first result + print >> debug_file, "Result of bug search is " + print >> debug_file, txt (number,status) = scanner.result()[0] return (not status in ["CLOS", "RESO", "VERI"],number) -def seppuku_reopen_bug(opener, file, product, component, bug_number, bugname, text): +def seppuku_reopen_bug(poster, file, product, component, bug_number, bugname, text): """ Reopen a bug report and append to the comment Same as with opening a new report, some bits need to be inside the url - http://bugzilla.openmoko.org/cgi-bin/bugzilla/process_bug.cgi?id=239&bug_file_loc=http%3A%2F%2F&version=2007&longdesclength=2&product=OpenMoko&component=autobuilds&comment=bla&priority=P2&bug_severity=normal&op_sys=Linux&rep_platform=Neo1973&knob=reopen&target_milestone=Phase+0&short_desc=foo + http://bugs.openembedded.org/process_bug.cgi?id=239&bug_file_loc=http%3A%2F%2F&version=Angstrom&longdesclength=2&product=Openembedded&component=Build&comment=bla&priority=P2&bug_severity=normal&op_sys=Linux&rep_platform=Other&knob=reopen&short_desc=foo """ - import urllib, urllib2 - param = urllib.urlencode( { "product" : product, "component" : component, "longdesclength" : 2, - "short_desc" : bugname, "knob" : "reopen", "id" : bug_number, "comment" : text } ) + import urllib2 + (uri, param) = seppuku_spliturl( file ) + + # Prepare the post + param["product"] = product + param["component"] = component + param["longdesclength"] = 2 + param["short_desc"] = bugname + param["knob"] = "reopen" + param["id"] = bug_number + param["comment"] = text + try: - result = opener.open( file + param ) + result = poster.open( uri, param ) except urllib2.HTTPError, e: print e.geturl() print e.info() return False + except Exception, e: + print e + return False if result.code != 200: return False else: return True -def seppuku_file_bug(opener, file, product, component, bugname, text): +def seppuku_file_bug(poster, file, product, component, bugname, text): """ Create a completely new bug report - http://bugzilla.openmoko.org/cgi-bin/bugzilla/post_bug.cgi?bug_file_loc=http%3A%2F%2F&version=2007&product=OpenMoko&component=autobuilds&short_desc=foo&comment=bla&priority=P2&bug_severity=normal&op_sys=Linux&rep_platform=Neo1973 + http://bugs.openembedded.org/post_bug.cgi?bug_file_loc=http%3A%2F%2F&version=Angstrom&product=Openembedded&component=Build&short_desc=foo&comment=bla&priority=P2&bug_severity=normal&op_sys=Linux&rep_platform=Other You are forced to add some default values to the bugzilla query and stop with '&' @@ -150,23 +199,64 @@ def seppuku_file_bug(opener, file, product, component, bugname, text): @param text Text """ - import urllib,urllib2 - param = urllib.urlencode( { "product" : product, "component" : component, "short_desc" : bugname, "comment" : text } ) + import urllib2 + (uri, param) = seppuku_spliturl( file ) + param["product"] = product + param["component"] = component + param["short_desc"] = bugname + param["comment"] = text + try: - result = opener.open( file + param ) + result = poster.open( uri, param ) except urllib2.HTTPError, e: print e.geturl() print e.info() - raise e + return False + except Exception, e: + print e return False + # scan the result for a bug number + # it will look like + # '<a href="show_bug.cgi?id=308">Back To BUG# 308</a>' + import re + res = re.findall(("\>Back To BUG\# (?P<int>\d+)\</a\>"), result.read() ) + if result.code != 200 or len(res) != 1: + return None + else: + return res[0] + +def seppuku_create_attachment(debug, poster, attach_query, product, component, bug_number, text, file): + """ + + Create a new attachment for the failed report + """ + + if not bug_number: + import bb + bb.note("Can't create an attachment, the bug is not present") + return False + + import urllib2 + param = { "bugid" : bug_number, "action" : "insert", "data" : file, "description" : "Build log", "ispatch" : "0", "contenttypemethod" : "list", "contenttypeselection" : "text/plain", "comment" : text } + + try: + result = poster.open( attach_query, param ) + except urllib2.HTTPError, e: + print e.geturl() + print e.info() + return False + except Exception, e: + print e + return False + + print >> debug, result.read() if result.code != 200: return False else: return True - addhandler seppuku_eventhandler python seppuku_eventhandler() { """ @@ -177,7 +267,12 @@ python seppuku_eventhandler() { from bb import data, mkdirhier, build import bb, os, glob - bb.note( "Ran" ) + # Try to load our exotic libraries + try: + import MultipartPostHandler + except: + bb.note("You need to put the MultipartPostHandler into your PYTHONPATH. Download it from http://pipe.scs.fsu.edu/PostHandler/MultipartPostHandler.py") + return NotHandled try: import urllib2, cookielib @@ -194,50 +289,73 @@ python seppuku_eventhandler() { elif name == "TaskFailed" or name == "NoProvider": cj = cookielib.CookieJar() opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) + poster = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj),MultipartPostHandler.MultipartPostHandler) login = bb.data.getVar("SEPPUKU_LOGIN", data, True) query = bb.data.getVar("SEPPUKU_QUERY", data, True) newbug = bb.data.getVar("SEPPUKU_NEWREPORT", data, True) reopen = bb.data.getVar("SEPPUKU_ADDCOMMENT", data, True) + attach = bb.data.getVar("SEPPUKU_ATTACHMENT", data, True) user = bb.data.getVar("SEPPUKU_USER", data, True) passw = bb.data.getVar("SEPPUKU_PASS", data, True) product = bb.data.getVar("SEPPUKU_PRODUCT", data, True) component = bb.data.getVar("SEPPUKU_COMPONENT", data, True) + # evil hack to figure out what is going on + debug_file = open(os.path.join(bb.data.getVar("TMPDIR", data, True),"..","seppuku-log"),"a") if not seppuku_login(opener, login, user, passw): bb.note("Login to bugzilla failed") + print >> debug_file, "Login to bugzilla failed" return NotHandled else: - print "Logged into the box" + print >> debug_file, "Logged into the box" + file = None if name == "TaskFailed": bugname = "%(package)s-%(pv)s-%(pr)s-%(task)s" % { "package" : bb.data.getVar("PN", data, True), "pv" : bb.data.getVar("PV", data, True), "pr" : bb.data.getVar("PR", data, True), "task" : e.task } log_file = glob.glob("%s/log.%s.*" % (bb.data.getVar('T', event.data, True), event.task)) + text = "The package failed to build at %s" % bb.data.getVar('DATETIME', data, True) if len(log_file) != 0: - to_file = bb.data.getVar('TINDER_LOG', event.data, True) - text = "".join(open(log_file[0], 'r').readlines()) + print >> debug_file, "Adding log file %s" % log_file[0] + file = open(log_file[0], 'r') + else: + print >> debug_file, "No log file found for the glob" elif name == "NoProvider": bugname = "noprovider for %s runtime: %s" % (event.getItem, event.getisRuntime) text = "Please fix it" else: + print >> debug_file, "Unknown name '%s'" % name assert False - (bug_open, bug_number) = seppuku_find_bug_report(opener, query, product, component, bugname) - - bb.note("Bug is open: %s and bug number: %s" % (bug_open, bug_number)) + (bug_open, bug_number) = seppuku_find_bug_report(debug_file, opener, query, product, component, bugname) + print >> debug_file, "Bug is open: %s and bug number: %s" % (bug_open, bug_number) # The bug is present and still open, no need to attach an error log if bug_number and bug_open: - bb.note("The bug is known as '%s'" % bug_number) + print >> debug_file, "The bug is known as '%s'" % bug_number return NotHandled if bug_number and not bug_open: - if not seppuku_reopen_bug(opener, reopen, product, component, bug_number, bugname, text): - bb.note("Failed to reopen the bug report") - elif not seppuku_file_bug(opener, newbug, product, component, bugname, text): - bb.note("Filing a bugreport failed") + if not seppuku_reopen_bug(poster, reopen, product, component, bug_number, bugname, text): + print >> debug_file, "Failed to reopen the bug report" + else: + print >> debug_file, "Reopened the bug report" + else: + bug_number = seppuku_file_bug(poster, newbug, product, component, bugname, text) + if not bug_number: + print >> debug_file, "Filing a bugreport failed" + else: + print >> debug_file, "The new bug_number: '%s'" % bug_number + + if file: + if not seppuku_create_attachment(debug_file, poster, attach, product, component, bug_number, text, file): + print >> debug_file, "Failed to attach the build log" + else: + print >> debug_file, "Created an attachment for '%s' '%s' '%s'" % (product, component, bug_number) + else: + print >> debug_file, "Not trying to create an attachment" return NotHandled } |
