UI and code improvements to make working with the multiple SCMs easier

This commit is contained in:
Joseph Schorr 2015-05-03 10:38:11 -07:00
parent f091aaa07e
commit d07f9f04e9
10 changed files with 70 additions and 114 deletions

View file

@ -48,14 +48,19 @@ def user_view(user):
def trigger_view(trigger, can_read=False, can_admin=False):
if trigger and trigger.uuid:
build_trigger = BuildTriggerHandler.get_handler(trigger)
build_source = build_trigger.config.get('build_source')
repo_url = build_trigger.get_repository_url() if build_source else None
return {
'service': trigger.service.name,
'build_source': build_trigger.config.get('build_source') if can_read else None,
'build_source': build_source if can_read else None,
'config': build_trigger.config if can_admin else {},
'id': trigger.uuid,
'connected_user': trigger.connected_user.username,
'is_active': build_trigger.is_active(),
'pull_robot': user_view(trigger.pull_robot) if trigger.pull_robot else None
'pull_robot': user_view(trigger.pull_robot) if trigger.pull_robot else None,
'repository_url': repo_url if can_read else None,
}
return None

View file

@ -367,8 +367,7 @@ class BuildTriggerAnalyze(RepositoryParamResource):
'name': base_repository,
'is_public': found_repository.visibility.name == 'public',
'robots': read_robots,
'status': 'analyzed',
'dockerfile_url': handler.dockerfile_url()
'status': 'analyzed'
}
except RepositoryReadException as rre:

View file

@ -120,12 +120,6 @@ class BuildTriggerHandler(object):
""" Returns the auth token for the trigger. """
return self.trigger.auth_token
def dockerfile_url(self):
"""
Returns the URL at which the Dockerfile for the trigger is found or None if none/not applicable.
"""
raise NotImplementedError
def load_dockerfile_contents(self):
"""
Loads the Dockerfile found for the trigger's config and returns them or None if none could
@ -188,6 +182,11 @@ class BuildTriggerHandler(object):
"""
raise NotImplementedError
def get_repository_url(self):
""" Returns the URL of the current trigger's repository. Note that this operation
can be called in a loop, so it should be as fast as possible. """
raise NotImplementedError
@classmethod
def service_name(cls):
"""
@ -212,6 +211,18 @@ class BuildTriggerHandler(object):
""" Sets the auth token for the trigger, saving it to the DB. """
model.update_build_trigger(self.trigger, self.config, auth_token=auth_token)
def get_dockerfile_path(self):
""" Returns the normalized path to the Dockerfile found in the subdirectory
in the config. """
subdirectory = self.config.get('subdir', '')
if subdirectory == '/':
subdirectory = ''
else:
if not subdirectory.endswith('/'):
subdirectory = subdirectory + '/'
return subdirectory + 'Dockerfile'
class BitbucketBuildTrigger(BuildTriggerHandler):
"""
@ -371,24 +382,9 @@ class BitbucketBuildTrigger(BuildTriggerHandler):
return []
def dockerfile_url(self):
repository = self._get_repository_client()
subdirectory = self.config.get('subdir', '')
path = subdirectory + '/Dockerfile' if subdirectory else 'Dockerfile'
master_branch = 'master'
(result, data, _) = repository.get_main_branch()
if result:
master_branch = data['name']
return 'https://bitbucket.org/%s/%s/src/%s/%s' % (repository.namespace,
repository.repository_name,
master_branch, path)
def load_dockerfile_contents(self):
repository = self._get_repository_client()
subdirectory = self.config.get('subdir', '/')[1:]
path = subdirectory + '/Dockerfile' if subdirectory else 'Dockerfile'
path = self.get_dockerfile_path()
(result, data, err_msg) = repository.get_raw_path_contents(path, revision='master')
if not result:
@ -539,6 +535,11 @@ class BitbucketBuildTrigger(BuildTriggerHandler):
return self._prepare_build(commit_sha, ref, True)
def get_repository_url(self):
source = self.config['build_source']
(namespace, name) = source.split('/')
return 'https://bitbucket.org/%s/%s' % (namespace, name)
class GithubBuildTrigger(BuildTriggerHandler):
"""
@ -696,30 +697,13 @@ class GithubBuildTrigger(BuildTriggerHandler):
raise RepositoryReadException(message)
def dockerfile_url(self):
config = self.config
source = config['build_source']
subdirectory = config.get('subdir', '')
path = subdirectory + '/Dockerfile' if subdirectory else 'Dockerfile'
gh_client = self._get_client()
try:
repo = gh_client.get_repo(source)
master_branch = repo.default_branch or 'master'
return 'https://github.com/%s/blob/%s/%s' % (source, master_branch, path)
except GithubException:
logger.exception('Could not load repository for Dockerfile.')
return None
def load_dockerfile_contents(self):
config = self.config
gh_client = self._get_client()
source = config['build_source']
subdirectory = config.get('subdir', '')
path = subdirectory + '/Dockerfile' if subdirectory else 'Dockerfile'
path = self.get_dockerfile_path()
try:
repo = gh_client.get_repo(source)
file_info = repo.get_file_contents(path)
@ -922,6 +906,12 @@ class GithubBuildTrigger(BuildTriggerHandler):
return None
def get_repository_url(self):
from app import github_trigger
source = self.config['build_source']
return github_trigger.get_public_url(source)
class CustomBuildTrigger(BuildTriggerHandler):
payload_schema = {
'type': 'object',
@ -1084,6 +1074,9 @@ class CustomBuildTrigger(BuildTriggerHandler):
self.config = config
return config
def get_repository_url(self):
return None
class GitLabBuildTrigger(BuildTriggerHandler):
"""
@ -1221,35 +1214,9 @@ class GitLabBuildTrigger(BuildTriggerHandler):
return []
def dockerfile_url(self):
gl_client = self._get_authorized_client()
subdir = self.config.get('subdir', '')
path = subdir + '/Dockerfile' if subdir else 'Dockerfile'
repository = gl_client.getproject(self.config['build_source'])
if repository is False:
return None
branches = self.list_field_values('branch_name')
branches = find_matching_branches(self.config, branches)
if branches == []:
return None
branch_name = branches[0]
if repository['default_branch'] in branches:
branch_name = repository['default_branch']
return '%s/%s/blob/%s/%s' % (gl_client.host,
repository['path_with_namespace'],
branch_name,
path)
def load_dockerfile_contents(self):
gl_client = self._get_authorized_client()
subdir = self.config.get('subdir', '')
if subdir == '/':
subdir = ''
path = subdir + 'Dockerfile' if subdir else 'Dockerfile'
path = self.get_dockerfile_path()
repository = gl_client.getproject(self.config['build_source'])
if repository is False:
@ -1394,3 +1361,12 @@ class GitLabBuildTrigger(BuildTriggerHandler):
ref = 'refs/heads/%s' % branch_name
return self._prepare_build(commit, ref, True)
def get_repository_url(self):
gl_client = self._get_authorized_client()
repository = gl_client.getproject(self.config['build_source'])
if repository is False:
return None
return '%s/%s' % (gl_client.host, repository['path_with_namespace'])

