Gitlab - Minimal reporter ables to comment on MR
For history: https://gitlab.com/fabien.dot.boucher/demo-zuul/merge_requests/7#note_244782493 Change-Id: I2b7486c00dad24752d7073f301ce8d3384c0646c
This commit is contained in:
parent
f1368e84ec
commit
e20d254e6d
|
@ -1584,6 +1584,18 @@ class FakeGitlabAPIClient(gitlabconnection.GitlabAPIClient):
|
|||
if match:
|
||||
return [{'name': 'master'}], 200, "", "GET"
|
||||
|
||||
def post(self, url, params=None, zuul_event_id=None):
|
||||
|
||||
self.log.info(
|
||||
"Posting on resource %s, params (%s) ..." % (url, params))
|
||||
|
||||
match = re.match(r'.+/projects/(.+)/merge_requests/(\d+)/notes$', url)
|
||||
if match:
|
||||
mr = self._get_mr(match)
|
||||
mr.addNote(params['body'])
|
||||
|
||||
return {}, 200, "", "POST"
|
||||
|
||||
|
||||
class GitlabChangeReference(git.Reference):
|
||||
_common_path_default = "refs/merge-requests"
|
||||
|
@ -1612,6 +1624,7 @@ class FakeGitlabMergeRequest(object):
|
|||
self.merge_status = 'can_be_merged'
|
||||
self.uuid = uuid.uuid4().hex
|
||||
self.labels = []
|
||||
self.notes = []
|
||||
self.upstream_root = upstream_root
|
||||
self.url = "https://%s/%s/merge_requests/%s" % (
|
||||
self.gitlab.server, urllib.parse.quote_plus(
|
||||
|
@ -1632,6 +1645,15 @@ class FakeGitlabMergeRequest(object):
|
|||
def getMRReference(self):
|
||||
return '%s/head' % self.number
|
||||
|
||||
def addNote(self, body):
|
||||
self.notes.append(
|
||||
{
|
||||
"body": body,
|
||||
"created_at": datetime.datetime.now().strftime(
|
||||
'%Y-%m-%dT%H:%M:%S.%fZ'),
|
||||
}
|
||||
)
|
||||
|
||||
def _addCommitInMR(self, files=[], reset=False):
|
||||
repo = self._getRepo()
|
||||
ref = repo.references[self.getMRReference()]
|
||||
|
|
|
@ -6,6 +6,15 @@
|
|||
- event: gl_merge_request
|
||||
action:
|
||||
- opened
|
||||
start:
|
||||
gitlab:
|
||||
comment: True
|
||||
success:
|
||||
gitlab:
|
||||
comment: True
|
||||
failure:
|
||||
gitlab:
|
||||
comment: True
|
||||
|
||||
- job:
|
||||
name: base
|
||||
|
@ -16,8 +25,13 @@
|
|||
name: project-test1
|
||||
run: playbooks/project-test1.yaml
|
||||
|
||||
- job:
|
||||
name: project-test2
|
||||
run: playbooks/project-test2.yaml
|
||||
|
||||
- project:
|
||||
name: org/project
|
||||
check:
|
||||
jobs:
|
||||
- project-test1
|
||||
- project-test2
|
||||
|
|
|
@ -12,11 +12,14 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import re
|
||||
import socket
|
||||
|
||||
from tests.base import ZuulTestCase, simple_layout
|
||||
from tests.base import ZuulWebFixture
|
||||
|
||||
from testtools.matchers import MatchesRegex
|
||||
|
||||
|
||||
class TestGitlabWebhook(ZuulTestCase):
|
||||
config_file = 'zuul-gitlab-driver.conf'
|
||||
|
@ -67,3 +70,42 @@ class TestGitlabWebhook(ZuulTestCase):
|
|||
|
||||
self.assertEqual('SUCCESS',
|
||||
self.getJobFromHistory('project-test1').result)
|
||||
|
||||
|
||||
class TestGitlabDriver(ZuulTestCase):
|
||||
config_file = 'zuul-gitlab-driver.conf'
|
||||
|
||||
@simple_layout('layouts/basic-gitlab.yaml', driver='gitlab')
|
||||
def test_pull_request_opened(self):
|
||||
|
||||
description = "This is the\nMR description."
|
||||
A = self.fake_gitlab.openFakeMergeRequest(
|
||||
'org/project', 'master', 'A', description=description)
|
||||
self.fake_gitlab.emitEvent(
|
||||
A.getMergeRequestEvent(), project='org/project')
|
||||
self.waitUntilSettled()
|
||||
|
||||
self.assertEqual('SUCCESS',
|
||||
self.getJobFromHistory('project-test1').result)
|
||||
|
||||
self.assertEqual('SUCCESS',
|
||||
self.getJobFromHistory('project-test2').result)
|
||||
|
||||
job = self.getJobFromHistory('project-test2')
|
||||
zuulvars = job.parameters['zuul']
|
||||
self.assertEqual(str(A.number), zuulvars['change'])
|
||||
self.assertEqual(str(A.patch_number), zuulvars['patchset'])
|
||||
self.assertEqual('master', zuulvars['branch'])
|
||||
self.assertEquals('https://gitlab/org/project/merge_requests/1',
|
||||
zuulvars['items'][0]['change_url'])
|
||||
self.assertEqual(zuulvars["message"], description)
|
||||
self.assertEqual(2, len(self.history))
|
||||
self.assertEqual(2, len(A.notes))
|
||||
self.assertEqual(
|
||||
A.notes[0]['body'], "Starting check jobs.")
|
||||
self.assertThat(
|
||||
A.notes[1]['body'],
|
||||
MatchesRegex(r'.*project-test1.*SUCCESS.*', re.DOTALL))
|
||||
self.assertThat(
|
||||
A.notes[1]['body'],
|
||||
MatchesRegex(r'.*project-test2.*SUCCESS.*', re.DOTALL))
|
||||
|
|
|
@ -184,7 +184,7 @@ class GitlabAPIClient():
|
|||
self.session = requests.Session()
|
||||
self.baseurl = '%s/api/v4/' % baseurl
|
||||
self.api_token = api_token
|
||||
self.headers = {'Authorization': 'Authorization: Bearer %s' % (
|
||||
self.headers = {'Authorization': 'Bearer %s' % (
|
||||
self.api_token)}
|
||||
|
||||
def _manage_error(self, data, code, url, verb, zuul_event_id=None):
|
||||
|
@ -204,6 +204,15 @@ class GitlabAPIClient():
|
|||
ret.status_code, ret.text))
|
||||
return ret.json(), ret.status_code, ret.url, 'GET'
|
||||
|
||||
def post(self, url, params=None, zuul_event_id=None):
|
||||
log = get_annotated_logger(self.log, zuul_event_id)
|
||||
log.info(
|
||||
"Posting on resource %s, params (%s) ..." % (url, params))
|
||||
ret = self.session.post(url, data=params, headers=self.headers)
|
||||
log.debug("POST returned (code: %s): %s" % (
|
||||
ret.status_code, ret.text))
|
||||
return ret.json(), ret.status_code, ret.url, 'POST'
|
||||
|
||||
# https://docs.gitlab.com/ee/api/merge_requests.html#get-single-mr
|
||||
def get_mr(self, project_name, number, zuul_event_id=None):
|
||||
path = "/projects/%s/merge_requests/%s" % (
|
||||
|
@ -220,6 +229,17 @@ class GitlabAPIClient():
|
|||
self._manage_error(*resp, zuul_event_id=zuul_event_id)
|
||||
return [branch['name'] for branch in resp[0]]
|
||||
|
||||
# https://docs.gitlab.com/ee/api/notes.html#create-new-merge-request-note
|
||||
def comment_mr(self, project_name, number, msg, zuul_event_id=None):
|
||||
path = "/projects/%s/merge_requests/%s/notes" % (
|
||||
quote_plus(project_name), number)
|
||||
params = {'body': msg}
|
||||
resp = self.post(
|
||||
self.baseurl + path, params=params,
|
||||
zuul_event_id=zuul_event_id)
|
||||
self._manage_error(*resp, zuul_event_id=zuul_event_id)
|
||||
return resp[0]
|
||||
|
||||
|
||||
class GitlabConnection(BaseConnection):
|
||||
driver_name = 'gitlab'
|
||||
|
@ -393,6 +413,12 @@ class GitlabConnection(BaseConnection):
|
|||
log.info('Got MR %s#%s', project_name, number)
|
||||
return mr
|
||||
|
||||
def commentMR(self, project_name, number, message, event=None):
|
||||
log = get_annotated_logger(self.log, event)
|
||||
self.gl_client.comment_mr(
|
||||
project_name, number, message, zuul_event_id=event)
|
||||
log.info("Commented on MR %s#%s", project_name, number)
|
||||
|
||||
|
||||
class GitlabWebController(BaseWebController):
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ import logging
|
|||
import voluptuous as v
|
||||
|
||||
from zuul.reporter import BaseReporter
|
||||
from zuul.lib.logutil import get_annotated_logger
|
||||
from zuul.driver.gitlab.gitlabsource import GitlabSource
|
||||
|
||||
|
||||
class GitlabReporter(BaseReporter):
|
||||
|
@ -26,10 +28,30 @@ class GitlabReporter(BaseReporter):
|
|||
|
||||
def __init__(self, driver, connection, pipeline, config=None):
|
||||
super(GitlabReporter, self).__init__(driver, connection, config)
|
||||
self._create_comment = self.config.get('comment', True)
|
||||
|
||||
def report(self, item):
|
||||
"""Report on an event."""
|
||||
raise NotImplementedError()
|
||||
if not isinstance(item.change.project.source, GitlabSource):
|
||||
return
|
||||
|
||||
if item.change.project.source.connection.canonical_hostname != \
|
||||
self.connection.canonical_hostname:
|
||||
return
|
||||
|
||||
if hasattr(item.change, 'number'):
|
||||
if self._create_comment:
|
||||
self.addMRComment(item)
|
||||
|
||||
def addMRComment(self, item, comment=None):
|
||||
log = get_annotated_logger(self.log, item.event)
|
||||
message = comment or self._formatItemReport(item)
|
||||
project = item.change.project.name
|
||||
pr_number = item.change.number
|
||||
log.debug('Reporting change %s, params %s, message: %s',
|
||||
item.change, self.config, message)
|
||||
self.connection.commentMR(project, pr_number, message,
|
||||
event=item.event)
|
||||
|
||||
def mergePull(self, item):
|
||||
raise NotImplementedError()
|
||||
|
@ -39,4 +61,7 @@ class GitlabReporter(BaseReporter):
|
|||
|
||||
|
||||
def getSchema():
|
||||
return v.Schema({})
|
||||
gitlab_reporter = v.Schema({
|
||||
'comment': bool,
|
||||
})
|
||||
return gitlab_reporter
|
||||
|
|
Loading…
Reference in New Issue