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:
parent
21b09a7451
commit
8e863b8cf5
47 changed files with 1835 additions and 1068 deletions
|
@ -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.
|
||||
|
|
Reference in a new issue