summaryrefslogtreecommitdiff
path: root/meta/classes/bugzilla.bbclass
blob: 801bd66d2f6b641a2d0c6dff916cdef341fefbf0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#
# 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
python bugzilla_eventhandler() {
    import bb, os, 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  = bb.data.getVar("BUGZILLA_XMLRPC", data, True)
        user    = bb.data.getVar("BUGZILLA_USER",  data, True)
        passw   = bb.data.getVar("BUGZILLA_PASS",  data, True)
        product = bb.data.getVar("BUGZILLA_PRODUCT", data, True)
        compon  = bb.data.getVar("BUGZILLA_COMPONENT", data, True)
        version = bb.data.getVar("BUGZILLA_VERSION", data, True)

        proxy   = bb.data.getVar('http_proxy', data, 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(bb.data.getVar("TMPDIR", data, True),"..","bugzilla-log"),"a")

        file = None
        bugname = "%(package)s-%(pv)s-autobuild" % { "package" : bb.data.getVar("PN", data, True),
                                                           "pv"      : bb.data.getVar("PV", data, True),
                                                           }
        log_file = glob.glob("%s/log.%s.*" % (bb.data.getVar('T', event.data, True), event.task))
        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 ) )
        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" % (bb.data.getVar('MACHINE', data, 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:
            bb.data.setVar('OESTATS_BUG_NUMBER', bug_number, data)
}