almost all PR discussion fixes

This commit is contained in:
Jimmy Zelinskie 2015-04-21 18:04:25 -04:00
parent d25cc4db9c
commit 02498d72ba
13 changed files with 200 additions and 148 deletions

View file

@ -93,10 +93,6 @@ class BuildComponent(BaseComponent):
self._build_failure('Could not load build job information', irbe)
base_image_information = {}
buildpack_url = ""
if build_job.repo_build.resource_key is not None:
buildpack_url = self.user_files.get_file_url(build_job.repo_build.resource_key,
requires_cors=False)
# Add the pull robot information, if any.
if build_job.pull_credentials:
@ -109,6 +105,7 @@ class BuildComponent(BaseComponent):
# Parse the build queue item into build arguments.
# build_package: URL to the build package to download and untar/unzip.
# defaults to empty string to avoid requiring a pointer on the builder.
# sub_directory: The location within the build package of the Dockerfile and the build context.
# repository: The repository for which this build is occurring.
# registry: The registry for which this build is occuring (e.g. 'quay.io', 'staging.quay.io').
@ -121,14 +118,16 @@ class BuildComponent(BaseComponent):
# username: The username for pulling the base image (if any).
# password: The password for pulling the base image (if any).
build_arguments = {
'build_package': buildpack_url,
'sub_directory': build_config.get('build_subdir', ''),
'repository': repository_name,
'registry': self.registry_hostname,
'pull_token': build_job.repo_build.access_token.code,
'push_token': build_job.repo_build.access_token.code,
'tag_names': build_config.get('docker_tags', ['latest']),
'base_image': base_image_information,
'build_package': self.user_files.get_file_url(build_job.repo_build.resource_key,
requires_cors=False)
if build_job.repo_build.resource_key is not None else "",
'sub_directory': build_config.get('build_subdir', ''),
'repository': repository_name,
'registry': self.registry_hostname,
'pull_token': build_job.repo_build.access_token.code,
'push_token': build_job.repo_build.access_token.code,
'tag_names': build_config.get('docker_tags', ['latest']),
'base_image': base_image_information,
}
# If the trigger has a private key, it's using git, thus we should add
@ -138,8 +137,8 @@ class BuildComponent(BaseComponent):
# private_key: the key used to get read access to the git repository
if build_job.repo_build.trigger.private_key is not None:
build_arguments['git'] = {
'url': build_config['trigger_metadata']['git_url'],
'sha': build_config['trigger_metadata']['commit_sha'],
'url': build_config['trigger_metadata'].get('git_url', ''),
'sha': build_config['trigger_metadata'].get('commit_sha', ''),
'private_key': build_job.repo_build.trigger.private_key,
}

View file

@ -190,7 +190,8 @@ class GithubBuildTrigger(BuildTrigger):
# Add a deploy key to the GitHub repository.
try:
config['public_key'], private_key = generate_ssh_keypair()
deploy_key = gh_repo.create_key('Quay.io Builder', config['public_key'])
deploy_key = gh_repo.create_key('%s Builder' % app.config['REGISTRY_TITLE'],
config['public_key'])
config['deploy_key_id'] = deploy_key.id
except GithubException:
msg = 'Unable to add deploy key to repository: %s' % new_build_source
@ -224,13 +225,16 @@ class GithubBuildTrigger(BuildTrigger):
raise TriggerDeactivationException(msg)
# If the trigger uses a deploy key, remove it.
if config['deploy_key_id']:
try:
try:
if config['deploy_key_id']:
deploy_key = repo.get_key(config['deploy_key_id'])
deploy_key.delete()
except GithubException:
msg = 'Unable to remove deploy key: %s' % config['deploy_key_id']
raise TriggerDeactivationException(msg)
except KeyError:
# There was no config['deploy_key_id'], thus this is an old trigger without a deploy key.
pass
except GithubException:
msg = 'Unable to remove deploy key: %s' % config['deploy_key_id']
raise TriggerDeactivationException(msg)
# Remove the webhook.
try:
@ -329,6 +333,7 @@ class GithubBuildTrigger(BuildTrigger):
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, auth_token, config):
@ -383,42 +388,56 @@ class GithubBuildTrigger(BuildTrigger):
return commit_info
@staticmethod
def _prepare_tarball(repo, commit_sha):
# Prepare the download and upload URLs
archive_link = repo.get_archive_link('tarball', commit_sha)
download_archive = client.get(archive_link, stream=True)
tarball_subdir = ''
with SpooledTemporaryFile(CHUNK_SIZE) as tarball:
for chunk in download_archive.iter_content(CHUNK_SIZE):
tarball.write(chunk)
# Seek to position 0 to make tarfile happy
tarball.seek(0)
# Pull out the name of the subdir that GitHub generated
with tarfile.open(fileobj=tarball) as archive:
tarball_subdir = archive.getnames()[0]
# Seek to position 0 to make tarfile happy.
tarball.seek(0)
entries = {
tarball_subdir + '/.git/HEAD': commit_sha,
tarball_subdir + '/.git/objects/': None,
tarball_subdir + '/.git/refs/': None
}
appender = TarfileAppender(tarball, entries).get_stream()
dockerfile_id = user_files.store_file(appender, TARBALL_MIME)
logger.debug('Successfully prepared job')
return tarball_subdir, dockerfile_id
@staticmethod
def _prepare_build(trigger, config, repo, commit_sha, build_name, ref, git_url):
# If the trigger isn't using git, prepare the buildpack.
repo_subdir = config['subdir']
joined_subdir = repo_subdir
dockerfile_id = None
if trigger.private_key is None:
# Prepare the download and upload URLs
archive_link = repo.get_archive_link('tarball', commit_sha)
download_archive = client.get(archive_link, stream=True)
tarball_subdir = ''
with SpooledTemporaryFile(CHUNK_SIZE) as tarball:
for chunk in download_archive.iter_content(CHUNK_SIZE):
tarball.write(chunk)
# Seek to position 0 to make tarfile happy
tarball.seek(0)
# Pull out the name of the subdir that GitHub generated
with tarfile.open(fileobj=tarball) as archive:
tarball_subdir = archive.getnames()[0]
# Seek to position 0 to make tarfile happy.
tarball.seek(0)
entries = {
tarball_subdir + '/.git/HEAD': commit_sha,
tarball_subdir + '/.git/objects/': None,
tarball_subdir + '/.git/refs/': None
}
appender = TarfileAppender(tarball, entries).get_stream()
dockerfile_id = user_files.store_file(appender, TARBALL_MIME)
# If the trigger isn't using git, prepare the buildpack.
tarball_subdir, dockerfile_id = GithubBuildTrigger._prepare_tarball(repo, commit_sha)
logger.debug('Successfully prepared job')
else:
dockerfile_id = None
# Join provided subdir with the tarball subdir.
joined_subdir = os.path.join(tarball_subdir, repo_subdir)
logger.debug('Final subdir: %s', joined_subdir)
# compute the tag(s)
branch = ref.split('/')[-1]
@ -429,14 +448,6 @@ class GithubBuildTrigger(BuildTrigger):
logger.debug('Pushing to tags: %s', tags)
# compute the subdir
repo_subdir = config['subdir']
if trigger.private_key is None:
joined_subdir = os.path.join(tarball_subdir, repo_subdir)
else:
joined_subdir = repo_subdir
logger.debug('Final subdir: %s', joined_subdir)
# compute the metadata
metadata = {
'commit_sha': commit_sha,
@ -551,30 +562,70 @@ class CustomBuildTrigger(BuildTrigger):
payload_schema = {
'type': 'object',
'properties': {
'commits': {'type': 'string'},
'ref': {'type': 'string'},
'default_branch': {'type': 'string'},
'commit': {
'type': 'string',
'description': 'SHA-1 identifier for a git commit',
},
'ref': {
'type': 'string',
'description': 'git reference for a git commit',
'pattern': '^refs\/(heads|tags|remotes)\/(.+)$',
},
'default_branch': {
'type': 'string',
'description': 'default branch of the git repository',
},
'commit_info': {
'type': 'object',
'description': 'metadata about a git commit',
'properties': {
'url': {'type': 'string'},
'message': {'type': 'string'},
'date': {'type': 'string'},
'url': {
'type': 'string',
'description': 'URL to view a git commit',
},
'message': {
'type': 'string',
'description': 'git commit message',
},
'date': {
'type': 'string',
'description': 'timestamp for a git commit'
},
'author': {
'type': 'object',
'description': 'metadata about the author of a git commit',
'properties': {
'username': {'type': 'string'},
'url': {'type': 'string'},
'avatar_url': {'type': 'string'},
'username': {
'type': 'string',
'description': 'username of the author',
},
'url': {
'type': 'string',
'description': 'URL to view the profile of the author',
},
'avatar_url': {
'type': 'string',
'description': 'URL to view the avatar of the author',
},
},
'required': ['username', 'url', 'avatar_url'],
},
'committer': {
'type': 'object',
'description': 'metadata about the committer of a git commit',
'properties': {
'username': {'type': 'string'},
'url': {'type': 'string'},
'avatar_url': {'type': 'string'},
'username': {
'type': 'string',
'description': 'username of the committer',
},
'url': {
'type': 'string',
'description': 'URL to view the profile of the committer',
},
'avatar_url': {
'type': 'string',
'description': 'URL to view the avatar of the committer',
},
},
'required': ['username', 'url', 'avatar_url'],
},
@ -587,7 +638,7 @@ class CustomBuildTrigger(BuildTrigger):
@classmethod
def service_name(cls):
return 'custom'
return 'custom-git'
def is_active(self, config):
return 'public_key' in config
@ -630,9 +681,9 @@ class CustomBuildTrigger(BuildTrigger):
return config
def manual_start(self, trigger, run_parameters=None):
for parameter in ['commit_sha']:
if parameter not in run_parameters:
raise TriggerStartException('missing required parameter')
# commit_sha is the only required parameter
if 'commit_sha' not in run_parameters:
raise TriggerStartException('missing required parameter')
config = get_trigger_config(trigger)
dockerfile_id = None

View file

@ -20,6 +20,7 @@ from util.cache import no_cache
from endpoints.common import common_login, render_page_template, route_show_if, param_required
from endpoints.csrf import csrf_protect, generate_csrf_token, verify_csrf
from endpoints.registry import set_cache_headers
from endpoints.trigger import CustomBuildTrigger
from util.names import parse_repository_name, parse_repository_name_and_tag
from util.useremails import send_email_changed
from util.systemlogs import build_logs_archive
@ -505,7 +506,8 @@ def attach_custom_build_trigger(namespace, repository_name):
msg = 'Invalid repository: %s/%s' % (namespace, repository_name)
abort(404, message=msg)
trigger = model.create_build_trigger(repo, 'custom', None, current_user.db_user())
trigger = model.create_build_trigger(repo, CustomBuildTrigger.service_name(),
None, current_user.db_user())
repo_path = '%s/%s' % (namespace, repository_name)
full_url = '%s%s%s' % (url_for('web.repository', path=repo_path), '?tab=builds&newtrigger=',

View file

@ -203,7 +203,7 @@ def initialize_database():
LoginService.create(name='ldap')
BuildTriggerService.create(name='github')
BuildTriggerService.create(name='custom')
BuildTriggerService.create(name='custom-git')
AccessTokenKind.create(name='build-worker')
AccessTokenKind.create(name='pushpull-token')

View file

@ -91,7 +91,7 @@
</button>
<ul class="dropdown-menu dropdown-menu-right pull-right">
<li ng-repeat="type in TriggerService.getTypes()">
<a href="{{ TriggerService.getRedirectUrl(type, repository.namespace, repository.name) }}" target="{{ TriggerService.getMetadata(type).target }}">
<a href="{{ TriggerService.getRedirectUrl(type, repository.namespace, repository.name) }}" target="{{ TriggerService.getMetadata(type).is_external ? '' : '_self' }}">
<i class="fa fa-lg" ng-class="TriggerService.getMetadata(type).icon"></i>
{{ TriggerService.getTitle(type) }}
</a>
@ -140,7 +140,7 @@
</td>
<td>
<span class="cor-options-menu">
<span class="cor-option" option-click="showTriggerCredentialsModal(trigger)" ng-show="trigger.service == 'custom'">
<span class="cor-option" option-click="showTriggerCredentialsModal(trigger)" ng-show="trigger.service == 'custom-git'">
<i class="fa fa-unlock-alt"></i> View Credentials
</span>
<span class="cor-option" option-click="askRunTrigger(trigger)"

View file

@ -19,7 +19,7 @@
next-step-counter="nextStepCounter" current-step-valid="state.stepValid"
analyze="checkAnalyze(isValid)"></div>
</div>
<div ng-switch-when="custom">
<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>
@ -35,6 +35,7 @@
<div class="trigger-option-section" ng-show="currentView == 'analyzed'">
<!-- Messaging -->
<!-- TODO(jschorr): eventually ng-switch on pullINfo.analysis.status -->
<div class="alert alert-danger" ng-if="pullInfo.analysis.status == 'error'">
{{ pullInfo.analysis.message }}
</div>
@ -113,7 +114,7 @@
</div>
<div class="trigger-option-section" ng-show="currentView == 'postActivation'" ng-switch on="trigger.service">
<div ng-switch-when="custom">
<div ng-switch-when="custom-git">
<div class="alert alert-warning">
The trigger has been successfully created, but the following first requires action:
<ul>

View file

@ -1,4 +1,5 @@
<span class="trigger-description-element" ng-switch on="trigger.service">
<!-- GitHub -->
<span ng-switch-when="github">
<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
@ -14,22 +15,24 @@
<div>
<span class="trigger-description-subtitle">Dockerfile:</span>
<span ng-if="trigger.config.subdir">//{{ TriggerService.trimSubdir(trigger.config.subdir) }}/Dockerfile</span>
<span ng-if="!trigger.config.subdir">//Dockerfile</span>
<span>{{ TriggerService.getDockerfileLocation(trigger) }}</span>
</div>
</div>
</span>
<span ng-switch-when="custom">
<!-- Git -->
<span ng-switch-when="custom-git">
<i class="fa fa-git fa-lg" style="margin-right: 6px;" data-title="git" bs-tooltip="tooltip.title"></i>
Push to {{ trigger.config.build_source }}
<div style="margin-top: 4px; margin-left: 26px; font-size: 12px; color: gray;" ng-if="!short">
<div>
<span class="trigger-description-subtitle">Dockerfile:</span>
<span ng-if="trigger.config.subdir">//{{ TriggerService.trimSubdir(trigger.config.subdir) }}/Dockerfile</span>
<span ng-if="!trigger.config.subdir">//Dockerfile</span>
<span>{{ TriggerService.getDockerfileLocation(trigger) }}</span<
</div>
</div>
</span>
<!-- Who knows? -->
<span ng-switch-default>
Unknown
</span>

View file

@ -18,9 +18,10 @@
<!-- Step view -->
<div class="step-view" next-step-counter="nextStepCounter" current-step-valid="currentStepValid"
steps-completed="stepsCompleted()">
steps-completed="stepsCompleted()">
<!-- Git URL Input -->
<!-- TODO(jschorr): make nopLoad(callback) no longer required -->
<div class="step-view-step" complete-condition="trigger['config']['build_source']" load-callback="nopLoad(callback)"
load-message="Loading Git URL Input">
<div style="margin-bottom: 12px;">Please enter an HTTP or SSH style URL used to clone your git repository:</div>

View file

@ -1,18 +1,17 @@
<div class="triggered-build-description-element">
<span class="tbd-content" class="manual" ng-if="!build.trigger && !build.job_config.manual_user">
(Manually Triggered Build)
</span>
<span class="tbd-content" class="manual" ng-if="!build.trigger && !build.job_config.manual_user">
(Manually Triggered Build)
</span>
<span class="tbd-content" ng-if="!build.trigger && build.job_config.manual_user">
<i class="fa fa-user"></i> {{ build.job_config.manual_user }}
</span>
<span class="tbd-content" ng-if="!build.trigger && build.job_config.manual_user">
<i class="fa fa-user"></i> {{ build.job_config.manual_user }}
</span>
<span ng-switch on="build.trigger.service" ng-if="build.trigger">
<!-- GitHub -->
<span ng-switch-when="github">
<!-- Full Commit Information -->
<span class="tbd-content" ng-if="build.job_config.trigger_metadata.commit_info">
<!-- Full Commit Information -->
<span class="tbd-content" ng-if="build.job_config.trigger_metadata.commit_info" ng-switch on="build.trigger.service">
<!-- GitHub -->
<div ng-switch-when="github">
<div class="commit-message">
<a ng-href="{{ getGitHubRepoURL(build) }}/commit/{{ build.job_config.trigger_metadata.commit_sha }}"
target="_blank">
@ -39,30 +38,10 @@
branch-template="getGitHubRepoURL(build) + '/tree/{branch}'"
tag-template="getGitHubRepoURL(build) + '/releases/tag/{tag}'"></span>
</div>
</span>
</div>
<!-- Just commit SHA -->
<span class="tbd-content" ng-if="build.job_config.trigger_metadata && !build.job_config.trigger_metadata.commit_info">
Triggered by commit
<span class="source-commit-link"
commit-sha="build.job_config.trigger_metadata.commit_sha"
url-template="getGitHubRepoURL(build) + '/commit/{sha}'"></span>
</span>
<!-- No information -->
<span class="tbd-content" ng-if="!build.job_config.trigger_metadata">
Triggered by commit to
<i class="fa fa-github fa-lg" data-title="GitHub" data-container="body" bs-tooltip></i>
<a ng-href="{{ getGitHubRepoURL(build) }}" target="_new">
{{ build.trigger.config.build_source }}
</a>
</span>
</span>
<!-- Custom -->
<span ng-switch-when="custom">
<!-- Full Commit Information -->
<span ng-if="build.job_config.trigger_metadata.commit_info">
<!-- Git -->
<div ng-switch-when="custom-git">
<div class="commit-message">
{{ build.job_config.trigger_metadata.commit_info.message }}
</div>
@ -81,25 +60,41 @@
{{ build.job_config.trigger_metadata.ref }}
</span>
</div>
</span>
</div>
</span>
<!-- Just commit SHA -->
<span ng-if="build.job_config.trigger_metadata && !build.job_config.trigger_metadata.commit_info">
Triggered by commit
<span>
{{ build.job_config.trigger_metadata.commit_sha }}
</span>
</span>
<!-- Just commit SHA -->
<span class="tbd-content" ng-if="build.job_config.trigger_metadata && !build.job_config.trigger_metadata.commit_info" ng-switch on="build.trigger.service">
Triggered by commit
<!-- GitHub -->
<div ng-switch-when="github">
<span class="source-commit-link"
commit-sha="build.job_config.trigger_metadata.commit_sha"
url-template="getGitHubRepoURL(build) + '/commit/{sha}'"></span>
</div>
<!-- No information -->
<span ng-if="!build.job_config.trigger_metadata">
Triggered by commit to
<i class="fa fa-git fa-lg" data-title="git" bs-tooltip="tooltip.title"></i>
{{ build.trigger.config.build_source }}
</span>
<!-- Git -->
<div ng-switch-when="custom-git">
<span>{{ build.job_config.trigger_metadata.commit_sha }}</span>
</div>
</span>
<!-- No information -->
<span class="tbd-content" ng-if="!build.job_config.trigger_metadata" ng-switch on="build.trigger.service">
Triggered by commit to
<!-- GitHub -->
<div ng-switch-when="github">
<i class="fa fa-github fa-lg" data-title="GitHub" data-container="body" bs-tooltip></i>
<a ng-href="{{ getGitHubRepoURL(build) }}" target="_new">
{{ build.trigger.config.build_source }}
</a>
</div>
<!-- Git -->
<div ng-switch-when="custom-git">
<i class="fa fa-git fa-lg" data-title="git" data-container="body" bs-tooltip></i>
{{ build.trigger.config.build_source }}
</div>
</span>
<!-- Unknown -->
<span ng-switch-default>Unknown Build Trigger</span>
</span>
</div>

View file

@ -170,8 +170,6 @@ angular.module('quay').directive('repoPanelBuilds', function () {
$scope.showTriggerCredentialsModal = function(trigger) {
$scope.triggerCredentialsModalTrigger = trigger;
$scope.triggerCredentialsModalCounter++;
console.log($scope.triggerCredentialsModalTrigger)
console.log($scope.triggerCredentialsModalCounter)
};
$scope.askDeleteTrigger = function(trigger) {

View file

@ -1,5 +1,5 @@
/**
* An element which displays a dialog with the public SSH keycredentials for a trigger.
* An element which displays a dialog with the necessary credentials for a build trigger.
*/
angular.module('quay').directive('triggerCredentialsDialog', function () {
var directiveDefinitionObject = {
@ -14,7 +14,7 @@ angular.module('quay').directive('triggerCredentialsDialog', function () {
},
controller: function($scope, $element) {
var show = function() {
if (!$scope.trigger) {
if (!$scope.trigger || !$scope.counter) {
$('#triggercredentialsmodal').modal('hide');
return;
}

View file

@ -37,7 +37,7 @@ angular.module('quay').factory('TriggerService', ['UtilService', '$sanitize', 'K
return authorize_url + 'client_id=' + client_id +
'&scope=repo,user:email&redirect_uri=' + redirect_uri;
},
'target': '',
'is_external': true,
'is_enabled': function() {
return Features.GITHUB_BUILD;
},
@ -52,7 +52,7 @@ angular.module('quay').factory('TriggerService', ['UtilService', '$sanitize', 'K
}
},
'custom': {
'custom-git': {
'description': function(config) {
var source = UtilService.textToSafeHtml(config['build_source']);
var desc = '<i class"fa fa-git fa-lg" style="margin-left:2px; margin-right: 2px"></i> Push to Custom Git Repository ' + source;
@ -69,7 +69,7 @@ angular.module('quay').factory('TriggerService', ['UtilService', '$sanitize', 'K
'get_redirect_url': function(namespace, repository) {
return Config.getUrl('/customtrigger/setup/' + namespace + '/' + repository);
},
'target': '_self',
'is_external': false,
'is_enabled': function() { return true; },
'icon': 'fa-git',
'title': function() { return 'Custom Git Repository Push'; }
@ -95,9 +95,11 @@ angular.module('quay').factory('TriggerService', ['UtilService', '$sanitize', 'K
return type['get_redirect_url'](namespace, repository);
};
// Helper to remove the prefix and suffix /s on subdir paths.
triggerService.trimSubdir = function(subdir) {
return subdir.replace(new RegExp('(^\/+|\/+$)'), '');
triggerService.getDockerfileLocation = function(trigger) {
if (!trigger.config.subdir) {
return '//Dockerfile';
}
return '//' + trigger.config.subdir.replace(new RegExp('(^\/+|\/+$)'), '') + '/Dockerfile';
};
triggerService.getTitle = function(name) {

Binary file not shown.