Add schema validation of namespaces and sources methods
This commit is contained in:
parent
57528aa2bc
commit
e025d8c2b2
5 changed files with 96 additions and 9 deletions
|
@ -6,6 +6,79 @@ from endpoints.building import PreparedBuild
|
||||||
from data import model
|
from data import model
|
||||||
from buildtrigger.triggerutil import get_trigger_config, InvalidServiceException
|
from buildtrigger.triggerutil import get_trigger_config, InvalidServiceException
|
||||||
|
|
||||||
|
NAMESPACES_SCHEMA = {
|
||||||
|
'type': 'array',
|
||||||
|
'items': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'personal': {
|
||||||
|
'type': 'boolean',
|
||||||
|
'description': 'True if the namespace is the user\'s personal namespace',
|
||||||
|
},
|
||||||
|
'score': {
|
||||||
|
'type': 'number',
|
||||||
|
'description': 'Score of the relevance of the namespace',
|
||||||
|
},
|
||||||
|
'avatar_url': {
|
||||||
|
'type': 'string',
|
||||||
|
'description': 'URL of the avatar for this namespace',
|
||||||
|
},
|
||||||
|
'url': {
|
||||||
|
'type': 'string',
|
||||||
|
'description': 'URL of the website to view the namespace',
|
||||||
|
},
|
||||||
|
'id': {
|
||||||
|
'type': 'string',
|
||||||
|
'description': 'Trigger-internal ID of the namespace',
|
||||||
|
},
|
||||||
|
'title': {
|
||||||
|
'type': 'string',
|
||||||
|
'description': 'Human-readable title of the namespace',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'required': ['personal', 'score', 'avatar_url', 'url', 'id', 'title'],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
BUILD_SOURCES_SCHEMA = {
|
||||||
|
'type': 'array',
|
||||||
|
'items': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'name': {
|
||||||
|
'type': 'string',
|
||||||
|
'description': 'The name of the repository, without its namespace',
|
||||||
|
},
|
||||||
|
'full_name': {
|
||||||
|
'type': 'string',
|
||||||
|
'description': 'The name of the repository, with its namespace',
|
||||||
|
},
|
||||||
|
'description': {
|
||||||
|
'type': 'string',
|
||||||
|
'description': 'The description of the repository. May be an empty string',
|
||||||
|
},
|
||||||
|
'last_updated': {
|
||||||
|
'type': 'number',
|
||||||
|
'description': 'The date/time when the repository was last updated, since epoch in UTC',
|
||||||
|
},
|
||||||
|
'url': {
|
||||||
|
'type': 'string',
|
||||||
|
'description': 'The URL at which to view the repository in the browser',
|
||||||
|
},
|
||||||
|
'has_admin_permissions': {
|
||||||
|
'type': 'boolean',
|
||||||
|
'description': 'True if the current user has admin permissions on the repository',
|
||||||
|
},
|
||||||
|
'private': {
|
||||||
|
'type': 'boolean',
|
||||||
|
'description': 'True if the repository is private',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'required': ['name', 'full_name', 'description', 'last_updated', 'url',
|
||||||
|
'has_admin_permissions', 'private'],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
METADATA_SCHEMA = {
|
METADATA_SCHEMA = {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'properties': {
|
'properties': {
|
||||||
|
@ -242,3 +315,14 @@ class BuildTriggerHandler(object):
|
||||||
prepared.tags = [commit_sha[:7]]
|
prepared.tags = [commit_sha[:7]]
|
||||||
|
|
||||||
return prepared
|
return prepared
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def build_sources_response(cls, sources):
|
||||||
|
validate(sources, BUILD_SOURCES_SCHEMA)
|
||||||
|
return sources
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def build_namespaces_response(cls, namespaces_dict):
|
||||||
|
namespaces = list(namespaces_dict.values())
|
||||||
|
validate(namespaces, NAMESPACES_SCHEMA)
|
||||||
|
return namespaces
|
||||||
|
|
|
@ -416,7 +416,7 @@ class BitbucketBuildTrigger(BuildTriggerHandler):
|
||||||
'score': 1,
|
'score': 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
return list(namespaces.values())
|
return BuildTriggerHandler.build_namespaces_response(namespaces)
|
||||||
|
|
||||||
def list_build_sources_for_namespace(self, namespace):
|
def list_build_sources_for_namespace(self, namespace):
|
||||||
def repo_view(repo):
|
def repo_view(repo):
|
||||||
|
@ -437,7 +437,8 @@ class BitbucketBuildTrigger(BuildTriggerHandler):
|
||||||
if not result:
|
if not result:
|
||||||
raise RepositoryReadException('Could not read repository list: ' + err_msg)
|
raise RepositoryReadException('Could not read repository list: ' + err_msg)
|
||||||
|
|
||||||
return [repo_view(repo) for repo in data if repo['owner'] == namespace]
|
repos = [repo_view(repo) for repo in data if repo['owner'] == namespace]
|
||||||
|
return BuildTriggerHandler.build_sources_response(repos)
|
||||||
|
|
||||||
def list_build_subdirs(self):
|
def list_build_subdirs(self):
|
||||||
config = self.config
|
config = self.config
|
||||||
|
|
|
@ -300,7 +300,7 @@ class GithubBuildTrigger(BuildTriggerHandler):
|
||||||
'score': org.plan.private_repos if org.plan else 0,
|
'score': org.plan.private_repos if org.plan else 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
return list(namespaces.values())
|
return BuildTriggerHandler.build_namespaces_response(namespaces)
|
||||||
|
|
||||||
@_catch_ssl_errors
|
@_catch_ssl_errors
|
||||||
def list_build_sources_for_namespace(self, namespace):
|
def list_build_sources_for_namespace(self, namespace):
|
||||||
|
@ -318,7 +318,8 @@ class GithubBuildTrigger(BuildTriggerHandler):
|
||||||
gh_client = self._get_client()
|
gh_client = self._get_client()
|
||||||
usr = gh_client.get_user()
|
usr = gh_client.get_user()
|
||||||
if namespace == usr.login:
|
if namespace == usr.login:
|
||||||
return [repo_view(repo) for repo in usr.get_repos() if repo.owner.login == namespace]
|
repos = [repo_view(repo) for repo in usr.get_repos() if repo.owner.login == namespace]
|
||||||
|
return BuildTriggerHandler.build_sources_response(repos)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
org = gh_client.get_organization(namespace)
|
org = gh_client.get_organization(namespace)
|
||||||
|
@ -327,7 +328,8 @@ class GithubBuildTrigger(BuildTriggerHandler):
|
||||||
except GithubException:
|
except GithubException:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
return [repo_view(repo) for repo in org.get_repos(type='member')]
|
repos = [repo_view(repo) for repo in org.get_repos(type='member')]
|
||||||
|
return BuildTriggerHandler.build_sources_response(repos)
|
||||||
|
|
||||||
|
|
||||||
@_catch_ssl_errors
|
@_catch_ssl_errors
|
||||||
|
|
|
@ -289,7 +289,7 @@ class GitLabBuildTrigger(BuildTriggerHandler):
|
||||||
'url': gl_client.host + '/' + namespace['path'],
|
'url': gl_client.host + '/' + namespace['path'],
|
||||||
}
|
}
|
||||||
|
|
||||||
return list(namespaces.values())
|
return BuildTriggerHandler.build_namespaces_response(namespaces)
|
||||||
|
|
||||||
@_catch_timeouts
|
@_catch_timeouts
|
||||||
def list_build_sources_for_namespace(self, namespace):
|
def list_build_sources_for_namespace(self, namespace):
|
||||||
|
@ -313,7 +313,8 @@ class GitLabBuildTrigger(BuildTriggerHandler):
|
||||||
|
|
||||||
gl_client = self._get_authorized_client()
|
gl_client = self._get_authorized_client()
|
||||||
repositories = _paginated_iterator(gl_client.getprojects, RepositoryReadException)
|
repositories = _paginated_iterator(gl_client.getprojects, RepositoryReadException)
|
||||||
return [repo_view(repo) for repo in repositories if repo['namespace']['path'] == namespace]
|
repos = [repo_view(repo) for repo in repositories if repo['namespace']['path'] == namespace]
|
||||||
|
return BuildTriggerHandler.build_sources_response(repos)
|
||||||
|
|
||||||
@_catch_timeouts
|
@_catch_timeouts
|
||||||
def list_build_subdirs(self):
|
def list_build_subdirs(self):
|
||||||
|
|
|
@ -108,12 +108,11 @@ def test_list_build_source_namespaces(githost_trigger):
|
||||||
}]),
|
}]),
|
||||||
])
|
])
|
||||||
def test_list_build_sources_for_namespace(namespace, expected, githost_trigger):
|
def test_list_build_sources_for_namespace(namespace, expected, githost_trigger):
|
||||||
# TODO: schema validation on the resulting namespaces.
|
|
||||||
assert githost_trigger.list_build_sources_for_namespace(namespace) == expected
|
assert githost_trigger.list_build_sources_for_namespace(namespace) == expected
|
||||||
|
|
||||||
|
|
||||||
def test_activate(githost_trigger):
|
def test_activate(githost_trigger):
|
||||||
config, private_key = githost_trigger.activate('http://some/url')
|
_, private_key = githost_trigger.activate('http://some/url')
|
||||||
assert 'private_key' in private_key
|
assert 'private_key' in private_key
|
||||||
|
|
||||||
|
|
||||||
|
|
Reference in a new issue