Implement new create and manager trigger UI

Implements the new trigger setup user interface, which is now a linear workflow found on its own page, rather than a tiny modal dialog

Fixes #1187
This commit is contained in:
Joseph Schorr 2016-09-27 16:52:34 +02:00
parent 21b09a7451
commit 8e863b8cf5
47 changed files with 1835 additions and 1068 deletions

View file

@ -2,14 +2,15 @@ import logging
import os.path
import base64
from calendar import timegm
from functools import wraps
from ssl import SSLError
from github import (Github, UnknownObjectException, GithubException,
BadCredentialsException as GitHubBadCredentialsException)
from jsonschema import validate
from app import app, github_trigger
from buildtrigger.triggerutil import (RepositoryReadException, TriggerActivationException,
TriggerDeactivationException, TriggerStartException,
EmptyRepositoryException, ValidationRequestException,
@ -273,55 +274,57 @@ class GithubBuildTrigger(BuildTriggerHandler):
return config
@_catch_ssl_errors
def list_build_sources(self):
def list_build_source_namespaces(self):
gh_client = self._get_client()
usr = gh_client.get_user()
try:
repos = usr.get_repos()
except GithubException:
raise RepositoryReadException('Unable to list user repositories')
# Build the full set of namespaces for the user, starting with their own.
namespaces = {}
has_non_personal = False
namespaces[usr.login] = {
'personal': True,
'id': usr.login,
'title': usr.name or usr.login,
'avatar_url': usr.avatar_url,
'score': usr.plan.private_repos if usr.plan else 0,
}
for repository in repos:
namespace = repository.owner.login
if not namespace in namespaces:
is_personal_repo = namespace == usr.login
namespaces[namespace] = {
'personal': is_personal_repo,
'repos': [],
'info': {
'name': namespace,
'avatar_url': repository.owner.avatar_url
}
}
for org in usr.get_orgs():
namespaces[org.name] = {
'personal': False,
'id': org.login,
'title': org.name or org.login,
'avatar_url': org.avatar_url,
'url': org.html_url,
'score': org.plan.private_repos if org.plan else 0,
}
if not is_personal_repo:
has_non_personal = True
return list(namespaces.values())
namespaces[namespace]['repos'].append(repository.full_name)
@_catch_ssl_errors
def list_build_sources_for_namespace(self, namespace):
def repo_view(repo):
return {
'name': repo.name,
'full_name': repo.full_name,
'description': repo.description or '',
'last_updated': timegm(repo.pushed_at.utctimetuple()),
'url': repo.html_url,
'has_admin_permissions': repo.permissions.admin,
'private': repo.private,
}
# In older versions of GitHub Enterprise, the get_repos call above does not
# return any non-personal repositories. In that case, we need to lookup the
# repositories manually.
# TODO: Remove this once we no longer support GHE versions <= 2.1
if not has_non_personal:
for org in usr.get_orgs():
repo_list = [repo.full_name for repo in org.get_repos(type='member')]
namespaces[org.name] = {
'personal': False,
'repos': repo_list,
'info': {
'name': org.name or org.login,
'avatar_url': org.avatar_url
}
}
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]
org = gh_client.get_organization(namespace)
if org is None:
return []
return [repo_view(repo) for repo in org.get_repos(type='member')]
entries = list(namespaces.values())
entries.sort(key=lambda e: e['info']['name'])
return entries
@_catch_ssl_errors
def list_build_subdirs(self):
@ -357,19 +360,17 @@ class GithubBuildTrigger(BuildTriggerHandler):
source = config['build_source']
path = self.get_dockerfile_path()
try:
repo = gh_client.get_repo(source)
file_info = repo.get_file_contents(path)
if file_info is None:
return None
content = file_info.content
if file_info.encoding == 'base64':
content = base64.b64decode(content)
return content
except GithubException as ghe:
message = ghe.data.get('message', 'Unable to read Dockerfile: %s' % source)
raise RepositoryReadException(message)
return None
if file_info is None:
return None
content = file_info.content
if file_info.encoding == 'base64':
content = base64.b64decode(content)
return content
@_catch_ssl_errors
def list_field_values(self, field_name, limit=None):
@ -535,7 +536,7 @@ class GithubBuildTrigger(BuildTriggerHandler):
logger.debug('GitHub trigger payload %s', payload)
metadata = get_transformed_webhook_payload(payload, default_branch=default_branch,
lookup_user=lookup_user)
lookup_user=lookup_user)
prepared = self.prepare_build(metadata)
# Check if we should skip this build.