trigger: initial custom git trigger
This commit is contained in:
parent
9c55aca011
commit
998c6007cd
4 changed files with 143 additions and 8 deletions
|
@ -212,15 +212,12 @@ class BuildTriggerActivate(RepositoryParamResource):
|
|||
token = model.create_delegate_token(namespace, repository, token_name,
|
||||
'write')
|
||||
|
||||
# Generate an SSH keypair
|
||||
new_config_dict['public_key'], trigger.private_key = generate_ssh_keypair()
|
||||
|
||||
try:
|
||||
path = url_for('webhooks.build_trigger_webhook', trigger_uuid=trigger.uuid)
|
||||
authed_url = _prepare_webhook_url(app.config['PREFERRED_URL_SCHEME'], '$token', token.code,
|
||||
app.config['SERVER_HOSTNAME'], path)
|
||||
|
||||
final_config = handler.activate(trigger.uuid, authed_url,
|
||||
final_config, trigger.private_key = handler.activate(trigger.uuid, authed_url,
|
||||
trigger.auth_token, new_config_dict)
|
||||
except TriggerActivationException as exc:
|
||||
token.delete_instance()
|
||||
|
@ -512,3 +509,12 @@ class BuildTriggerSources(RepositoryParamResource):
|
|||
}
|
||||
else:
|
||||
raise Unauthorized()
|
||||
|
||||
@resource('/v1/repository/<repopath:repository>/trigger/redirect')
|
||||
@path_param('repository', 'The full path of the repository. e.g. namespace/name')
|
||||
@internal_only
|
||||
class CustomBuildTriggerRedirect(RepositoryParamResource):
|
||||
""" Custom verb to properly handle redirecting users using their own custom git hook. """
|
||||
@nickname('customTriggerRedirect')
|
||||
def get(self, namespace, repository):
|
||||
pass
|
||||
|
|
|
@ -11,6 +11,7 @@ from tempfile import SpooledTemporaryFile
|
|||
|
||||
from app import app, userfiles as user_files, github_trigger
|
||||
from util.tarfileappender import TarfileAppender
|
||||
from util.ssh import generate_ssh_keypair
|
||||
|
||||
|
||||
client = app.config['HTTPCLIENT']
|
||||
|
@ -26,6 +27,8 @@ CHUNK_SIZE = 512 * 1024
|
|||
def should_skip_commit(message):
|
||||
return '[skip build]' in message or '[build skip]' in message
|
||||
|
||||
class InvalidPayloadException(Exception):
|
||||
pass
|
||||
|
||||
class BuildArchiveException(Exception):
|
||||
pass
|
||||
|
@ -185,6 +188,7 @@ 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'])
|
||||
config['deploy_key_id'] = deploy_key.id
|
||||
except GithubException:
|
||||
|
@ -206,7 +210,7 @@ class GithubBuildTrigger(BuildTrigger):
|
|||
msg = 'Unable to create webhook on repository: %s' % new_build_source
|
||||
raise TriggerActivationException(msg)
|
||||
|
||||
return config
|
||||
return config, private_key
|
||||
|
||||
def deactivate(self, auth_token, config):
|
||||
gh_client = self._get_client(auth_token)
|
||||
|
@ -541,3 +545,102 @@ class GithubBuildTrigger(BuildTrigger):
|
|||
return branches
|
||||
|
||||
return None
|
||||
|
||||
class CustomBuildTrigger(BuildTrigger):
|
||||
@classmethod
|
||||
def service_name(cls):
|
||||
return 'custom'
|
||||
|
||||
def is_active(self, config):
|
||||
return 'public_key' in config
|
||||
|
||||
@staticmethod
|
||||
def _metadata_from_payload(payload):
|
||||
try:
|
||||
metadata = {
|
||||
'commit_sha': payload['commit'],
|
||||
'ref': payload['ref'],
|
||||
'default_branch': payload.get('default_branch', 'master'),
|
||||
}
|
||||
except KeyError:
|
||||
raise InvalidPayloadException()
|
||||
|
||||
commit_info = payload['commit_info']
|
||||
if commit_info is not None:
|
||||
try:
|
||||
metadata['commit_info'] = {
|
||||
'url': commit_info['url'],
|
||||
'message': commit_info['message'],
|
||||
'date': commit_info['date'],
|
||||
}
|
||||
except KeyError:
|
||||
raise InvalidPayloadException()
|
||||
|
||||
author = commit_info['author']
|
||||
if author is not None:
|
||||
try:
|
||||
metadata['commit_info']['author'] = {
|
||||
'username': author['username'],
|
||||
'avatar_url': author['avatar_url'],
|
||||
'url': author['url'],
|
||||
}
|
||||
except KeyError:
|
||||
raise InvalidPayloadException()
|
||||
|
||||
committer = commit_info['committer']
|
||||
if committer is not None:
|
||||
try:
|
||||
metadata['commit_info']['committer'] = {
|
||||
'username': committer['username'],
|
||||
'avatar_url': committer['avatar_url'],
|
||||
'url': committer['url'],
|
||||
}
|
||||
except KeyError:
|
||||
raise InvalidPayloadException()
|
||||
|
||||
return metadata
|
||||
|
||||
def handle_trigger_request(self, request, trigger):
|
||||
payload = request.get_json()
|
||||
if not payload:
|
||||
raise SkipRequestException()
|
||||
|
||||
logger.debug('Payload %s', payload)
|
||||
metadata = self._metadata_from_payload(payload)
|
||||
|
||||
# The build source is the canonical git URL used to clone.
|
||||
config = get_trigger_config(trigger)
|
||||
metadata['git_url'] = config['build_source']
|
||||
|
||||
branch = metadata['ref'].split('/')[-1]
|
||||
tags = {branch}
|
||||
|
||||
build_name = metadata['commit_sha'][:6]
|
||||
dockerfile_id = None
|
||||
|
||||
return dockerfile_id, tags, build_name, trigger.config['subdir'], metadata
|
||||
|
||||
def activate(self, trigger_uuid, standard_webhook_url, auth_token, config):
|
||||
config['public_key'], private_key = generate_ssh_keypair()
|
||||
return config, private_key
|
||||
|
||||
def deactivate(self, auth_token, config):
|
||||
config.pop('public_key', None)
|
||||
return config
|
||||
|
||||
def manual_start(self, trigger, run_parameters=None):
|
||||
for parameter in ['branch_name', 'commit_sha',]:
|
||||
if parameter not in run_parameters:
|
||||
raise TriggerStartException
|
||||
|
||||
dockerfile_id = None
|
||||
branch = run_parameters.get('branch_name', None)
|
||||
tags = {branch} if branch is not None else {}
|
||||
build_name = 'HEAD'
|
||||
metadata = {
|
||||
'commit_sha': run_parameters['commit_sha'],
|
||||
'default_branch': branch,
|
||||
'ref': 'refs/heads/%s' % branch,
|
||||
}
|
||||
|
||||
return dockerfile_id, tags, build_name, trigger.config['subdir'], metadata
|
||||
|
|
|
@ -9,7 +9,7 @@ from auth.permissions import ModifyRepositoryPermission
|
|||
from util.invoice import renderInvoiceToHtml
|
||||
from util.useremails import send_invoice_email, send_subscription_change, send_payment_failed
|
||||
from util.http import abort
|
||||
from endpoints.trigger import BuildTrigger, ValidationRequestException, SkipRequestException
|
||||
from endpoints.trigger import BuildTrigger, ValidationRequestException, SkipRequestException, InvalidPayloadException
|
||||
from endpoints.common import start_build
|
||||
|
||||
|
||||
|
@ -88,14 +88,15 @@ def build_trigger_webhook(trigger_uuid, **kwargs):
|
|||
try:
|
||||
specs = handler.handle_trigger_request(request, trigger)
|
||||
dockerfile_id, tags, name, subdir, metadata = specs
|
||||
|
||||
except ValidationRequestException:
|
||||
# This was just a validation request, we don't need to build anything
|
||||
return make_response('Okay')
|
||||
|
||||
except SkipRequestException:
|
||||
# The build was requested to be skipped
|
||||
return make_response('Okay')
|
||||
except InvalidPayloadException:
|
||||
# The payload was malformed
|
||||
abort(400)
|
||||
|
||||
pull_robot_name = model.get_pull_robot_name(trigger)
|
||||
repo = model.get_repository(namespace, repository)
|
||||
|
|
|
@ -49,6 +49,31 @@ angular.module('quay').factory('TriggerService', ['UtilService', '$sanitize', 'K
|
|||
|
||||
return 'GitHub Repository Push';
|
||||
}
|
||||
},
|
||||
|
||||
'custom': {
|
||||
'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;
|
||||
desc += '<br>Dockerfile folder: //' + UtilService.textToSafeHtml(config['subdir']);
|
||||
return desc;
|
||||
},
|
||||
'run_parameters': [
|
||||
{
|
||||
'title': 'Branch',
|
||||
'type': 'string',
|
||||
'name': 'branch_name'
|
||||
},
|
||||
{
|
||||
'title': 'Commit SHA1',
|
||||
'type': 'string',
|
||||
'name': 'commit_sha'
|
||||
}
|
||||
],
|
||||
'get_redirect_url': function() {},
|
||||
'is_enabled': function() { return true; },
|
||||
'icon': 'fa-git',
|
||||
'title': function() { return 'Custom Git Repository Push'; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue