diff --git a/endpoints/api/build.py b/endpoints/api/build.py index f67939576..92745c089 100644 --- a/endpoints/api/build.py +++ b/endpoints/api/build.py @@ -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 diff --git a/endpoints/api/trigger.py b/endpoints/api/trigger.py index 35dc6b9e9..8706ccf31 100644 --- a/endpoints/api/trigger.py +++ b/endpoints/api/trigger.py @@ -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: diff --git a/endpoints/trigger.py b/endpoints/trigger.py index b1145bc7d..26aa2c1e4 100644 --- a/endpoints/trigger.py +++ b/endpoints/trigger.py @@ -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']) + diff --git a/static/directives/setup-trigger-dialog.html b/static/directives/setup-trigger-dialog.html index 35d32de5d..cbed15bd8 100644 --- a/static/directives/setup-trigger-dialog.html +++ b/static/directives/setup-trigger-dialog.html @@ -13,29 +13,17 @@
- A robot account is required for this build trigger because - - the - - Dockerfile found - - Dockerfile found - + A robot account is required for this build trigger because the + Dockerfile found pulls from the private repository diff --git a/static/directives/trigger/bitbucket/trigger-description.html b/static/directives/trigger/bitbucket/trigger-description.html index 992fd14ac..997ae746b 100644 --- a/static/directives/trigger/bitbucket/trigger-description.html +++ b/static/directives/trigger/bitbucket/trigger-description.html @@ -1,7 +1,7 @@ Push to BitBucket repository - + {{ trigger.config.build_source }}
diff --git a/static/directives/trigger/github/trigger-description.html b/static/directives/trigger/github/trigger-description.html index 0309d5f4f..668a03785 100644 --- a/static/directives/trigger/github/trigger-description.html +++ b/static/directives/trigger/github/trigger-description.html @@ -1,7 +1,7 @@ Push to GitHub Enterprise repository - + {{ trigger.config.build_source }}
diff --git a/static/directives/trigger/gitlab/trigger-description.html b/static/directives/trigger/gitlab/trigger-description.html index fd93d6a81..930fcd0c7 100644 --- a/static/directives/trigger/gitlab/trigger-description.html +++ b/static/directives/trigger/gitlab/trigger-description.html @@ -1,7 +1,7 @@ Push to GitLab repository - + {{ trigger.config.build_source }}
diff --git a/static/js/services/trigger-service.js b/static/js/services/trigger-service.js index 564c7f321..69d01c386 100644 --- a/static/js/services/trigger-service.js +++ b/static/js/services/trigger-service.js @@ -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) { diff --git a/test/test_api_usage.py b/test/test_api_usage.py index ed64f5f87..19d1b7e4a 100644 --- a/test/test_api_usage.py +++ b/test/test_api_usage.py @@ -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: diff --git a/util/oauth.py b/util/oauth.py index a9a571eae..dfae97a2f 100644 --- a/util/oauth.py +++ b/util/oauth.py @@ -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('/'):