Skip to content

Commit

Permalink
rename Stash to BitbucketServer
Browse files Browse the repository at this point in the history
  • Loading branch information
EmilioPeJu committed Jun 23, 2017
1 parent a0bfa2e commit 7cfa010
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 166 deletions.
149 changes: 149 additions & 0 deletions master/buildbot/reporters/bitbucketserver.py
@@ -0,0 +1,149 @@
# 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 __future__ import absolute_import
from __future__ import print_function
from future.moves.urllib.parse import urlparse

from twisted.internet import defer

from buildbot.process.properties import Interpolate
from buildbot.process.properties import Properties
from buildbot.process.results import SUCCESS
from buildbot.reporters import http
from buildbot.util import httpclientservice
from buildbot.util.logger import Logger
from buildbot.util import unicode2bytes

log = Logger()

# Magic words understood by Bitbucket Server REST API
INPROGRESS = 'INPROGRESS'
SUCCESSFUL = 'SUCCESSFUL'
FAILED = 'FAILED'
STATUS_API_URL = '/rest/build-status/1.0/commits/{sha}'
COMMENT_API_URL = '/rest/api/1.0{path}/comments'
HTTP_PROCESSED = 204
HTTP_CREATED = 201


class BitbucketServerStatusPush(http.HttpStatusPushBase):
name = "BitbucketServerStatusPush"

@defer.inlineCallbacks
def reconfigService(self, base_url, user, password, key=None,
statusName=None, startDescription=None,
endDescription=None, verbose=False, **kwargs):
yield http.HttpStatusPushBase.reconfigService(
self, wantProperties=True, **kwargs)
self.key = key or Interpolate('%(prop:buildername)s')
self.statusName = statusName
self.endDescription = endDescription or 'Build done.'
self.startDescription = startDescription or 'Build started.'
self.verbose = verbose
self._http = yield httpclientservice.HTTPClientService.getService(
self.master, base_url, auth=(user, password),
debug=self.debug, verify=self.verify)

@defer.inlineCallbacks
def send(self, build):
props = Properties.fromDict(build['properties'])
results = build['results']
if build['complete']:
status = SUCCESSFUL if results == SUCCESS else FAILED
description = self.endDescription
else:
status = INPROGRESS
description = self.startDescription

# got_revision could be a string, a dictionary or None
got_revision = props.getProperty('got_revision', None)
for sourcestamp in build['buildset']['sourcestamps']:
sha = sourcestamp['revision']

if sha is None:
if isinstance(got_revision, dict):
sha = got_revision[sourcestamp['codebase']]
else:
sha = got_revision

if sha is None:
log.error("Unable to get the commit hash")
continue

key = yield props.render(self.key)
payload = {
'state': status,
'url': build['url'],
'key': key,
}
if description:
payload['description'] = yield props.render(description)
if self.statusName:
payload['name'] = yield props.render(self.statusName)
response = yield self._http.post(
STATUS_API_URL.format(sha=sha), json=payload)
if response.code == HTTP_PROCESSED:
if self.verbose:
log.info('Status "{status}" sent for {sha}.',
status=status, sha=sha)
else:
content = yield response.content()
log.error("{code}: Unable to send Bitbucket Server status: {content}",
code=response.code, content=content)


class BitbucketServerPRCommentPush(http.HttpStatusPushBase):
name = "BitbucketServerPRCommentPush"

@defer.inlineCallbacks
def reconfigService(self, base_url, user, password, text=None,
verbose=False, **kwargs):
yield http.HttpStatusPushBase.reconfigService(
self, wantProperties=True, **kwargs)
self.text = text or Interpolate('Builder: %(prop:buildername)s '
'Status: %(prop:statustext)s')
self.verbose = verbose
self._http = yield httpclientservice.HTTPClientService.getService(
self.master, base_url, auth=(user, password),
debug=self.debug, verify=self.verify)

@defer.inlineCallbacks
def send(self, build):
if build['complete'] and "pullrequesturl" in build['properties']:
yield self.sendPullRequestComment(build)

@defer.inlineCallbacks
def sendPullRequestComment(self, build):
props = Properties.fromDict(build['properties'])
pr_url = props.getProperty("pullrequesturl")
# we assume that the PR URL is well-formed as it comes from a PR event
path = urlparse(unicode2bytes(pr_url)).path
status = "SUCCESS" if build['results'] == SUCCESS else "FAILED"
props.setProperty('statustext', status, self.name)
props.setProperty('url', build['url'], self.name)
comment_text = yield props.render(self.text)
payload = {'text': comment_text}
response = yield self._http.post(
COMMENT_API_URL.format(path=path), json=payload)

if response.code == HTTP_CREATED:
if self.verbose:
log.info('{comment} sent to {url}',
comment=comment_text, url=pr_url)
else:
content = yield response.content()
log.error("{code}: Unable to send a comment: {content}",
code=response.code, content=content)
136 changes: 7 additions & 129 deletions master/buildbot/reporters/stash.py
Expand Up @@ -15,135 +15,13 @@