View file

@ -13,29 +13,17 @@
<div class="modal-body" ng-show="currentView != 'activating'">
<!-- Trigger-specific setup -->
<div class="trigger-description-element trigger-option-section" ng-switch on="trigger.service">
<div ng-switch-when="github">
<div class="trigger-setup-githost" repository="repository" trigger="trigger"
kind="github"
next-step-counter="nextStepCounter" current-step-valid="state.stepValid"
analyze="checkAnalyze(isValid)"></div>
</div>
<div ng-switch-when="bitbucket">
<div class="trigger-setup-githost" repository="repository" trigger="trigger"
kind="bitbucket"
next-step-counter="nextStepCounter" current-step-valid="state.stepValid"
analyze="checkAnalyze(isValid)"></div>
</div>
<div ng-switch-when="gitlab">
<div class="trigger-setup-githost" repository="repository" trigger="trigger"
kind="gitlab"
next-step-counter="nextStepCounter" current-step-valid="state.stepValid"
analyze="checkAnalyze(isValid)"></div>
</div>
<div ng-switch-when="custom-git">
<div class="trigger-setup-custom" repository="repository" trigger="trigger"
next-step-counter="nextStepCounter" current-step-valid="state.stepValid"
analyze="checkAnalyze(isValid)"></div>
</div>
<div ng-switch-default>
<div class="trigger-setup-githost" repository="repository" trigger="trigger"
kind="{{ trigger.service }}"
next-step-counter="nextStepCounter" current-step-valid="state.stepValid"
analyze="checkAnalyze(isValid)"></div>
</div>
</div>
<!-- Loading pull information -->
@ -57,14 +45,8 @@
</div>
<div class="dockerfile-found" ng-if="pullInfo.analysis.is_public === false">
<div class="dockerfile-found-content">
A robot account is <strong>required</strong> for this build trigger because
the
<a href="{{ pullInfo.analysis.dockerfile_url }}" ng-if="pullInfo.analysis.dockerfile_url" target="_blank">
Dockerfile found
</a>
<span ng-if="!pullInfo.analysis.dockerfile_url">Dockerfile found</span>
A robot account is <strong>required</strong> for this build trigger because the
Dockerfile found
pulls from the private <span class="registry-name"></span> repository
<a href="/repository/{{ pullInfo.analysis.namespace }}/{{ pullInfo.analysis.name }}" target="_blank">

