Repository: buildbot/buildbot

Issue:
Include build properties in gerrit summary callback
This allows a gerrit summary callback to do some more advanced filtering



Discussion:

Resolving patch:
diff --git a/master/buildbot/steps/python.py b/master/buildbot/steps/python.py
--- a/master/buildbot/steps/python.py
+++ b/master/buildbot/steps/python.py
@@ -135,6 +135,17 @@ class PyLint(ShellCommand):
     description = ["running", "pylint"]
     descriptionDone = ["pylint"]
 
+    # pylint's return codes (see pylint(1) for details)
+    # 1 - 16 will be bit-ORed
+
+    RC_OK = 0
+    RC_FATAL = 1
+    RC_ERROR = 2
+    RC_WARNING = 4
+    RC_REFACTOR = 8
+    RC_CONVENTION = 16
+    RC_USAGE = 32
+
     # Using the default text output, the message format is :
     # MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE
     # with --output-format=parseable it is: (the outer brackets are literal)
@@ -191,7 +202,7 @@ def createSummary(self, log):
         self.setProperty("pylint-total", sum(counts.values()))
 
     def evaluateCommand(self, cmd):
-        if cmd.rc != 0:
+        if cmd.rc & (self.RC_FATAL|self.RC_ERROR|self.RC_USAGE):
             return FAILURE
         for msg in self.flunkingIssues:
             if self.getProperty("pylint-%s" % self.MESSAGES[msg]):


Test patch:
diff --git a/master/buildbot/test/unit/test_steps_python.py b/master/buildbot/test/unit/test_steps_python.py
new file mode 100644
--- /dev/null
+++ b/master/buildbot/test/unit/test_steps_python.py
@@ -0,0 +1,95 @@
+# This file is part of Buildbot.  Buildbot is free software: you can
+# redistribute it and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation, version 2.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright Buildbot Team Members
+
+from twisted.trial import unittest
+
+from buildbot.status.results import FAILURE, SUCCESS
+from buildbot.steps import python
+from buildbot.test.fake.remotecommand import ExpectShell
+from buildbot.test.util import steps
+
+
+class PyLint(steps.BuildStepMixin, unittest.TestCase):
+
+    def setUp(self):
+        return self.setUpBuildStep()
+
+    def tearDown(self):
+        return self.tearDownBuildStep()
+
+    def test_success(self):
+        self.setupStep(python.PyLint(command=['pylint']))
+        self.expectCommands(
+            ExpectShell(workdir='wkdir', command=['pylint'],
+                        usePTY='slave-config')
+            + ExpectShell.log('stdio',
+                              stdout='Your code has been rated at 10/10')
+            + python.PyLint.RC_OK)
+        self.expectOutcome(result=SUCCESS, status_text=['pylint'])
+        return self.runStep()
+
+    def test_error(self):
+        self.setupStep(python.PyLint(command=['pylint']))
+        self.expectCommands(
+            ExpectShell(workdir='wkdir', command=['pylint'],
+                        usePTY='slave-config')
+            + ExpectShell.log(
+                'stdio',
+                stdout=('W: 11: Bad indentation. Found 6 spaces, expected 4\n'
+                        'E: 12: Undefined variable \'foo\'\n'))
+            + (python.PyLint.RC_WARNING|python.PyLint.RC_ERROR))
+        self.expectOutcome(result=FAILURE,
+                           status_text=['pylint', 'error=1', 'warning=1',
+                                        'failed'])
+        self.expectProperty('pylint-warning', 1)
+        self.expectProperty('pylint-error', 1)
+        return self.runStep()
+
+    def test_failure(self):
+        self.setupStep(python.PyLint(command=['pylint']))
+        self.expectCommands(
+            ExpectShell(workdir='wkdir', command=['pylint'],
+                        usePTY='slave-config')
+            + ExpectShell.log(
+                'stdio',
+                stdout=('W: 11: Bad indentation. Found 6 spaces, expected 4\n'
+                        'F: 13: something really strange happened\n'))
+            + (python.PyLint.RC_WARNING|python.PyLint.RC_FATAL))
+        self.expectOutcome(result=FAILURE,
+                           status_text=['pylint', 'fatal=1', 'warning=1',
+                                        'failed'])
+        self.expectProperty('pylint-warning', 1)
+        self.expectProperty('pylint-fatal', 1)
+        return self.runStep()
+
+    def test_failure_zero_returncode(self):
+        # Make sure that errors result in a failed step when pylint's
+        # return code is 0, e.g. when run through a wrapper script.
+        self.setupStep(python.PyLint(command=['pylint']))
+        self.expectCommands(
+            ExpectShell(workdir='wkdir', command=['pylint'],
+                        usePTY='slave-config')
+            + ExpectShell.log(
+                'stdio',
+                stdout=('W: 11: Bad indentation. Found 6 spaces, expected 4\n'
+                        'E: 12: Undefined variable \'foo\'\n'))
+            + 0)
+        self.expectOutcome(result=FAILURE,
+                           status_text=['pylint', 'error=1', 'warning=1',
+                                        'failed'])
+        self.expectProperty('pylint-warning', 1)
+        self.expectProperty('pylint-error', 1)
+        return self.runStep()
+