Perform actual HTTP requests in gitlab tests
In order to exercise our use of the requests library and the GitlabApiClient in Zuul, this removes the FakeGitlabApiClient in tests, instead running a real web server that we perform actual requests against. The existing work done by the fake client has been ported over to the web server. Change-Id: I553449d0e6d986378a38bf006347fd11a46876dc
This commit is contained in:
parent
96c61208a0
commit
6ddac4cb0c
201
tests/base.py
201
tests/base.py
|
@ -62,7 +62,6 @@ import testtools
|
||||||
import testtools.content
|
import testtools.content
|
||||||
import testtools.content_type
|
import testtools.content_type
|
||||||
from git.exc import NoSuchPathError
|
from git.exc import NoSuchPathError
|
||||||
from git.util import IterableList
|
|
||||||
import yaml
|
import yaml
|
||||||
import paramiko
|
import paramiko
|
||||||
import prometheus_client.exposition
|
import prometheus_client.exposition
|
||||||
|
@ -126,6 +125,7 @@ from zuul.lib.config import get_default
|
||||||
from zuul.lib.logutil import get_annotated_logger
|
from zuul.lib.logutil import get_annotated_logger
|
||||||
|
|
||||||
import tests.fakegithub
|
import tests.fakegithub
|
||||||
|
import tests.fakegitlab
|
||||||
|
|
||||||
FIXTURE_DIR = os.path.join(os.path.dirname(__file__), 'fixtures')
|
FIXTURE_DIR = os.path.join(os.path.dirname(__file__), 'fixtures')
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ class GitlabDriverMock(GitlabDriver):
|
||||||
changes_db=db,
|
changes_db=db,
|
||||||
upstream_root=self.upstream_root)
|
upstream_root=self.upstream_root)
|
||||||
setattr(self.registry, 'fake_' + name, connection)
|
setattr(self.registry, 'fake_' + name, connection)
|
||||||
registerProjects(connection.source.name, connection.gl_client,
|
registerProjects(connection.source.name, connection,
|
||||||
self.config)
|
self.config)
|
||||||
return connection
|
return connection
|
||||||
|
|
||||||
|
@ -1918,33 +1918,51 @@ class FakePagureConnection(pagureconnection.PagureConnection):
|
||||||
self.zuul_web_port = port
|
self.zuul_web_port = port
|
||||||
|
|
||||||
|
|
||||||
|
FakeGitlabBranch = namedtuple('Branch', ('name', 'protected'))
|
||||||
|
|
||||||
|
|
||||||
class FakeGitlabConnection(gitlabconnection.GitlabConnection):
|
class FakeGitlabConnection(gitlabconnection.GitlabConnection):
|
||||||
log = logging.getLogger("zuul.test.FakeGitlabConnection")
|
log = logging.getLogger("zuul.test.FakeGitlabConnection")
|
||||||
|
|
||||||
def __init__(self, driver, connection_name, connection_config, rpcclient,
|
def __init__(self, driver, connection_name, connection_config, rpcclient,
|
||||||
changes_db=None, upstream_root=None):
|
changes_db=None, upstream_root=None):
|
||||||
super(FakeGitlabConnection, self).__init__(driver, connection_name,
|
|
||||||
connection_config)
|
|
||||||
self.merge_requests = changes_db
|
self.merge_requests = changes_db
|
||||||
self.gl_client = FakeGitlabAPIClient(
|
|
||||||
self.baseurl, self.api_token, 60, merge_requests_db=changes_db)
|
|
||||||
self.rpcclient = rpcclient
|
self.rpcclient = rpcclient
|
||||||
self.upstream_root = upstream_root
|
self.upstream_root = upstream_root
|
||||||
self.mr_number = 0
|
self.mr_number = 0
|
||||||
|
|
||||||
|
self._test_web_server = tests.fakegitlab.GitlabWebServer(changes_db)
|
||||||
|
self._test_web_server.start()
|
||||||
|
self._test_baseurl = 'http://localhost:%s' % self._test_web_server.port
|
||||||
|
connection_config['baseurl'] = self._test_baseurl
|
||||||
|
|
||||||
|
super(FakeGitlabConnection, self).__init__(driver, connection_name,
|
||||||
|
connection_config)
|
||||||
|
|
||||||
|
def onStop(self):
|
||||||
|
super().onStop()
|
||||||
|
self._test_web_server.stop()
|
||||||
|
|
||||||
def addProject(self, project):
|
def addProject(self, project):
|
||||||
super(FakeGitlabConnection, self).addProject(project)
|
super(FakeGitlabConnection, self).addProject(project)
|
||||||
self.gl_client.addProject(project)
|
self.addProjectByName(project.name)
|
||||||
|
|
||||||
|
def addProjectByName(self, project_name):
|
||||||
|
owner, proj = project_name.split('/')
|
||||||
|
repo = self._test_web_server.fake_repos[(owner, proj)]
|
||||||
|
branch = FakeGitlabBranch('master', False)
|
||||||
|
if 'master' not in repo:
|
||||||
|
repo.append(branch)
|
||||||
|
|
||||||
def protectBranch(self, owner, project, branch, protected=True):
|
def protectBranch(self, owner, project, branch, protected=True):
|
||||||
if branch in self.gl_client.fake_repos[(owner, project)]:
|
if branch in self._test_web_server.fake_repos[(owner, project)]:
|
||||||
del self.gl_client.fake_repos[(owner, project)][branch]
|
del self._test_web_server.fake_repos[(owner, project)][branch]
|
||||||
fake_branch = FakeBranch(branch, protected=protected)
|
fake_branch = FakeGitlabBranch(branch, protected=protected)
|
||||||
self.gl_client.fake_repos[(owner, project)].append(fake_branch)
|
self._test_web_server.fake_repos[(owner, project)].append(fake_branch)
|
||||||
|
|
||||||
def deleteBranch(self, owner, project, branch):
|
def deleteBranch(self, owner, project, branch):
|
||||||
if branch in self.gl_client.fake_repos[(owner, project)]:
|
if branch in self._test_web_server.fake_repos[(owner, project)]:
|
||||||
del self.gl_client.fake_repos[(owner, project)][branch]
|
del self._test_web_server.fake_repos[(owner, project)][branch]
|
||||||
|
|
||||||
def getGitUrl(self, project):
|
def getGitUrl(self, project):
|
||||||
return 'file://' + os.path.join(self.upstream_root, project.name)
|
return 'file://' + os.path.join(self.upstream_root, project.name)
|
||||||
|
@ -2013,162 +2031,9 @@ class FakeGitlabConnection(gitlabconnection.GitlabConnection):
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def enable_community_edition(self):
|
def enable_community_edition(self):
|
||||||
self.gl_client.community_edition = True
|
self._test_web_server.options['community_edition'] = True
|
||||||
yield
|
yield
|
||||||
self.gl_client.community_edition = False
|
self._test_web_server.options['community_edition'] = False
|
||||||
|
|
||||||
|
|
||||||
FakeBranch = namedtuple('Branch', ('name', 'protected'))
|
|
||||||
|
|
||||||
|
|
||||||
class FakeGitlabAPIClient(gitlabconnection.GitlabAPIClient):
|
|
||||||
log = logging.getLogger("zuul.test.FakeGitlabAPIClient")
|
|
||||||
|
|
||||||
def __init__(self, baseurl, api_token, keepalive,
|
|
||||||
merge_requests_db={}):
|
|
||||||
super(FakeGitlabAPIClient, self).__init__(
|
|
||||||
baseurl, api_token, keepalive)
|
|
||||||
self.merge_requests = merge_requests_db
|
|
||||||
self.fake_repos = defaultdict(lambda: IterableList('name'))
|
|
||||||
self.community_edition = False
|
|
||||||
|
|
||||||
def gen_error(self, verb):
|
|
||||||
return {
|
|
||||||
'message': 'some error',
|
|
||||||
}, 503, "", verb
|
|
||||||
|
|
||||||
def _get_mr(self, match):
|
|
||||||
project, number = match.groups()
|
|
||||||
project = urllib.parse.unquote(project)
|
|
||||||
mr = self.merge_requests.get(project, {}).get(number)
|
|
||||||
if not mr:
|
|
||||||
return self.gen_error("GET")
|
|
||||||
return mr
|
|
||||||
|
|
||||||
def get(self, url, zuul_event_id=None):
|
|
||||||
log = get_annotated_logger(self.log, zuul_event_id)
|
|
||||||
log.debug("Getting resource %s ..." % url)
|
|
||||||
|
|
||||||
match = re.match(r'.+/projects/(.+)/merge_requests/(\d+)$', url)
|
|
||||||
if match:
|
|
||||||
mr = self._get_mr(match)
|
|
||||||
return {
|
|
||||||
'target_branch': mr.branch,
|
|
||||||
'title': mr.subject,
|
|
||||||
'state': mr.state,
|
|
||||||
'description': mr.description,
|
|
||||||
'author': {
|
|
||||||
'name': 'Administrator',
|
|
||||||
'username': 'admin'
|
|
||||||
},
|
|
||||||
'updated_at': mr.updated_at.strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
|
|
||||||
'sha': mr.sha,
|
|
||||||
'labels': mr.labels,
|
|
||||||
'merged_at': mr.merged_at,
|
|
||||||
'diff_refs': {
|
|
||||||
'base_sha': 'c380d3acebd181f13629a25d2e2acca46ffe1e00',
|
|
||||||
'head_sha': '2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f',
|
|
||||||
'start_sha': 'c380d3acebd181f13629a25d2e2acca46ffe1e00'
|
|
||||||
},
|
|
||||||
'merge_status': mr.merge_status,
|
|
||||||
}, 200, "", "GET"
|
|
||||||
|
|
||||||
match = re.match('.+/projects/(.+)/'
|
|
||||||
'repository/branches\\?.*$', url)
|
|
||||||
if match:
|
|
||||||
project = urllib.parse.unquote(match.group(1)).split('/')
|
|
||||||
req = urllib.parse.urlparse(url)
|
|
||||||
query = urllib.parse.parse_qs(req.query)
|
|
||||||
per_page = int(query["per_page"][0])
|
|
||||||
page = int(query["page"][0])
|
|
||||||
|
|
||||||
repo = self.fake_repos[tuple(project)]
|
|
||||||
first_entry = (page - 1) * per_page
|
|
||||||
last_entry = min(len(repo), (page) * per_page)
|
|
||||||
|
|
||||||
if first_entry >= len(repo):
|
|
||||||
branches = []
|
|
||||||
else:
|
|
||||||
branches = [{'name': repo[i].name,
|
|
||||||
'protected': repo[i].protected}
|
|
||||||
for i in range(first_entry, last_entry)]
|
|
||||||
|
|
||||||
return branches, 200, "", "GET"
|
|
||||||
|
|
||||||
match = re.match(
|
|
||||||
r'.+/projects/(.+)/merge_requests/(\d+)/approvals$', url)
|
|
||||||
if match:
|
|
||||||
mr = self._get_mr(match)
|
|
||||||
if not self.community_edition:
|
|
||||||
return {
|
|
||||||
'approvals_left': 0 if mr.approved else 1,
|
|
||||||
}, 200, "", "GET"
|
|
||||||
else:
|
|
||||||
return {
|
|
||||||
'approved': mr.approved,
|
|
||||||
}, 200, "", "GET"
|
|
||||||
|
|
||||||
match = re.match(r'.+/projects/(.+)/repository/branches/(.+)$', url)
|
|
||||||
if match:
|
|
||||||
project, branch = match.groups()
|
|
||||||
project = urllib.parse.unquote(project)
|
|
||||||
branch = urllib.parse.unquote(branch)
|
|
||||||
owner, name = project.split('/')
|
|
||||||
if branch in self.fake_repos[(owner, name)]:
|
|
||||||
protected = self.fake_repos[(owner, name)][branch].protected
|
|
||||||
return {'protected': protected}, 200, "", "GET"
|
|
||||||
else:
|
|
||||||
return {}, 404, "", "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'])
|
|
||||||
|
|
||||||
match = re.match(
|
|
||||||
r'.+/projects/(.+)/merge_requests/(\d+)/approve$', url)
|
|
||||||
if match:
|
|
||||||
assert 'sha' in params
|
|
||||||
mr = self._get_mr(match)
|
|
||||||
if params['sha'] != mr.sha:
|
|
||||||
return {'message': 'SHA does not match HEAD of source '
|
|
||||||
'branch: <new_sha>'}, 409, "", "POST"
|
|
||||||
mr.approved = True
|
|
||||||
|
|
||||||
match = re.match(
|
|
||||||
r'.+/projects/(.+)/merge_requests/(\d+)/unapprove$', url)
|
|
||||||
if match:
|
|
||||||
mr = self._get_mr(match)
|
|
||||||
mr.approved = False
|
|
||||||
|
|
||||||
return {}, 200, "", "POST"
|
|
||||||
|
|
||||||
def put(self, url, params=None, zuul_event_id=None):
|
|
||||||
|
|
||||||
self.log.info(
|
|
||||||
"Put on resource %s, params (%s) ..." % (url, params))
|
|
||||||
|
|
||||||
match = re.match(r'.+/projects/(.+)/merge_requests/(\d+)/merge$', url)
|
|
||||||
if match:
|
|
||||||
mr = self._get_mr(match)
|
|
||||||
mr.mergeMergeRequest()
|
|
||||||
|
|
||||||
return {'state': 'merged'}, 200, "", "PUT"
|
|
||||||
|
|
||||||
def addProject(self, project):
|
|
||||||
self.addProjectByName(project.name)
|
|
||||||
|
|
||||||
def addProjectByName(self, project_name):
|
|
||||||
owner, proj = project_name.split('/')
|
|
||||||
repo = self.fake_repos[(owner, proj)]
|
|
||||||
branch = FakeBranch('master', False)
|
|
||||||
if 'master' not in repo:
|
|
||||||
repo.append(branch)
|
|
||||||
|
|
||||||
|
|
||||||
class GitlabChangeReference(git.Reference):
|
class GitlabChangeReference(git.Reference):
|
||||||
|
|
|
@ -0,0 +1,246 @@
|
||||||
|
# Copyright 2016 Red Hat, Inc.
|
||||||
|
# Copyright 2021 Acme Gating, LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
import http.server
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import re
|
||||||
|
import socketserver
|
||||||
|
import threading
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
|
from git.util import IterableList
|
||||||
|
|
||||||
|
|
||||||
|
class GitlabWebServer(object):
|
||||||
|
|
||||||
|
def __init__(self, merge_requests):
|
||||||
|
super(GitlabWebServer, self).__init__()
|
||||||
|
self.merge_requests = merge_requests
|
||||||
|
self.fake_repos = defaultdict(lambda: IterableList('name'))
|
||||||
|
# A dictionary so we can mutate it
|
||||||
|
self.options = dict(community_edition=False)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
merge_requests = self.merge_requests
|
||||||
|
fake_repos = self.fake_repos
|
||||||
|
options = self.options
|
||||||
|
|
||||||
|
class Server(http.server.SimpleHTTPRequestHandler):
|
||||||
|
log = logging.getLogger("zuul.test.GitlabWebServer")
|
||||||
|
|
||||||
|
branches_re = re.compile(r'.+/projects/(?P<project>.+)/'
|
||||||
|
r'repository/branches\\?.*$')
|
||||||
|
branch_re = re.compile(r'.+/projects/(?P<project>.+)/'
|
||||||
|
r'repository/branches/(?P<branch>.+)$')
|
||||||
|
mr_re = re.compile(r'.+/projects/(?P<project>.+)/'
|
||||||
|
r'merge_requests/(?P<mr>\d+)$')
|
||||||
|
mr_approvals_re = re.compile(
|
||||||
|
r'.+/projects/(?P<project>.+)/'
|
||||||
|
r'merge_requests/(?P<mr>\d+)/approvals$')
|
||||||
|
|
||||||
|
mr_notes_re = re.compile(
|
||||||
|
r'.+/projects/(?P<project>.+)/'
|
||||||
|
r'merge_requests/(?P<mr>\d+)/notes$')
|
||||||
|
mr_approve_re = re.compile(
|
||||||
|
r'.+/projects/(?P<project>.+)/'
|
||||||
|
r'merge_requests/(?P<mr>\d+)/approve$')
|
||||||
|
mr_unapprove_re = re.compile(
|
||||||
|
r'.+/projects/(?P<project>.+)/'
|
||||||
|
r'merge_requests/(?P<mr>\d+)/unapprove$')
|
||||||
|
|
||||||
|
mr_merge_re = re.compile(r'.+/projects/(?P<project>.+)/'
|
||||||
|
r'merge_requests/(?P<mr>\d+)/merge$')
|
||||||
|
|
||||||
|
def _get_mr(self, project, number):
|
||||||
|
project = urllib.parse.unquote(project)
|
||||||
|
mr = merge_requests.get(project, {}).get(number)
|
||||||
|
if not mr:
|
||||||
|
# Find out what gitlab does in this case
|
||||||
|
raise NotImplementedError()
|
||||||
|
return mr
|
||||||
|
|
||||||
|
def do_GET(self):
|
||||||
|
path = self.path
|
||||||
|
self.log.debug("Got GET %s", path)
|
||||||
|
|
||||||
|
m = self.mr_re.match(path)
|
||||||
|
if m:
|
||||||
|
return self.get_mr(**m.groupdict())
|
||||||
|
m = self.mr_approvals_re.match(path)
|
||||||
|
if m:
|
||||||
|
return self.get_mr_approvals(**m.groupdict())
|
||||||
|
m = self.branch_re.match(path)
|
||||||
|
if m:
|
||||||
|
return self.get_branch(**m.groupdict())
|
||||||
|
m = self.branches_re.match(path)
|
||||||
|
if m:
|
||||||
|
return self.get_branches(path, **m.groupdict())
|
||||||
|
self.send_response(500)
|
||||||
|
self.end_headers()
|
||||||
|
|
||||||
|
def do_POST(self):
|
||||||
|
path = self.path
|
||||||
|
self.log.debug("Got POST %s", path)
|
||||||
|
|
||||||
|
data = self.rfile.read(int(self.headers['Content-Length']))
|
||||||
|
if (self.headers['Content-Type'] ==
|
||||||
|
'application/x-www-form-urlencoded'):
|
||||||
|
data = urllib.parse.parse_qs(data.decode('utf-8'))
|
||||||
|
|
||||||
|
self.log.debug("Got data %s", data)
|
||||||
|
|
||||||
|
m = self.mr_notes_re.match(path)
|
||||||
|
if m:
|
||||||
|
return self.post_mr_notes(data, **m.groupdict())
|
||||||
|
m = self.mr_approve_re.match(path)
|
||||||
|
if m:
|
||||||
|
return self.post_mr_approve(data, **m.groupdict())
|
||||||
|
m = self.mr_unapprove_re.match(path)
|
||||||
|
if m:
|
||||||
|
return self.post_mr_unapprove(data, **m.groupdict())
|
||||||
|
self.send_response(500)
|
||||||
|
self.end_headers()
|
||||||
|
|
||||||
|
def do_PUT(self):
|
||||||
|
path = self.path
|
||||||
|
self.log.debug("Got PUT %s", path)
|
||||||
|
|
||||||
|
data = self.rfile.read(int(self.headers['Content-Length']))
|
||||||
|
if (self.headers['Content-Type'] ==
|
||||||
|
'application/x-www-form-urlencoded'):
|
||||||
|
data = urllib.parse.parse_qs(data.decode('utf-8'))
|
||||||
|
|
||||||
|
self.log.debug("Got data %s", data)
|
||||||
|
|
||||||
|
m = self.mr_merge_re.match(path)
|
||||||
|
if m:
|
||||||
|
return self.put_mr_merge(data, **m.groupdict())
|
||||||
|
self.send_response(500)
|
||||||
|
self.end_headers()
|
||||||
|
|
||||||
|
def send_data(self, data, code=200):
|
||||||
|
data = json.dumps(data).encode('utf-8')
|
||||||
|
self.send_response(code)
|
||||||
|
self.send_header('Content-Type', 'application/json')
|
||||||
|
self.send_header('Content-Length', len(data))
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(data)
|
||||||
|
|
||||||
|
def get_mr(self, project, mr):
|
||||||
|
mr = self._get_mr(project, mr)
|
||||||
|
data = {
|
||||||
|
'target_branch': mr.branch,
|
||||||
|
'title': mr.subject,
|
||||||
|
'state': mr.state,
|
||||||
|
'description': mr.description,
|
||||||
|
'author': {
|
||||||
|
'name': 'Administrator',
|
||||||
|
'username': 'admin'
|
||||||
|
},
|
||||||
|
'updated_at':
|
||||||
|
mr.updated_at.strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
|
||||||
|
'sha': mr.sha,
|
||||||
|
'labels': mr.labels,
|
||||||
|
'merged_at': mr.merged_at.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
|
||||||
|
if mr.merged_at else mr.merged_at,
|
||||||
|
'diff_refs': {
|
||||||
|
'base_sha': 'c380d3acebd181f13629a25d2e2acca46ffe1e00',
|
||||||
|
'head_sha': '2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f',
|
||||||
|
'start_sha': 'c380d3acebd181f13629a25d2e2acca46ffe1e00'
|
||||||
|
},
|
||||||
|
'merge_status': mr.merge_status,
|
||||||
|
}
|
||||||
|
self.send_data(data)
|
||||||
|
|
||||||
|
def get_mr_approvals(self, project, mr):
|
||||||
|
mr = self._get_mr(project, mr)
|
||||||
|
if not options['community_edition']:
|
||||||
|
self.send_data({
|
||||||
|
'approvals_left': 0 if mr.approved else 1,
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
self.send_data({
|
||||||
|
'approved': mr.approved,
|
||||||
|
})
|
||||||
|
|
||||||
|
def get_branch(self, project, branch):
|
||||||
|
project = urllib.parse.unquote(project)
|
||||||
|
branch = urllib.parse.unquote(branch)
|
||||||
|
owner, name = project.split('/')
|
||||||
|
if branch in fake_repos[(owner, name)]:
|
||||||
|
protected = fake_repos[(owner, name)][branch].protected
|
||||||
|
self.send_data({'protected': protected})
|
||||||
|
else:
|
||||||
|
return self.send_data({}, code=404)
|
||||||
|
|
||||||
|
def get_branches(self, url, project):
|
||||||
|
project = urllib.parse.unquote(project).split('/')
|
||||||
|
req = urllib.parse.urlparse(url)
|
||||||
|
query = urllib.parse.parse_qs(req.query)
|
||||||
|
per_page = int(query["per_page"][0])
|
||||||
|
page = int(query["page"][0])
|
||||||
|
|
||||||
|
repo = fake_repos[tuple(project)]
|
||||||
|
first_entry = (page - 1) * per_page
|
||||||
|
last_entry = min(len(repo), (page) * per_page)
|
||||||
|
|
||||||
|
if first_entry >= len(repo):
|
||||||
|
branches = []
|
||||||
|
else:
|
||||||
|
branches = [{'name': repo[i].name,
|
||||||
|
'protected': repo[i].protected}
|
||||||
|
for i in range(first_entry, last_entry)]
|
||||||
|
self.send_data(branches)
|
||||||
|
|
||||||
|
def post_mr_notes(self, data, project, mr):
|
||||||
|
mr = self._get_mr(project, mr)
|
||||||
|
mr.addNote(data['body'][0])
|
||||||
|
self.send_data({})
|
||||||
|
|
||||||
|
def post_mr_approve(self, data, project, mr):
|
||||||
|
assert 'sha' in data
|
||||||
|
mr = self._get_mr(project, mr)
|
||||||
|
if data['sha'][0] != mr.sha:
|
||||||
|
return self.send_data(
|
||||||
|
{'message': 'SHA does not match HEAD of source '
|
||||||
|
'branch: <new_sha>'}, code=409)
|
||||||
|
mr.approved = True
|
||||||
|
self.send_data({})
|
||||||
|
|
||||||
|
def post_mr_unapprove(self, data, project, mr):
|
||||||
|
mr = self._get_mr(project, mr)
|
||||||
|
mr.approved = False
|
||||||
|
self.send_data({})
|
||||||
|
|
||||||
|
def put_mr_merge(self, data, project, mr):
|
||||||
|
mr = self._get_mr(project, mr)
|
||||||
|
mr.mergeMergeRequest()
|
||||||
|
self.send_data({'state': 'merged'})
|
||||||
|
|
||||||
|
def log_message(self, fmt, *args):
|
||||||
|
self.log.debug(fmt, *args)
|
||||||
|
|
||||||
|
self.httpd = socketserver.ThreadingTCPServer(('', 0), Server)
|
||||||
|
self.port = self.httpd.socket.getsockname()[1]
|
||||||
|
self.thread = threading.Thread(name='GitlabWebServer',
|
||||||
|
target=self.httpd.serve_forever)
|
||||||
|
self.thread.daemon = True
|
||||||
|
self.thread.start()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.httpd.shutdown()
|
||||||
|
self.thread.join()
|
|
@ -108,7 +108,8 @@ class TestGitlabDriver(ZuulTestCase):
|
||||||
self.assertEqual(str(A.number), zuulvars['change'])
|
self.assertEqual(str(A.number), zuulvars['change'])
|
||||||
self.assertEqual(str(A.sha), zuulvars['patchset'])
|
self.assertEqual(str(A.sha), zuulvars['patchset'])
|
||||||
self.assertEqual('master', zuulvars['branch'])
|
self.assertEqual('master', zuulvars['branch'])
|
||||||
self.assertEquals('https://gitlab/org/project/merge_requests/1',
|
self.assertEquals(f'{self.fake_gitlab._test_baseurl}/'
|
||||||
|
'org/project/merge_requests/1',
|
||||||
zuulvars['items'][0]['change_url'])
|
zuulvars['items'][0]['change_url'])
|
||||||
self.assertEqual(zuulvars["message"], strings.b64encode(description))
|
self.assertEqual(zuulvars["message"], strings.b64encode(description))
|
||||||
self.assertEqual(2, len(self.history))
|
self.assertEqual(2, len(self.history))
|
||||||
|
@ -282,7 +283,8 @@ class TestGitlabDriver(ZuulTestCase):
|
||||||
self.assertEqual('project-post-job', zuulvars['job'])
|
self.assertEqual('project-post-job', zuulvars['job'])
|
||||||
self.assertEqual('master', zuulvars['branch'])
|
self.assertEqual('master', zuulvars['branch'])
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'https://gitlab/org/project/tree/%s' % zuulvars['newrev'],
|
f'{self.fake_gitlab._test_baseurl}/org/project/tree/'
|
||||||
|
f'{zuulvars["newrev"]}',
|
||||||
zuulvars['change_url'])
|
zuulvars['change_url'])
|
||||||
self.assertEqual(expected_newrev, zuulvars['newrev'])
|
self.assertEqual(expected_newrev, zuulvars['newrev'])
|
||||||
self.assertEqual(expected_oldrev, zuulvars['oldrev'])
|
self.assertEqual(expected_oldrev, zuulvars['oldrev'])
|
||||||
|
@ -711,7 +713,8 @@ class TestGitlabDriver(ZuulTestCase):
|
||||||
project_git_url = self.fake_gitlab.real_getGitUrl(project)
|
project_git_url = self.fake_gitlab.real_getGitUrl(project)
|
||||||
# cloneurl created from config 'server' should be used
|
# cloneurl created from config 'server' should be used
|
||||||
# without credentials
|
# without credentials
|
||||||
self.assertEqual("https://gitlab/org/project1.git", project_git_url)
|
self.assertEqual(f"{self.fake_gitlab._test_baseurl}/org/project1.git",
|
||||||
|
project_git_url)
|
||||||
|
|
||||||
@simple_layout('layouts/crd-gitlab.yaml', driver='gitlab2')
|
@simple_layout('layouts/crd-gitlab.yaml', driver='gitlab2')
|
||||||
def test_api_token_cloneurl(self):
|
def test_api_token_cloneurl(self):
|
||||||
|
@ -743,7 +746,9 @@ class TestGitlabDriver(ZuulTestCase):
|
||||||
project_git_url = self.fake_gitlab4.real_getGitUrl(project)
|
project_git_url = self.fake_gitlab4.real_getGitUrl(project)
|
||||||
# cloneurl is not set, generate one from token name, token secret and
|
# cloneurl is not set, generate one from token name, token secret and
|
||||||
# server
|
# server
|
||||||
self.assertEqual("https://tokenname4:444@gitlabfour/org/project1.git",
|
self.assertEqual("http://tokenname4:444@localhost:"
|
||||||
|
f"{self.fake_gitlab4._test_web_server.port}"
|
||||||
|
"/org/project1.git",
|
||||||
project_git_url)
|
project_git_url)
|
||||||
|
|
||||||
@simple_layout('layouts/crd-gitlab.yaml', driver='gitlab5')
|
@simple_layout('layouts/crd-gitlab.yaml', driver='gitlab5')
|
||||||
|
|
Loading…
Reference in New Issue