Write triggers are successfully installing on GitHub, noice!

This commit is contained in:
jakedt 2014-02-21 17:09:56 -05:00
parent a6400171b3
commit 86e93a2c0f
7 changed files with 76 additions and 32 deletions

View file

@ -206,6 +206,8 @@ class TestConfig(FlaskConfig, FakeStorage, EphemeralDB, FakeUserfiles,
LOGGING_CONFIG = logs_init_builder(logging.WARN) LOGGING_CONFIG = logs_init_builder(logging.WARN)
POPULATE_DB_TEST_DATA = True POPULATE_DB_TEST_DATA = True
TESTING = True TESTING = True
URL_SCHEME = 'http'
URL_HOST = 'localhost:5000'
class DebugConfig(FlaskConfig, MailConfig, LocalStorage, SQLiteDB, class DebugConfig(FlaskConfig, MailConfig, LocalStorage, SQLiteDB,
@ -215,6 +217,8 @@ class DebugConfig(FlaskConfig, MailConfig, LocalStorage, SQLiteDB,
LOGGING_CONFIG = logs_init_builder(formatter=logging.Formatter()) LOGGING_CONFIG = logs_init_builder(formatter=logging.Formatter())
SEND_FILE_MAX_AGE_DEFAULT = 0 SEND_FILE_MAX_AGE_DEFAULT = 0
POPULATE_DB_TEST_DATA = True POPULATE_DB_TEST_DATA = True
URL_SCHEME = 'http'
URL_HOST = 'ci.devtable.com:5000'
class LocalHostedConfig(FlaskConfig, MailConfig, S3Storage, RDSMySQL, class LocalHostedConfig(FlaskConfig, MailConfig, S3Storage, RDSMySQL,
@ -224,6 +228,8 @@ class LocalHostedConfig(FlaskConfig, MailConfig, S3Storage, RDSMySQL,
UserEventConfig, LargePoolHttpClient): UserEventConfig, LargePoolHttpClient):
LOGGING_CONFIG = logs_init_builder() LOGGING_CONFIG = logs_init_builder()
SEND_FILE_MAX_AGE_DEFAULT = 0 SEND_FILE_MAX_AGE_DEFAULT = 0
URL_SCHEME = 'http'
URL_HOST = 'ci.devtable.com:5000'
class ProductionConfig(FlaskProdConfig, MailConfig, S3Storage, RDSMySQL, class ProductionConfig(FlaskProdConfig, MailConfig, S3Storage, RDSMySQL,
@ -234,3 +240,5 @@ class ProductionConfig(FlaskProdConfig, MailConfig, S3Storage, RDSMySQL,
LOGGING_CONFIG = logs_init_builder() LOGGING_CONFIG = logs_init_builder()
SEND_FILE_MAX_AGE_DEFAULT = 0 SEND_FILE_MAX_AGE_DEFAULT = 0
URL_SCHEME = 'https'
URL_HOST = 'quay.io'

View file

@ -110,19 +110,6 @@ class Repository(BaseModel):
) )
class BuildTriggerService(BaseModel):
name = CharField(index=True)
class RepositoryBuildTrigger(BaseModel):
uuid = CharField(default=uuid_generator)
service = ForeignKeyField(BuildTriggerService, index=True)
repository = ForeignKeyField(Repository, index=True)
connected_user = ForeignKeyField(User)
auth_token = CharField()
config = TextField(default='{}')
class Role(BaseModel): class Role(BaseModel):
name = CharField(index=True) name = CharField(index=True)
@ -176,6 +163,20 @@ class AccessToken(BaseModel):
temporary = BooleanField(default=True) temporary = BooleanField(default=True)
class BuildTriggerService(BaseModel):
name = CharField(index=True)
class RepositoryBuildTrigger(BaseModel):
uuid = CharField(default=uuid_generator)
service = ForeignKeyField(BuildTriggerService, index=True)
repository = ForeignKeyField(Repository, index=True)
connected_user = ForeignKeyField(User)
auth_token = CharField()
config = TextField(default='{}')
write_token = ForeignKeyField(AccessToken, null=True)
class EmailConfirmation(BaseModel): class EmailConfirmation(BaseModel):
code = CharField(default=random_string_generator(), unique=True, index=True) code = CharField(default=random_string_generator(), unique=True, index=True)
user = ForeignKeyField(User) user = ForeignKeyField(User)

View file

@ -1320,8 +1320,9 @@ def create_access_token(repository, role):
return new_token return new_token
def create_delegate_token(namespace_name, repository_name, friendly_name): def create_delegate_token(namespace_name, repository_name, friendly_name,
read_only = Role.get(name='read') role='read'):
read_only = Role.get(name=role)
repo = Repository.get(Repository.name == repository_name, repo = Repository.get(Repository.name == repository_name,
Repository.namespace == namespace_name) Repository.namespace == namespace_name)
new_token = AccessToken.create(repository=repo, role=read_only, new_token = AccessToken.create(repository=repo, role=read_only,
@ -1509,6 +1510,11 @@ def list_build_triggers(namespace_name, repository_name):
def delete_build_trigger(namespace_name, repository_name, trigger_uuid): def delete_build_trigger(namespace_name, repository_name, trigger_uuid):
trigger = get_build_trigger(namespace_name, repository_name, trigger_uuid) trigger = get_build_trigger(namespace_name, repository_name, trigger_uuid)
# Delete the access token created for this trigger, and the trigger itself
if trigger.write_token and trigger.write_token.code:
trigger.write_token.delete_instance()
trigger.delete_instance() trigger.delete_instance()

View file

@ -9,6 +9,7 @@ from flask.ext.login import current_user, logout_user
from flask.ext.principal import identity_changed, AnonymousIdentity from flask.ext.principal import identity_changed, AnonymousIdentity
from functools import wraps from functools import wraps
from collections import defaultdict from collections import defaultdict
from urllib import quote
from data import model from data import model
from data.queue import dockerfile_build_queue from data.queue import dockerfile_build_queue
@ -1363,6 +1364,11 @@ def get_build_trigger(namespace, repository, trigger_uuid):
abort(403) # Permission denied abort(403) # Permission denied
def _prepare_webhook_url(scheme, username, password, hostname, path):
auth_hostname = '%s:%s@%s' % (quote(username), quote(password), hostname)
return urlparse.urlunparse((scheme, auth_hostname, path, '', '', ''))
@api.route('/repository/<path:repository>/trigger/<trigger_uuid>/activate', @api.route('/repository/<path:repository>/trigger/<trigger_uuid>/activate',
methods=['POST']) methods=['POST'])
@api_login_required @api_login_required
@ -1386,20 +1392,29 @@ def activate_build_trigger(namespace, repository, trigger_uuid):
if user_permission.can(): if user_permission.can():
new_config_dict = request.get_json() new_config_dict = request.get_json()
token_name = 'Build Trigger: %s' % trigger.service.name
token = model.create_delegate_token(namespace, repository, token_name,
'write')
try: try:
repository = '%s/%s' % (trigger.repository.namespace, repository = '%s/%s' % (trigger.repository.namespace,
trigger.repository.name) trigger.repository.name)
webhook_url = url_for('webhooks.build_trigger_webhook', path = url_for('webhooks.build_trigger_webhook', repository=repository,
repository=repository, trigger_uuid=trigger.uuid, trigger_uuid=trigger.uuid)
_external=True) authed_url = _prepare_webhook_url(app.config['URL_SCHEME'], '$token',
handler.activate(trigger.uuid, webhook_url, trigger.auth_token, token.code, app.config['URL_HOST'],
path)
handler.activate(trigger.uuid, authed_url, trigger.auth_token,
new_config_dict) new_config_dict)
except TriggerActivationException as e: except TriggerActivationException as e:
token.delete_instance()
abort(400, message = e.msg) abort(400, message = e.msg)
return return
# Save the updated config. # Save the updated config.
trigger.config = json.dumps(new_config_dict) trigger.config = json.dumps(new_config_dict)
trigger.write_token = token
trigger.save() trigger.save()
return jsonify(trigger_view(trigger)) return jsonify(trigger_view(trigger))

View file

@ -1,7 +1,7 @@
import logging import logging
import io import io
from github import Github from github import Github, UnknownObjectException, GithubException
from tempfile import SpooledTemporaryFile from tempfile import SpooledTemporaryFile
from app import app from app import app
@ -27,6 +27,9 @@ class InvalidServiceException(Exception):
class TriggerActivationException(Exception): class TriggerActivationException(Exception):
pass pass
class ValidationRequestException(Exception):
pass
class BuildTrigger(object): class BuildTrigger(object):
def __init__(self): def __init__(self):
@ -97,17 +100,20 @@ class GithubBuildTrigger(BuildTrigger):
try: try:
to_add_webhook = gh_client.get_repo(new_build_source) to_add_webhook = gh_client.get_repo(new_build_source)
except UnknownObjectException:
msg = 'Unable to find GitHub repository for source: %s'
raise TriggerActivationException(msg % new_build_source)
webhook_config = { webhook_config = {
'url': standard_webhook_url, 'url': standard_webhook_url,
'content_type': 'json', 'content_type': 'json',
} }
try:
to_add_webhook.create_hook('web', webhook_config) to_add_webhook.create_hook('web', webhook_config)
except GithubException:
msg = 'Unable to create webhook on repository: %s'
except Exception: raise TriggerActivationException(msg % new_build_source)
pass
def list_build_sources(self, auth_token): def list_build_sources(self, auth_token):
gh_client = self._get_client(auth_token) gh_client = self._get_client(auth_token)
@ -142,6 +148,10 @@ class GithubBuildTrigger(BuildTrigger):
def handle_trigger_request(self, request, auth_token, config): def handle_trigger_request(self, request, auth_token, config):
payload = request.get_json() payload = request.get_json()
if 'zen' in payload:
raise ValidationRequestException()
logger.debug('Payload %s', payload) logger.debug('Payload %s', payload)
ref = payload['ref'] ref = payload['ref']
commit_id = payload['head_commit']['id'][0:7] commit_id = payload['head_commit']['id'][0:7]

View file

@ -11,7 +11,7 @@ from util.invoice import renderInvoiceToHtml
from util.email import send_invoice_email from util.email import send_invoice_email
from util.names import parse_repository_name from util.names import parse_repository_name
from util.http import abort from util.http import abort
from endpoints.trigger import BuildTrigger from endpoints.trigger import BuildTrigger, ValidationRequestException
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -61,9 +61,13 @@ def build_trigger_webhook(namespace, repository, trigger_uuid):
handler = BuildTrigger.get_trigger_for_service(trigger.service.name) handler = BuildTrigger.get_trigger_for_service(trigger.service.name)
logger.debug('Passing webhook request to handler %s', handler) logger.debug('Passing webhook request to handler %s', handler)
try:
df_id, tag, name = handler.handle_trigger_request(request, df_id, tag, name = handler.handle_trigger_request(request,
trigger.auth_token, trigger.auth_token,
trigger.config) trigger.config)
except ValidationRequestException:
# This was just a validation request, don't need to build anything
return make_response('Okay')
host = urlparse.urlparse(request.url).netloc host = urlparse.urlparse(request.url).netloc
full_tag = '%s/%s/%s:%s' % (host, trigger.repository.namespace, full_tag = '%s/%s/%s:%s' % (host, trigger.repository.namespace,

Binary file not shown.