View file

@ -1,7 +1,7 @@
<span>
<i class="fa fa-bitbucket fa-lg" style="margin-right: 6px" data-title="BitBucket" bs-tooltip="tooltip.title"></i>
Push to BitBucket repository
<a href="https://bitbucket.org/{{ trigger.config.build_source }}" target="_new">
<a href="{{ trigger.repository_url }}" target="_new">
{{ trigger.config.build_source }}
</a>
<div style="margin-top: 4px; margin-left: 26px; font-size: 12px; color: gray;" ng-if="!short">

View file

@ -1,7 +1,7 @@
<span>
<i class="fa fa-github fa-lg" style="margin-right: 6px" data-title="GitHub" bs-tooltip="tooltip.title"></i>
Push to GitHub <span ng-if="KeyService.isEnterprise('github-trigger')">Enterprise</span> repository
<a href="{{ KeyService['githubTriggerEndpoint'] }}{{ trigger.config.build_source }}" target="_new">
<a href="{{ trigger.repository_url }}" target="_new">
{{ trigger.config.build_source }}
</a>
<div style="margin-top: 4px; margin-left: 26px; font-size: 12px; color: gray;" ng-if="!short">

View file

@ -1,7 +1,7 @@
<span>
<i class="fa fa-git-square fa-lg" style="margin-right: 6px" data-title="GitLab" bs-tooltip="tooltip.title"></i>
Push to GitLab repository
<a href="https://gitlab.com/{{ trigger.config.build_source }}" target="_new">
<a ng-href="{{ trigger.repository_url }}" target="_new">
{{ trigger.config.build_source }}
</a>
<div style="margin-top: 4px; margin-left: 26px; font-size: 12px; color: gray;" ng-if="!short">

View file

@ -55,9 +55,6 @@ angular.module('quay').factory('TriggerService', ['UtilService', '$sanitize', 'K
'credentials': '/static/directives/trigger/githost/credentials.html',
'trigger-description': '/static/directives/trigger/github/trigger-description.html'
},
'repository_url': function(build) {
return KeyService['githubTriggerEndpoint'] + build.trigger.build_source;
},
'link_templates': {
'commit': '/commit/{sha}',
'branch': '/tree/{branch}',
@ -94,9 +91,6 @@ angular.module('quay').factory('TriggerService', ['UtilService', '$sanitize', 'K
'credentials': '/static/directives/trigger/githost/credentials.html',
'trigger-description': '/static/directives/trigger/bitbucket/trigger-description.html'
},
'repository_url': function(build) {
return 'https://bitbucket.org/' + build.trigger.build_source;
},
'link_templates': {
'commit': '/commits/{sha}',
'branch': '/branch/{branch}',
@ -137,9 +131,6 @@ angular.module('quay').factory('TriggerService', ['UtilService', '$sanitize', 'K
'credentials': '/static/directives/trigger/githost/credentials.html',
'trigger-description': '/static/directives/trigger/gitlab/trigger-description.html'
},
'repository_url': function(build) {
return 'https://bitbucket.org/' + build.trigger.build_source;
},
'link_templates': {
'commit': '/commit/{sha}',
'branch': '/tree/{branch}',
@ -191,8 +182,8 @@ angular.module('quay').factory('TriggerService', ['UtilService', '$sanitize', 'K
return null;
}
var repositoryUrl = type.repository_url;
if (!repositoryUrl || !repositoryUrl(build)) {
var repositoryUrl = build.trigger.repository_url;
if (!repositoryUrl) {
return null;
}
@ -201,7 +192,7 @@ angular.module('quay').factory('TriggerService', ['UtilService', '$sanitize', 'K
return null;
}
return repositoryUrl(build) + linkTemplate[templateName];
return repositoryUrl + linkTemplate[templateName];
};
triggerService.supportsFullListing = function(name) {

View file

@ -2478,8 +2478,8 @@ class FakeBuildTrigger(BuildTriggerHandler):
prepared.is_manual = True
return prepared
def dockerfile_url(self):
return 'http://some/url'
def get_repository_url(self):
return 'http://foo/' + self.config['build_source']
def load_dockerfile_contents(self):
if not 'dockerfile' in self.config:

View file

@ -78,6 +78,9 @@ class GithubOAuthConfig(OAuthConfig):
return [org.lower() for org in allowed]
def get_public_url(self, suffix):
return '%s%s' % (self._endpoint(), suffix)
def _endpoint(self):
endpoint = self.config.get('GITHUB_ENDPOINT', 'https://github.com')
if not endpoint.endswith('/'):