Skip to content

Commit

Permalink
first cut of custom gerrit labels
Browse files Browse the repository at this point in the history
* new format for the callback results (review & summary)
* test cases were renamed to _legacy (and they pass)
  • Loading branch information
Mikhail Sobolev committed Jul 10, 2014
1 parent 0c49182 commit c2d2e1a
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 48 deletions.
92 changes: 65 additions & 27 deletions master/buildbot/status/status_gerrit.py
Expand Up @@ -20,6 +20,8 @@

import time

import warnings

from buildbot.status import buildset
from buildbot.status.base import StatusReceiverMultiService
from buildbot.status.builder import EXCEPTION
Expand All @@ -36,17 +38,57 @@
# Cache the version that the gerrit server is running for this many seconds
GERRIT_VERSION_CACHE_TIMEOUT = 600

GERRIT_LABEL_VERIFIED = 'Verified'
GERRIT_LABEL_REVIEWED = 'Code-Review'


def makeReviewResult(message, *labels):
"""
helper to produce a review result
"""
return dict(message=message, labels=dict(labels))


def _handleLegacyResult(result):
"""
make sure the result is backward compatible
"""
if not isinstance(result, dict):
warnings.warn('The Gerrit status callback uses the old way to '
'communicate results. The outcome might be not what is '
'expected.')
message, verified, reviewed = result
result = makeReviewResult(message,
(GERRIT_LABEL_VERIFIED, verified),
(GERRIT_LABEL_REVIEWED, reviewed))
return result


def _old_add_label(label, value):
if label == GERRIT_LABEL_VERIFIED:
return ["--verified %d" % int(value)]
elif label == GERRIT_LABEL_REVIEWED:
return ["--code-review %d" % int(value)]
else:
warnings.warn('Gerrit older than 2.6 does not support custom labels. '
'Setting %s is ignored.' % label)
return []


def _new_add_label(label, value):
return ["--label %s=%d" % (label, int(value))]


def defaultReviewCB(builderName, build, result, status, arg):
if result == RETRY:
return None, 0, 0
return makeReviewResult(None)

message = "Buildbot finished compiling your patchset\n"
message += "on configuration: %s\n" % builderName
message += "The result is: %s\n" % Results[result].upper()

# message, verified, reviewed
return message, (result == SUCCESS or -1), 0
return makeReviewResult(message,
(GERRIT_LABEL_VERIFIED, result == SUCCESS or -1))


def defaultSummaryCB(buildInfoList, results, status, arg):
Expand All @@ -69,15 +111,12 @@ def defaultSummaryCB(buildInfoList, results, status, arg):
else:
failure = True

msg = '\n\n'.join(msgs)

if success and not failure:
verified = 1
else:
verified = -1

reviewed = 0
return (msg, verified, reviewed)
return makeReviewResult('\n\n'.join(msgs), (GERRIT_LABEL_VERIFIED, verified))


# These are just sentinel values for GerritStatusPush.__init__ args
Expand Down Expand Up @@ -232,8 +271,8 @@ def buildStarted(self, builderName, build):
def buildFinished(self, builderName, build, result):
"""Do the SSH gerrit verify command to the server."""
if self.reviewCB:
message, verified, reviewed = self.reviewCB(builderName, build, result, self.master_status, self.reviewArg)
self.sendCodeReviews(build, message, verified, reviewed)
result = _handleLegacyResult(self.reviewCB(builderName, build, result, self.master_status, self.reviewArg))
self.sendCodeReviews(build, result)

def sendBuildSetSummary(self, buildset, builds):
if self.summaryCB:
Expand All @@ -254,10 +293,11 @@ def getBuildInfo(build):
}
buildInfoList = sorted([getBuildInfo(build) for build in builds], key=lambda bi: bi['name'])

message, verified, reviewed = self.summaryCB(buildInfoList, Results[buildset['results']], self.master_status, self.summaryArg)
self.sendCodeReviews(builds[0], message, verified, reviewed)
result = _handleLegacyResult(self.summaryCB(buildInfoList, Results[buildset['results']], self.master_status, self.summaryArg))
self.sendCodeReviews(builds[0], result)

def sendCodeReviews(self, build, message, verified=0, reviewed=0):
def sendCodeReviews(self, build, result):
message = result.get('message', None)
if message is None:
return

Expand All @@ -275,7 +315,7 @@ def sendCodeReviews(self, build, message, verified=0, reviewed=0):
change2 = downloaded[2 * i]
revision = downloaded[2 * i + 1]
if change1 == change2:
self.sendCodeReview(project, revision, message, verified, reviewed)
self.sendCodeReview(project, revision, result)
else:
return # something is wrong, abort
return
Expand All @@ -291,32 +331,30 @@ def sendCodeReviews(self, build, message, verified=0, reviewed=0):
revision = None

if project is not None and revision is not None:
self.sendCodeReview(project, revision, message, verified, reviewed)
self.sendCodeReview(project, revision, result)
return

def sendCodeReview(self, project, revision, message=None, verified=0, reviewed=0):
def sendCodeReview(self, project, revision, result):
gerrit_version = self.getCachedVersion()
if (verified or reviewed) and gerrit_version is None:
self.callWithVersion(lambda: self.sendCodeReview(project, revision, message, verified, reviewed))
if gerrit_version is None:
self.callWithVersion(lambda: self.sendCodeReview(project, revision, result))
return

command = self._gerritCmd("review", "--project %s" % str(project))
message = result.get('message', None)
if message:
command.append("--message '%s'" % message.replace("'", "\""))

if verified:
assert(gerrit_version)
labels = result.get('labels', None)
if labels:
assert gerrit_version
if gerrit_version < LooseVersion("2.6"):
command.extend(["--verified %d" % int(verified)])
add_label = _old_add_label
else:
command.extend(["--label Verified=%d" % int(verified)])
add_label = _new_add_label