from __future__ import absolute_import
from __future__ import print_function
from future.moves.urllib.parse import urlparse

from twisted.internet import defer
from buildbot.reporters.bitbucketserver import BitbucketServerStatusPush

from buildbot.process.properties import Interpolate
from buildbot.process.properties import Properties
from buildbot.process.results import SUCCESS
from buildbot.reporters import http
from buildbot.util import httpclientservice
from buildbot.util.logger import Logger
from buildbot.util import unicode2bytes
import warnings

log = Logger()

# Magic words understood by Stash REST API
STASH_INPROGRESS = 'INPROGRESS'
STASH_SUCCESSFUL = 'SUCCESSFUL'
STASH_FAILED = 'FAILED'
STASH_STATUS_API_URL = '/rest/build-status/1.0/commits/{sha}'
STASH_COMMENT_API_URL = '/rest/api/1.0{path}/comments'
HTTP_PROCESSED = 204
HTTP_CREATED = 201


class StashStatusPush(http.HttpStatusPushBase):
name = "StashStatusPush"

@defer.inlineCallbacks
def reconfigService(self, base_url, user, password, key=None,
statusName=None, startDescription=None,
endDescription=None, verbose=False, **kwargs):
yield http.HttpStatusPushBase.reconfigService(
self, wantProperties=True, **kwargs)
self.key = key or Interpolate('%(prop:buildername)s')
self.statusName = statusName
self.endDescription = endDescription or 'Build done.'
self.startDescription = startDescription or 'Build started.'
self.verbose = verbose
self._http = yield httpclientservice.HTTPClientService.getService(
self.master, base_url, auth=(user, password),
debug=self.debug, verify=self.verify)

@defer.inlineCallbacks
def send(self, build):
props = Properties.fromDict(build['properties'])
results = build['results']
if build['complete']:
status = STASH_SUCCESSFUL if results == SUCCESS else STASH_FAILED
description = self.endDescription
else:
status = STASH_INPROGRESS
description = self.startDescription

# got_revision could be a string, a dictionary or None
got_revision = props.getProperty('got_revision', None)
for sourcestamp in build['buildset']['sourcestamps']:
sha = sourcestamp['revision']

if sha is None:
if isinstance(got_revision, dict):
sha = got_revision[sourcestamp['codebase']]
else:
sha = got_revision

if sha is None:
log.error("Unable to get the commit hash")
continue

key = yield props.render(self.key)
payload = {
'state': status,
'url': build['url'],
'key': key,
}
if description:
payload['description'] = yield props.render(description)
if self.statusName:
payload['name'] = yield props.render(self.statusName)
response = yield self._http.post(
STASH_STATUS_API_URL.format(sha=sha), json=payload)
if response.code == HTTP_PROCESSED:
if self.verbose:
log.info('Status "{status}" sent for {sha}.',
status=status, sha=sha)
else:
content = yield response.content()
log.error("{code}: Unable to send Stash status: {content}",
code=response.code, content=content)


class StashPRCommentPush(http.HttpStatusPushBase):
name = "StashPRCommentPush"

@defer.inlineCallbacks
def reconfigService(self, base_url, user, password, text=None,
verbose=False, **kwargs):
yield http.HttpStatusPushBase.reconfigService(
self, wantProperties=True, **kwargs)
self.text = text or Interpolate('Builder: %(prop:buildername)s '
'Status: %(prop:statustext)s')
self.verbose = verbose
self._http = yield httpclientservice.HTTPClientService.getService(
self.master, base_url, auth=(user, password),
debug=self.debug, verify=self.verify)

@defer.inlineCallbacks
def send(self, build):
if build['complete'] and "pullrequesturl" in build['properties']:
yield self.sendPullRequestComment(build)

@defer.inlineCallbacks
def sendPullRequestComment(self, build):
props = Properties.fromDict(build['properties'])
pr_url = props.getProperty("pullrequesturl")
# we assume that the PR URL is well-formed as it comes from a PR event
path = urlparse(unicode2bytes(pr_url)).path
status = "SUCCESS" if build['results'] == SUCCESS else "FAILED"
props.setProperty('statustext', status, self.name)
props.setProperty('url', build['url'], self.name)
comment_text = yield props.render(self.text)
payload = {'text': comment_text}
response = yield self._http.post(
STASH_COMMENT_API_URL.format(path=path), json=payload)

