[Buildbot-devel] HTML Mail notifier

Andy Howell AndyHowell at austin.rr.com
Sun Aug 1 08:35:10 UTC 2010


I was having problems making a an html mail formatter based on the one in the docs. That
one does not work as written. The 'changes' do not have a method asHTML.

I got the one below working. The utf-8 problems I was having with the GCC error messages
were solved by passing the logfile lines through unicode(line,'utf-8')

I think the log lines are coming from the BZ2File module. I couldn't find a way to set the
encoding there.

There is probably a better way to handle the unicode conversion, but this works.

I'm happy to make a patch to the docs with this if its deemed suitable.

Thanks,

	Andy


def html_message_formatter(mode, name, build, results, master_status):
    """Provide a customized message to BuildBot's MailNotifier.

    The last 300 lines of the log are provided as well as the changes
    relevant to the build.  Message content is formatted as html.
    """
    result = Results[results]

    limit_lines = 300
    text = list()
    text.append(u'<h4>Build status: %s</h4>' % result.upper())
    text.append(u'<table cellspacing="10"><tr>')
    text.append(u"<td>Buildslave for this Build:</td><td><b>%s</b></td></tr>" %
build.getSlavename())
    if master_status.getURLForThing(build):
        text.append(u'<tr><td>Complete logs for all build steps:</td><td><a
href="%s">%s</a></td></tr>'
                    % (master_status.getURLForThing(build),
                       master_status.getURLForThing(build))
                    )
        text.append(u'<tr><td>Build Reason:</td><td>%s</td></tr>' % build.getReason())
        source = u""
        ss = build.getSourceStamp()
        if ss.branch:
            source += u"[branch %s] " % ss.branch
        if ss.revision:
            source +=  ss.revision
        else:
            source += u"HEAD"
        if ss.patch:
            source += u" (plus patch)"
        text.append(u"<tr><td>Build Source Stamp:</td><td><b>%s</b></td></tr>" % source)
        text.append(u"<tr><td>Blamelist:</td><td>%s</td></tr>" %
",".join(build.getResponsibleUsers()))
        text.append(u'</table>')
        if ss.changes:
            text.append(u'<h4>Recent Changes:</h4>')
            for c in ss.changes:
                cd = c.asDict()
                when = datetime.datetime.fromtimestamp(cd['when'] ).ctime()
                text.append(u'<table cellspacing="10">')
                text.append(u'<tr><td>Repository:</td><td>%s</td></tr>' % cd['repository'] )
                text.append(u'<tr><td>Project:</td><td>%s</td></tr>' % cd['project'] )
                text.append(u'<tr><td>Time:</td><td>%s</td></tr>' % when)
                text.append(u'<tr><td>Changed by:</td><td>%s</td></tr>' % cd['who'] )
                text.append(u'<tr><td>Comments:</td><td>%s</td></tr>' % cd['comments'] )
                text.append(u'</table>')
                files = cd['files']
                if files:
                    text.append(u'<table cellspacing="10"><tr><th
align="left">Files</th><th>URL</th></tr>')
                    for file in files:
                        text.append(u'<tr><td>%s:</td><td>%s</td></tr>' % (file['name'],
file['url']))
                    text.append(u'</table>')
        text.append(u'<br>')
        # get log for last step
        logs = build.getLogs()
        # logs within a step are in reverse order. Search back until we find stdio
        for log in reversed(logs):
            if log.getName() == 'stdio':
                break
        name = "%s.%s" % (log.getStep().getName(), log.getName())
        status, dummy = log.getStep().getResults()
        content = log.getText().splitlines() # Note: can be VERY LARGE
        url = u'%s/steps/%s/logs/%s' % (master_status.getURLForThing(build),
                                       log.getStep().getName(),
                                       log.getName())

        text.append(u'<i>Detailed log of last build step:</i> <a href="%s">%s</a>'
                    % (url, url))
        text.append(u'<br>')
        text.append(u'<h4>Last %d lines of "%s"</h4>' % (limit_lines, name))
        unilist = list()
        for line in content[len(content)-limit_lines:]:
            try:
                unilist.append(cgi.escape(unicode(line,'utf-8')))
            except:
                unilist.append(hexdump(line,16))

        text.append(u'<pre>'.join([uniline for uniline in unilist]))
        text.append(u'</pre>')
        text.append(u'<br><br>')
        text.append(u'<b>-The BuildBot</b>')
        return {
            'body': u"\n".join(text),
            'type': 'html'
            }





More information about the devel mailing list