[Buildbot-devel] How to set build status in new style step?

Greg MacDonald gmacdonald at trionworlds.com
Thu Jun 25 22:30:42 UTC 2015

Happens with this simplified version as well, could this be a bug?

class ObservedShellCommand(buildstep.ShellMixin, buildstep.BuildStep):
    def __init__(self, **kwargs):
        kwargs = self.setupShellMixin(kwargs)
        buildstep.BuildStep.__init__(self, **kwargs)

    def run(self):
        cmd = yield self.makeRemoteShellCommand()
        yield self.runCommand(cmd)
        yield defer.returnValue(cmd.results())

From: Greg MacDonald
Sent: Thursday, June 25, 2015 2:42 PM
To: Greg MacDonald; buildbot-devel at lists.sourceforge.net
Subject: RE: How to set build status in new style step?

The build status is still green...

From: Greg MacDonald [mailto:gmacdonald at trionworlds.com]
Sent: Thursday, June 25, 2015 2:39 PM
To: buildbot-devel at lists.sourceforge.net<mailto:buildbot-devel at lists.sourceforge.net>
Subject: [Buildbot-devel] How to set build status in new style step?

Hi Everyone,

I'm having problems with my new-style custom shell command in 0.8.12. If the process returns 1, the build step fails with the rest of the steps aborted as expected, yet the status is still green on the web page. The example in the documentation here: http://docs.buildbot.net/current/manual/new-style-steps.html refers to a convertResults method that doesn't exist. Please help, what am I missing?

Here's my code:

from buildbot.plugins import util
from re import compile, IGNORECASE
from buildbot.process import buildstep
from buildbot.status.results import FAILURE, EXCEPTION, WARNINGS
from twisted.internet import defer

class _LogObserver(util.LogLineObserver):
    prefix = 'Observed: '

    def __init__(self, warningPatterns=None, errorPatterns=None, failImmediately=True):
        self.step = None
        self.warningPatterns = [compile(i, IGNORECASE) for i in warningPatterns] if warningPatterns else []
        self.errorPatterns = [compile(i, IGNORECASE) for i in errorPatterns] if errorPatterns else []
        self.failImmediately = failImmediately
        self.warnings = []
        self.errors = []
        self._log = None

    def log(self):
        if not self._log:
            self._log = self.step.getLog('stdio')
        return self._log

    def _processLine(self, line):
        if line.startswith(self.prefix):

        if any([i.search(line) for i in self.errorPatterns]):
            self.log.addStderr(unicode(self.prefix + 'Error: ' + line))
            if self.failImmediately:
                self.log.addStderr(u'Aborting step.')
                raise buildstep.BuildStepFailed('Fatal error detected.')
        elif any([i.search(line) for i in self.warningPatterns]):
            self.log.addStderr(unicode(self.prefix + 'Warning: ' + line))

    def outLineReceived(self, line):

    def errLineReceived(self, line):

    def getResults(self):
        if len(self.errors) > 0:
            return FAILURE
        if len(self.warnings) > 0:
            return WARNINGS
        return None

class ObservedShellCommand(buildstep.ShellMixin, buildstep.BuildStep):
    """Detects errors and warnings in stdio of a shell command."""
    name = "observed_shell"

    def __init__(self, warningPatterns=None, errorPatterns=None, failImmediately=True, **kwargs):
        kwargs = self.setupShellMixin(kwargs)
        buildstep.BuildStep.__init__(self, **kwargs)

        self.logObserver = _LogObserver(warningPatterns, errorPatterns, failImmediately)
        self.addLogObserver('stdio', self.logObserver)

        self.stepResults = None

    def getCurrentSummary(self):
        if self.stepResults in [FAILURE, EXCEPTION]:
            return {'build': u'failed', 'step': u'failed'}
        return u'running'

    def getResultSummary(self):
        if self.stepResults in [FAILURE, EXCEPTION]:
            return {'build': u'failed', 'step': u'failed'}
        return {}

    def run(self):
        cmd = yield self.makeRemoteShellCommand()
        yield self.runCommand(cmd)
        if cmd.didFail():
            self.stepResults = cmd.results()
            observedResults = self.logObserver.getResults()
            self.stepResults = observedResults if observedResults else cmd.results()

And the config:

                                       description=["Generate foo."],

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://buildbot.net/pipermail/devel/attachments/20150625/799bb66b/attachment.html>

More information about the devel mailing list