if response.code == HTTP_CREATED:
if self.verbose:
log.info('{comment} sent to {url}',
comment=comment_text, url=pr_url)
else:
content = yield response.content()
log.error("{code}: Unable to send a comment: {content}",
code=response.code, content=content)
def StashStatusPush(*args, **kwargs):
warnings.warn("The 'StashStatusPush' class was renamed to "
"'BitbucketServerStatusPush'",
DeprecationWarning )
return BitbucketServerStatusPush(*args, **kwargs)
Expand Up @@ -25,15 +25,15 @@
from buildbot.process.properties import Interpolate
from buildbot.process.results import FAILURE
from buildbot.process.results import SUCCESS
from buildbot.reporters.stash import StashStatusPush
from buildbot.reporters.stash import StashPRCommentPush
from buildbot.reporters.bitbucketserver import BitbucketServerPRCommentPush
from buildbot.reporters.bitbucketserver import BitbucketServerStatusPush
from buildbot.test.fake import httpclientservice as fakehttpclientservice
from buildbot.test.fake import fakemaster
from buildbot.test.util.logging import LoggingMixin
from buildbot.test.util.reporter import ReporterTestMixin


class TestStashStatusPush(unittest.TestCase, ReporterTestMixin, LoggingMixin):
class TestBitbucketServerStatusPush(unittest.TestCase, ReporterTestMixin, LoggingMixin):

@defer.inlineCallbacks
def setupReporter(self, **kwargs):
Expand All @@ -46,7 +46,7 @@ def setupReporter(self, **kwargs):
self.master, self,
'serv', auth=('username', 'passwd'),
debug=None, verify=None)
self.sp = sp = StashStatusPush("serv", "username", "passwd", **kwargs)
self.sp = sp = BitbucketServerStatusPush("serv", "username", "passwd", **kwargs)
yield sp.setServiceParent(self.master)
yield self.master.startService()

Expand Down Expand Up @@ -139,10 +139,10 @@ def test_error(self):
build['complete'] = False
self.setUpLogging()
self.sp.buildStarted(("build", 20, "started"), build)
self.assertLogged('404: Unable to send Stash status')
self.assertLogged('404: Unable to send Bitbucket Server status')


class TestStashPRCommentPush(unittest.TestCase, ReporterTestMixin, LoggingMixin):
class TestBitbucketServerPRCommentPush(unittest.TestCase, ReporterTestMixin, LoggingMixin):

@defer.inlineCallbacks
def setupReporter(self, **kwargs):
Expand All @@ -154,8 +154,8 @@ def setupReporter(self, **kwargs):
self._http = yield fakehttpclientservice.HTTPClientService.getFakeService(
self.master, self, 'serv', auth=('username', 'passwd'), debug=None,
verify=None)
self.sp = sp = StashPRCommentPush("serv", "username", "passwd", **kwargs)
yield sp.setServiceParent(self.master)
self.cp = cp = BitbucketServerPRCommentPush("serv", "username", "passwd", **kwargs)
yield cp.setServiceParent(self.master)
yield self.master.startService()

@defer.inlineCallbacks
Expand All @@ -182,17 +182,17 @@ def test_basic(self):
code=201)
build["complete"] = False
# this shouldn't send anything
self.sp.buildStarted(("build", 20, "started"), build)
self.cp.buildStarted(("build", 20, "started"), build)
self.assertEqual(len(self._http._expected), 1)
build["complete"] = True
self.sp.buildFinished(("build", 20, "finished"), build)
self.cp.buildFinished(("build", 20, "finished"), build)
self._http.expect(
"post",
u'/rest/api/1.0/projects/PRO/repos/myrepo/pull-requests/20/comments',
json={"text": "Builder: Builder0 Status: FAILED"},
code=201)
build["results"] = FAILURE
self.sp.buildFinished(("build", 20, "finished"), build)
self.cp.buildFinished(("build", 20, "finished"), build)

@defer.inlineCallbacks
def test_setting_options(self):
Expand All @@ -204,17 +204,17 @@ def test_setting_options(self):
json={'text': 'url: http://localhost:8080/#builders/79/builds/0 status: SUCCESS'},
code=201)
build["complete"] = False
self.sp.buildStarted(("build", 20, "started"), build)
self.cp.buildStarted(("build", 20, "started"), build)
self.assertEqual(len(self._http._expected), 1)
build["complete"] = True
self.sp.buildFinished(("build", 20, "finished"), build)
self.cp.buildFinished(("build", 20, "finished"), build)
self._http.expect(
"post",
u'/rest/api/1.0/projects/PRO/repos/myrepo/pull-requests/20/comments',
json={'text': 'url: http://localhost:8080/#builders/79/builds/0 status: FAILED'},
code=201)
build["results"] = FAILURE
self.sp.buildFinished(("build", 20, "finished"), build)
self.cp.buildFinished(("build", 20, "finished"), build)

@defer.inlineCallbacks
def test_error(self):
Expand All @@ -228,5 +228,5 @@ def test_error(self):
content_json=None)
self.setUpLogging()
build['complete'] = True
self.sp.buildFinished(("build", 20, "finished"), build)
self.cp.buildFinished(("build", 20, "finished"), build)
self.assertLogged('404: Unable to send a comment: None')

0 comments on commit 7cfa010

Please sign in to comment.