167 lines
4.8 KiB
Python
167 lines
4.8 KiB
Python
|
import logging
|
||
|
import json
|
||
|
|
||
|
from jsonschema import validate
|
||
|
from buildtrigger.triggerutil import (RepositoryReadException, TriggerActivationException,
|
||
|
TriggerStartException, ValidationRequestException,
|
||
|
InvalidPayloadException,
|
||
|
SkipRequestException, raise_if_skipped_build,
|
||
|
find_matching_branches)
|
||
|
|
||
|
from buildtrigger.basehandler import BuildTriggerHandler
|
||
|
|
||
|
from util.security.ssh import generate_ssh_keypair
|
||
|
|
||
|
|
||
|
logger = logging.getLogger(__name__)
|
||
|
|
||
|
class CustomBuildTrigger(BuildTriggerHandler):
|
||
|
payload_schema = {
|
||
|
'type': 'object',
|
||
|
'properties': {
|
||
|
'commit': {
|
||
|
'type': 'string',
|
||
|
'description': 'first 7 characters of the SHA-1 identifier for a git commit',
|
||
|
'pattern': '^([A-Fa-f0-9]{7,})$',
|
||
|
},
|
||
|
'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',
|
||
|
'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',
|
||
|
'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',
|
||
|
'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'],
|
||
|
},
|
||
|
},
|
||
|
'required': ['url', 'message', 'date'],
|
||
|
},
|
||
|
},
|
||
|
'required': ['commit', 'ref', 'default_branch'],
|
||
|
}
|
||
|
|
||
|
@classmethod
|
||
|
def service_name(cls):
|
||
|
return 'custom-git'
|
||
|
|
||
|
def is_active(self):
|
||
|
return self.config.has_key('credentials')
|
||
|
|
||
|
def _metadata_from_payload(self, payload):
|
||
|
try:
|
||
|
metadata = json.loads(payload)
|
||
|
validate(metadata, self.payload_schema)
|
||
|
except Exception as e:
|
||
|
raise InvalidPayloadException(e.message)
|
||
|
return metadata
|
||
|
|
||
|
def handle_trigger_request(self, request):
|
||
|
payload = request.data
|
||
|
if not payload:
|
||
|
raise InvalidPayloadException()
|
||
|
|
||
|
logger.debug('Payload %s', payload)
|
||
|
|
||
|
metadata = self._metadata_from_payload(payload)
|
||
|
metadata['git_url'] = self.config['build_source']
|
||
|
|
||
|
prepared = self.prepare_build(metadata)
|
||
|
|
||
|
# Check if we should skip this build.
|
||
|
raise_if_skipped_build(prepared)
|
||
|
|
||
|
return prepared
|
||
|
|
||
|
def manual_start(self, run_parameters=None):
|
||
|
# commit_sha is the only required parameter
|
||
|
commit_sha = run_parameters.get('commit_sha')
|
||
|
if commit_sha is None:
|
||
|
raise TriggerStartException('missing required parameter')
|
||
|
|
||
|
config = self.config
|
||
|
metadata = {
|
||
|
'commit': commit_sha,
|
||
|
'git_url': config['build_source'],
|
||
|
}
|
||
|
|
||
|
return self.prepare_build(metadata, is_manual=True)
|
||
|
|
||
|
def activate(self, standard_webhook_url):
|
||
|
config = self.config
|
||
|
public_key, private_key = generate_ssh_keypair()
|
||
|
config['credentials'] = [
|
||
|
{
|
||
|
'name': 'SSH Public Key',
|
||
|
'value': public_key,
|
||
|
},
|
||
|
{
|
||
|
'name': 'Webhook Endpoint URL',
|
||
|
'value': standard_webhook_url,
|
||
|
},
|
||
|
]
|
||
|
self.config = config
|
||
|
return config, {'private_key': private_key}
|
||
|
|
||
|
def deactivate(self):
|
||
|
config = self.config
|
||
|
config.pop('credentials', None)
|
||
|
self.config = config
|
||
|
return config
|
||
|
|
||
|
def get_repository_url(self):
|
||
|
return None
|