Added GiteaStatusPush reporter
This commit is contained in:
parent
29750bcbdb
commit
78ccfc074b
166
buildbot_gitea/reporter.py
Normal file
166
buildbot_gitea/reporter.py
Normal file
|
@ -0,0 +1,166 @@
|
|||
# Based on the gitlab reporter from buildbot
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from twisted.internet import defer
|
||||
from twisted.python import log
|
||||
|
||||
from buildbot.process.properties import Interpolate
|
||||
from buildbot.process.properties import Properties
|
||||
from buildbot.process.results import CANCELLED
|
||||
from buildbot.process.results import EXCEPTION
|
||||
from buildbot.process.results import FAILURE
|
||||
from buildbot.process.results import RETRY
|
||||
from buildbot.process.results import SKIPPED
|
||||
from buildbot.process.results import SUCCESS
|
||||
from buildbot.process.results import WARNINGS
|
||||
from buildbot.reporters import http
|
||||
from buildbot.util import httpclientservice
|
||||
from buildbot.util import unicode2NativeString
|
||||
|
||||
|
||||
class GiteaStatusPush(http.HttpStatusPushBase):
|
||||
name = "GiteaStatusPush"
|
||||
neededDetails = dict(wantProperties=True)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def reconfigService(self, baseURL, token,
|
||||
startDescription=None, endDescription=None,
|
||||
context=None, context_pr=None, verbose=False,
|
||||
warningAsSuccess=False, **kwargs):
|
||||
|
||||
token = yield self.renderSecrets(token)
|
||||
yield http.HttpStatusPushBase.reconfigService(self, **kwargs)
|
||||
|
||||
self.context = context or Interpolate('buildbot/%(prop:buildername)s')
|
||||
self.context_pr = context_pr or \
|
||||
Interpolate('buildbot/pull_request/%(prop:buildername)s')
|
||||
self.startDescription = startDescription or 'Build started.'
|
||||
self.endDescription = endDescription or 'Build done.'
|
||||
if baseURL.endswith('/'):
|
||||
baseURL = baseURL[:-1]
|
||||
self.baseURL = baseURL
|
||||
self._http = yield httpclientservice.HTTPClientService.getService(
|
||||
self.master, baseURL,
|
||||
headers={'AuthorizationHeaderToken': 'token {}'.format(token)},
|
||||
debug=self.debug, verify=self.verify)
|
||||
self.verbose = verbose
|
||||
self.project_ids = {}
|
||||
self.warningAsSuccess = warningAsSuccess
|
||||
|
||||
def createStatus(self,
|
||||
project_owner, repo_name, sha, state, target_url=None,
|
||||
description=None, context=None):
|
||||
"""
|
||||
:param project_owner: username of the owning user or organization
|
||||
:param repo_name: name of the repository
|
||||
:param sha: Full sha to create the status for.
|
||||
:param state: one of the following 'pending', 'success', 'failed'
|
||||
or 'cancelled'.
|
||||
:param target_url: Target url to associate with this status.
|
||||
:param description: Short description of the status.
|
||||
:param context: Context of the result
|
||||
:return: A deferred with the result from GitLab.
|
||||
|
||||
"""
|
||||
payload = {'state': state}
|
||||
|
||||
if description is not None:
|
||||
payload['description'] = description
|
||||
|
||||
if target_url is not None:
|
||||
payload['target_url'] = target_url
|
||||
|
||||
if context is not None:
|
||||
payload['name'] = context
|
||||
|
||||
return self._http.post(
|
||||
'/api/v1/repos/{owner}/{repository}/statuses/{sha}'.format(
|
||||
owner=project_owner,
|
||||
repository=repo_name,
|
||||
sha=sha
|
||||
),
|
||||
json=payload)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def send(self, build):
|
||||
props = Properties.fromDict(build['properties'])
|
||||
props.master = self.master
|
||||
|
||||
if build['complete']:
|
||||
state = {
|
||||
SUCCESS: 'success',
|
||||
WARNINGS: 'success' if self.warningAsSuccess else 'warning',
|
||||
FAILURE: 'failure',
|
||||
SKIPPED: 'success',
|
||||
EXCEPTION: 'error',
|
||||
RETRY: 'pending',
|
||||
CANCELLED: 'error'
|
||||
}.get(build['results'], 'failure')
|
||||
description = yield props.render(self.endDescription)
|
||||
else:
|
||||
state = 'pending'
|
||||
description = yield props.render(self.startDescription)
|
||||
|
||||
if 'pr_id' in props:
|
||||
context = yield props.render(self.context_pr)
|
||||
else:
|
||||
context = yield props.render(self.context)
|
||||
|
||||
sourcestamps = build['buildset']['sourcestamps']
|
||||
|
||||
for sourcestamp in sourcestamps:
|
||||
sha = sourcestamp['revision']
|
||||
if 'repository_name' in props:
|
||||
repository_name = props['repository_name']
|
||||
else:
|
||||
log.msg(
|
||||
"Could not send status, "
|
||||
"build has no repository_name property for Gitea.")
|
||||
continue
|
||||
if 'owner' in props:
|
||||
repository_owner = props['owner']
|
||||
else:
|
||||
log.msg(
|
||||
"Could not send status, "
|
||||
"build has no owner property for Gitea.")
|
||||
continue
|
||||
try:
|
||||
sha = unicode2NativeString(sha)
|
||||
state = unicode2NativeString(state)
|
||||
target_url = unicode2NativeString(build['url'])
|
||||
context = unicode2NativeString(context)
|
||||
description = unicode2NativeString(description)
|
||||
res = yield self.createStatus(
|
||||
project_owner=repository_owner,
|
||||
repo_name=repository_name,
|
||||
sha=sha,
|
||||
state=state,
|
||||
target_url=target_url,
|
||||
context=context,
|
||||
description=description
|
||||
)
|
||||
if res.code not in (200, 201, 204):
|
||||
message = yield res.json()
|
||||
message = message.get('message', 'unspecified error')
|
||||
log.msg(
|
||||
'Could not send status "{state}" for '
|
||||
'{repo} at {sha}: {message}'.format(
|
||||
state=state,
|
||||
repo=sourcestamp['repository'], sha=sha,
|
||||
message=message))
|
||||
elif self.verbose:
|
||||
log.msg(
|
||||
'Status "{state}" sent for '
|
||||
'{repo} at {sha}.'.format(
|
||||
state=state,
|
||||
repo=sourcestamp['repository'], sha=sha))
|
||||
except Exception as e:
|
||||
log.err(
|
||||
e,
|
||||
'Failed to send status "{state}" for '
|
||||
'{repo} at {sha}'.format(
|
||||
state=state,
|
||||
repo=sourcestamp['repository'], sha=sha
|
||||
))
|
162
buildbot_gitea/test/test_reporter.py
Normal file
162
buildbot_gitea/test/test_reporter.py
Normal file
|
@ -0,0 +1,162 @@
|
|||
# Based on TestGitLabStatusPush from buildbot
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from mock import Mock
|
||||
|
||||
from twisted.internet import defer
|
||||
from twisted.trial import unittest
|
||||
|
||||
from buildbot import config
|
||||
from buildbot.process.properties import Interpolate
|
||||
from buildbot.process.results import FAILURE
|
||||
from buildbot.process.results import SUCCESS
|
||||
from buildbot_gitea.reporter import GiteaStatusPush
|
||||
from buildbot.test.fake import fakemaster
|
||||
from buildbot.test.fake import httpclientservice as fakehttpclientservice
|
||||
from buildbot.test.util import logging
|
||||
from buildbot.test.util.reporter import ReporterTestMixin
|
||||
|
||||
|
||||
class TestGiteaStatusPush(
|
||||
unittest.TestCase,
|
||||
ReporterTestMixin,
|
||||
logging.LoggingMixin):
|
||||
# repository must be in the form http://gitea/<owner>/<project>
|
||||
TEST_REPO = u'http://gitea/buildbot/buildbot'
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def setUp(self):
|
||||
# ignore config error if txrequests is not installed
|
||||
self.patch(config, '_errors', Mock())
|
||||
self.master = fakemaster.make_master(testcase=self,
|
||||
wantData=True, wantDb=True, wantMq=True)
|
||||
|
||||
yield self.master.startService()
|
||||
self._http = yield fakehttpclientservice.HTTPClientService.getFakeService(
|
||||
self.master, self,
|
||||
"http://gitea", headers={'AuthorizationHeaderToken': 'token XXYYZZ'},
|
||||
debug=None, verify=None)
|
||||
self.sp = sp = GiteaStatusPush("http://gitea/", Interpolate('XXYYZZ'))
|
||||
sp.sessionFactory = Mock(return_value=Mock())
|
||||
|
||||
yield sp.setServiceParent(self.master)
|
||||
|
||||
def tearDown(self):
|
||||
return self.master.stopService()
|
||||
|
||||
def setupProps(self):
|
||||
self.TEST_PROPS['owner'] = "buildbot"
|
||||
self.TEST_PROPS['repository_name'] = "buildbot"
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def setupBuildResults(self, buildResults):
|
||||
self.insertTestData([buildResults], buildResults)
|
||||
build = yield self.master.data.get(("builds", 20))
|
||||
defer.returnValue(build)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_basic(self):
|
||||
self.setupProps()
|
||||
build = yield self.setupBuildResults(SUCCESS)
|
||||
# we make sure proper calls to txrequests have been made
|
||||
self._http.expect(
|
||||
'post',
|
||||
'/api/v1/repos/buildbot/buildbot/statuses/d34db33fd43db33f',
|
||||
json={'state': 'pending',
|
||||
'target_url': 'http://localhost:8080/#builders/79/builds/0',
|
||||
'description': 'Build started.', 'name': 'buildbot/Builder0'})
|
||||
self._http.expect(
|
||||
'post',
|
||||
'/api/v1/repos/buildbot/buildbot/statuses/d34db33fd43db33f',
|
||||
json={'state': 'success',
|
||||
'target_url': 'http://localhost:8080/#builders/79/builds/0',
|
||||
'description': 'Build done.', 'name': 'buildbot/Builder0'})
|
||||
self._http.expect(
|
||||
'post',
|
||||
'/api/v1/repos/buildbot/buildbot/statuses/d34db33fd43db33f',
|
||||
json={'state': 'failure',
|
||||
'target_url': 'http://localhost:8080/#builders/79/builds/0',
|
||||
'description': 'Build done.', 'name': 'buildbot/Builder0'})
|
||||
|
||||
build['complete'] = False
|
||||
self.sp.buildStarted(("build", 20, "started"), build)
|
||||
build['complete'] = True
|
||||
self.sp.buildFinished(("build", 20, "finished"), build)
|
||||
build['results'] = FAILURE
|
||||
self.sp.buildFinished(("build", 20, "finished"), build)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_sshurl(self):
|
||||
self.setupProps()
|
||||
self.TEST_REPO = u'git@gitea:buildbot/buildbot.git'
|
||||
build = yield self.setupBuildResults(SUCCESS)
|
||||
# we make sure proper calls to txrequests have been made
|
||||
self._http.expect(
|
||||
'post',
|
||||
'/api/v1/repos/buildbot/buildbot/statuses/d34db33fd43db33f',
|
||||
json={'state': 'pending',
|
||||
'target_url': 'http://localhost:8080/#builders/79/builds/0',
|
||||
'description': 'Build started.', 'name': 'buildbot/Builder0'})
|
||||
build['complete'] = False
|
||||
self.sp.buildStarted(("build", 20, "started"), build)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_noowner(self):
|
||||
self.setUpLogging()
|
||||
self.setupProps()
|
||||
del self.TEST_PROPS["owner"]
|
||||
self.TEST_REPO = u''
|
||||
build = yield self.setupBuildResults(SUCCESS)
|
||||
build['complete'] = False
|
||||
self.sp.buildStarted(("build", 20, "started"), build)
|
||||
# implicit check that no http request is done
|
||||
self.assertLogged("Could not send status, "
|
||||
"build has no owner property for Gitea.")
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_noreponame(self):
|
||||
self.setUpLogging()
|
||||
self.setupProps()
|
||||
del self.TEST_PROPS["repository_name"]
|
||||
self.TEST_REPO = u''
|
||||
build = yield self.setupBuildResults(SUCCESS)
|
||||
build['complete'] = False
|
||||
self.sp.buildStarted(("build", 20, "started"), build)
|
||||
# implicit check that no http request is done
|
||||
self.assertLogged("Could not send status, "
|
||||
"build has no repository_name property for Gitea.")
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_senderror(self):
|
||||
self.setupProps()
|
||||
self.setUpLogging()
|
||||
build = yield self.setupBuildResults(SUCCESS)
|
||||
# we make sure proper calls to txrequests have been made
|
||||
self._http.expect(
|
||||
'post',
|
||||
'/api/v1/repos/buildbot/buildbot/statuses/d34db33fd43db33f',
|
||||
json={'state': 'pending',
|
||||
'target_url': 'http://localhost:8080/#builders/79/builds/0',
|
||||
'description': 'Build started.', 'name': 'buildbot/Builder0'},
|
||||
content_json={'message': 'sha1 not found for branch master'},
|
||||
code=404)
|
||||
build['complete'] = False
|
||||
self.sp.buildStarted(("build", 20, "started"), build)
|
||||
self.assertLogged(
|
||||
"Could not send status \"pending\" for "
|
||||
"http://gitea/buildbot/buildbot at d34db33fd43db33f:"
|
||||
" sha1 not found for branch master")
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_badchange(self):
|
||||
self.setupProps()
|
||||
self.setUpLogging()
|
||||
build = yield self.setupBuildResults(SUCCESS)
|
||||
# we make sure proper calls to txrequests have been made
|
||||
build['complete'] = False
|
||||
self.sp.buildStarted(("build", 20, "started"), build)
|
||||
self.assertLogged("Failed to send status \"pending\" for"
|
||||
" http://gitea/buildbot/buildbot at d34db33fd43db33f")
|
||||
self.flushLoggedErrors(AssertionError)
|
|
@ -43,6 +43,8 @@ class GiteaHandler(BaseHookHandler):
|
|||
'category': event_type,
|
||||
'properties': {
|
||||
'event': event_type,
|
||||
'repository_name': repository['name'],
|
||||
'owner': repository["owner"]["username"]
|
||||
},
|
||||
}
|
||||
if codebase is not None:
|
||||
|
@ -97,6 +99,8 @@ class GiteaHandler(BaseHookHandler):
|
|||
'head_git_ssh_url': head['repo']['ssh_url'],
|
||||
'pr_id': pull_request['id'],
|
||||
'pr_number': pull_request['number'],
|
||||
'repository_name': repository['name'],
|
||||
'owner': repository["owner"]["username"],
|
||||
},
|
||||
}
|
||||
if codebase is not None:
|
||||
|
|
Loading…
Reference in New Issue
Block a user