diff --git a/buildtrigger/gitlabhandler.py b/buildtrigger/gitlabhandler.py index f23b4a80a..7abedc2d0 100644 --- a/buildtrigger/gitlabhandler.py +++ b/buildtrigger/gitlabhandler.py @@ -307,23 +307,30 @@ class GitLabBuildTrigger(BuildTriggerHandler): @_catch_timeouts def list_build_sources_for_namespace(self, namespace): def repo_view(repo): - last_modified = dateutil.parser.parse(repo['last_activity_at']) - has_admin_permission = False + # Because *anything* can be None in GitLab API! + permissions = repo.get('permissions') or {} + project_access = permissions.get('project_access') or {} + access_level = project_access.get('access_level') or 0 + has_admin_permission = _ACCESS_LEVEL_MAP.get(access_level, ("", False))[1] - if repo.get('permissions'): - access_level = repo['permissions']['project_access']['access_level'] - has_admin_permission = _ACCESS_LEVEL_MAP.get(access_level, ("", False))[1] - - return { + view = { 'name': repo['path'], 'full_name': repo['path_with_namespace'], - 'description': repo['description'] or '', - 'last_updated': timegm(last_modified.utctimetuple()), - 'url': repo['web_url'], + 'description': repo.get('description') or '', + 'url': repo.get('web_url'), 'has_admin_permissions': has_admin_permission, - 'private': repo['public'] is False, + 'private': repo.get('public', False) is False, } + if repo.get('last_activity_at'): + try: + last_modified = dateutil.parser.parse(repo['last_activity_at']) + view['last_updated'] = timegm(last_modified.utctimetuple()) + except ValueError: + logger.exception('Gitlab gave us an invalid last_activity_at: %s', last_modified) + + return view + gl_client = self._get_authorized_client() repositories = _paginated_iterator(gl_client.getprojects, RepositoryReadException) repos = [repo_view(repo) for repo in repositories if repo['namespace']['path'] == namespace] diff --git a/buildtrigger/test/gitlabmock.py b/buildtrigger/test/gitlabmock.py index 2c9489ae6..c15f42a6b 100644 --- a/buildtrigger/test/gitlabmock.py +++ b/buildtrigger/test/gitlabmock.py @@ -27,6 +27,13 @@ def get_currentuser_mock(): } def project(namespace, name, is_org=False): + project_access = None + + if namespace == 'knownuser': + project_access = { + 'access_level': 50, + } + data = { 'id': '%s/%s' % (namespace, name), 'default_branch': 'master', @@ -43,9 +50,7 @@ def project(namespace, name, is_org=False): 'ssh_url_to_repo': 'git://%s/%s' % (namespace, name), 'public': name != 'somerepo', 'permissions': { - 'project_access': { - 'access_level': 50 if namespace == 'knownuser' else 0, - } + 'project_access': project_access, }, 'owner': { 'avatar_url': 'avatarurl',