if reviewed:
assert(gerrit_version)
if gerrit_version < LooseVersion("2.6"):
command.extend(["--code-review %d" % int(reviewed)])
else:
command.extend(["--label Code-Review=%d" % int(reviewed)])
for label, value in labels.items():
command.extend(add_label(label, value))

command.append(str(revision))
print command
Expand Down
50 changes: 29 additions & 21 deletions master/buildbot/test/unit/test_status_gerrit.py
Expand Up @@ -16,19 +16,22 @@
from buildbot.status.results import FAILURE
from buildbot.status.results import SUCCESS
from buildbot.status.status_gerrit import GerritStatusPush
from buildbot.status.status_gerrit import makeReviewResult
from buildbot.status.status_gerrit import GERRIT_LABEL_VERIFIED
from buildbot.status.status_gerrit import GERRIT_LABEL_REVIEWED
from buildbot.test.fake import fakedb
from buildbot.test.fake import fakemaster
from buildbot.test.fake.fakebuild import FakeBuildStatus
from mock import Mock
from twisted.trial import unittest


def testReviewCB(builderName, build, result, status, arg):
def legacyTestReviewCB(builderName, build, result, status, arg):
msg = str({'name': builderName, 'result': result})
return (msg, 1 if result == SUCCESS else -1, 0)


def testSummaryCB(buildInfoList, results, status, arg):
def legacyTestSummaryCB(buildInfoList, results, status, arg):
success = False
failure = False

Expand Down Expand Up @@ -63,8 +66,8 @@ def run_prepare_gsp(self, gsp):
gsp.master = fakemaster.make_master()
gsp.master_status = gsp.master.status

def run_fake_summary_build(self, buildResults, finalResult, resultText, verifiedScore):
gsp = GerritStatusPush('host.example.com', 'username', summaryCB=testSummaryCB)
def run_fake_summary_build_legacy(self, buildResults, finalResult, resultText, verifiedScore):
gsp = GerritStatusPush('host.example.com', 'username', summaryCB=legacyTestSummaryCB)

buildpairs = []
i = 0
Expand Down Expand Up @@ -128,27 +131,31 @@ def check(_):
info.append({'name': "Builder-%d" % i, 'result': buildResults[i],
'resultText': resultText[i], 'text': 'buildText',
'url': self.THING_URL})
fakeSCR.assert_called_once_with(self.TEST_PROJECT, self.TEST_REVISION, str(info), verifiedScore, 0)

fakeSCR.assert_called_once_with(self.TEST_PROJECT, self.TEST_REVISION,
makeReviewResult(str(info),
(GERRIT_LABEL_VERIFIED, verifiedScore),
(GERRIT_LABEL_REVIEWED, 0)))
return d

def test_buildsetComplete_success_sends_summary_review(self):
d = self.run_fake_summary_build(buildResults=[SUCCESS, SUCCESS], finalResult=SUCCESS,
def test_buildsetComplete_success_sends_summary_review_legacy(self):
d = self.run_fake_summary_build_legacy(buildResults=[SUCCESS, SUCCESS], finalResult=SUCCESS,
resultText=["succeeded", "succeeded"], verifiedScore=1)
return d

def test_buildsetComplete_failure_sends_summary_review(self):
d = self.run_fake_summary_build(buildResults=[FAILURE, FAILURE], finalResult=FAILURE,
def test_buildsetComplete_failure_sends_summary_review_legacy(self):
d = self.run_fake_summary_build_legacy(buildResults=[FAILURE, FAILURE], finalResult=FAILURE,
resultText=["failed", "failed"], verifiedScore=-1)
return d

def test_buildsetComplete_mixed_sends_summary_review(self):
d = self.run_fake_summary_build(buildResults=[SUCCESS, FAILURE], finalResult=FAILURE,
resultText=["succeeded", "failed"], verifiedScore=-1)
def test_buildsetComplete_mixed_sends_summary_review_legacy(self):
d = self.run_fake_summary_build_legacy(buildResults=[SUCCESS, FAILURE],
finalResult=FAILURE,
resultText=["succeeded", "failed"],
verifiedScore=-1)
return d

def run_fake_single_build(self, buildResult, verifiedScore):
gsp = GerritStatusPush('host.example.com', 'username', reviewCB=testReviewCB)
def run_fake_single_build_legacy(self, buildResult, verifiedScore):
gsp = GerritStatusPush('host.example.com', 'username', reviewCB=legacyTestReviewCB)
self.run_prepare_gsp(gsp)

fakeSCR = Mock()
Expand All @@ -160,11 +167,12 @@ def run_fake_single_build(self, buildResult, verifiedScore):
gsp.buildFinished('dummyBuilder', build, buildResult)

fakeSCR.assert_called_once_with(self.TEST_PROJECT, self.TEST_REVISION,
str({'name': 'dummyBuilder', 'result': buildResult}),
verifiedScore, 0)
makeReviewResult(str({'name': 'dummyBuilder', 'result': buildResult}),
(GERRIT_LABEL_VERIFIED, verifiedScore),
(GERRIT_LABEL_REVIEWED, 0)))

def test_buildsetComplete_success_sends_review(self):
self.run_fake_single_build(SUCCESS, 1)
def test_buildsetComplete_success_sends_review_legacy(self):
self.run_fake_single_build_legacy(SUCCESS, 1)

def test_buildsetComplete_failure_sends_review(self):
self.run_fake_single_build(FAILURE, -1)
def test_buildsetComplete_failure_sends_review_legacy(self):
self.run_fake_single_build_legacy(FAILURE, -1)

0 comments on commit c2d2e1a

Please sign in to comment.