Add schema validation of namespaces and sources methods

This commit is contained in:
Joseph Schorr 2017-02-13 18:04:41 -05:00
parent 57528aa2bc
commit e025d8c2b2
5 changed files with 96 additions and 9 deletions

View file

@ -6,6 +6,79 @@ from endpoints.building import PreparedBuild
from data import model
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 = {
'type': 'object',
'properties': {
@ -242,3 +315,14 @@ class BuildTriggerHandler(object):
prepared.tags = [commit_sha[:7]]
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

View file

@ -416,7 +416,7 @@ class BitbucketBuildTrigger(BuildTriggerHandler):
'score': 1,
}
return list(namespaces.values())
return BuildTriggerHandler.build_namespaces_response(namespaces)
def list_build_sources_for_namespace(self, namespace):
def repo_view(repo):
@ -437,7 +437,8 @@ class BitbucketBuildTrigger(BuildTriggerHandler):
if not result:
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):
config = self.config

View file

@ -300,7 +300,7 @@ class GithubBuildTrigger(BuildTriggerHandler):
'score': org.plan.private_repos if org.plan else 0,
}
return list(namespaces.values())
return BuildTriggerHandler.build_namespaces_response(namespaces)
@_catch_ssl_errors
def list_build_sources_for_namespace(self, namespace):
@ -318,7 +318,8 @@ class GithubBuildTrigger(BuildTriggerHandler):
gh_client = self._get_client()
usr = gh_client.get_user()
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:
org = gh_client.get_organization(namespace)
@ -327,7 +328,8 @@ class GithubBuildTrigger(BuildTriggerHandler):
except GithubException:
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

View file

@ -289,7 +289,7 @@ class GitLabBuildTrigger(BuildTriggerHandler):
'url': gl_client.host + '/' + namespace['path'],
}
return list(namespaces.values())
return BuildTriggerHandler.build_namespaces_response(namespaces)
@_catch_timeouts
def list_build_sources_for_namespace(self, namespace):
@ -313,7 +313,8 @@ class GitLabBuildTrigger(BuildTriggerHandler):
gl_client = self._get_authorized_client()
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
def list_build_subdirs(self):

View file

@ -108,12 +108,11 @@ def test_list_build_source_namespaces(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
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