Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 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 | |
| 12 | def 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 | |
| 25 | def 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 | |
| 39 | def 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 | |
| 49 | def 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 | |
| 63 | def 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 | |
| 73 | addhandler bugzilla_eventhandler |
| 74 | bugzilla_eventhandler[eventmask] = "bb.event.MsgNote bb.build.TaskFailed" |
| 75 | python bugzilla_eventhandler() { |
| 76 | import glob |
| 77 | import xmlrpclib, httplib |
| 78 | |
| 79 | class ProxiedTransport(xmlrpclib.Transport): |
| 80 | def __init__(self, proxy, use_datetime = 0): |
| 81 | xmlrpclib.Transport.__init__(self, use_datetime) |
| 82 | self.proxy = proxy |
| 83 | self.user = None |
| 84 | self.password = None |
| 85 | |
| 86 | def set_user(self, user): |
| 87 | self.user = user |
| 88 | |
| 89 | def set_password(self, password): |
| 90 | self.password = password |
| 91 | |
| 92 | def make_connection(self, host): |
| 93 | self.realhost = host |
| 94 | return httplib.HTTP(self.proxy) |
| 95 | |
| 96 | def send_request(self, connection, handler, request_body): |
| 97 | connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler)) |
| 98 | if self.user != None: |
| 99 | if self.password != None: |
| 100 | auth = "%s:%s" % (self.user, self.password) |
| 101 | else: |
| 102 | auth = self.user |
| 103 | connection.putheader("Proxy-authorization", "Basic " + base64.encodestring(auth)) |
| 104 | |
| 105 | event = e |
| 106 | data = e.data |
| 107 | name = bb.event.getName(event) |
| 108 | if name == "MsgNote": |
| 109 | # avoid recursion |
| 110 | return |
| 111 | |
| 112 | if name == "TaskFailed": |
| 113 | xmlrpc = data.getVar("BUGZILLA_XMLRPC", True) |
| 114 | user = data.getVar("BUGZILLA_USER", True) |
| 115 | passw = data.getVar("BUGZILLA_PASS", True) |
| 116 | product = data.getVar("BUGZILLA_PRODUCT", True) |
| 117 | compon = data.getVar("BUGZILLA_COMPONENT", True) |
| 118 | version = data.getVar("BUGZILLA_VERSION", True) |
| 119 | |
| 120 | proxy = data.getVar('http_proxy', True ) |
| 121 | if (proxy): |
| 122 | import urllib2 |
| 123 | s, u, p, hostport = urllib2._parse_proxy(proxy) |
| 124 | transport = ProxiedTransport(hostport) |
| 125 | else: |
| 126 | transport = None |
| 127 | |
| 128 | server = xmlrpclib.ServerProxy(xmlrpc, transport=transport, verbose=0) |
| 129 | args = { |
| 130 | 'Bugzilla_login': user, |
| 131 | 'Bugzilla_password': passw, |
| 132 | 'product': product, |
| 133 | 'component': compon} |
| 134 | |
| 135 | # evil hack to figure out what is going on |
| 136 | debug_file = open(os.path.join(data.getVar("TMPDIR", True),"..","bugzilla-log"),"a") |
| 137 | |
| 138 | file = None |
| 139 | bugname = "%(package)s-%(pv)s-autobuild" % { "package" : data.getVar("PN", True), |
| 140 | "pv" : data.getVar("PV", True), |
| 141 | } |
| 142 | log_file = glob.glob("%s/log.%s.*" % (event.data.getVar('T', True), event.task)) |
| 143 | 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 ) ) |
| 144 | if len(log_file) != 0: |
| 145 | print >> debug_file, "Adding log file %s" % log_file[0] |
| 146 | file = open(log_file[0], 'r') |
| 147 | log = file.read() |
| 148 | file.close(); |
| 149 | else: |
| 150 | print >> debug_file, "No log file found for the glob" |
| 151 | log = None |
| 152 | |
| 153 | (bug_open, bug_number) = bugzilla_find_bug_report(debug_file, server, args.copy(), bugname) |
| 154 | print >> debug_file, "Bug is open: %s and bug number: %s" % (bug_open, bug_number) |
| 155 | |
| 156 | # The bug is present and still open, attach an error log |
| 157 | if not bug_number: |
| 158 | bug_number = bugzilla_file_bug(debug_file, server, args.copy(), bugname, text, version) |
| 159 | if not bug_number: |
| 160 | print >> debug_file, "Couldn't acquire a new bug_numer, filing a bugreport failed" |
| 161 | else: |
| 162 | print >> debug_file, "The new bug_number: '%s'" % bug_number |
| 163 | elif not bug_open: |
| 164 | if not bugzilla_reopen_bug(debug_file, server, args.copy(), bug_number): |
| 165 | print >> debug_file, "Failed to reopen the bug #%s" % bug_number |
| 166 | else: |
| 167 | print >> debug_file, "Reopened the bug #%s" % bug_number |
| 168 | |
| 169 | if bug_number and log: |
| 170 | print >> debug_file, "The bug is known as '%s'" % bug_number |
| 171 | desc = "Build log for machine %s" % (data.getVar('MACHINE', True)) |
| 172 | if not bugzilla_create_attachment(debug_file, server, args.copy(), bug_number, text, log_file[0], log, desc): |
| 173 | print >> debug_file, "Failed to attach the build log for bug #%s" % bug_number |
| 174 | else: |
| 175 | print >> debug_file, "Created an attachment for '%s' '%s' '%s'" % (product, compon, bug_number) |
| 176 | else: |
| 177 | print >> debug_file, "Not trying to create an attachment for bug #%s" % bug_number |
| 178 | if not bugzilla_add_comment(debug_file, server, args.copy(), bug_number, text, ): |
| 179 | print >> debug_file, "Failed to create a comment the build log for bug #%s" % bug_number |
| 180 | else: |
| 181 | print >> debug_file, "Created an attachment for '%s' '%s' '%s'" % (product, compon, bug_number) |
| 182 | |
| 183 | # store bug number for oestats-client |
| 184 | if bug_number: |
| 185 | data.setVar('OESTATS_BUG_NUMBER', bug_number) |
| 186 | } |
| 187 | |