Unwrap payload and git clone

This commit is contained in:
Théophile Bastian 2018-03-03 01:45:54 +01:00
parent c059cb650d
commit f25c79cdc2
2 changed files with 85 additions and 6 deletions

View file

@ -2,16 +2,92 @@
A webhook-handler for Gogs running `make` when needed. """ A webhook-handler for Gogs running `make` when needed. """
import os
import subprocess
from flask import Flask, request from flask import Flask, request
from .settings import HOOKS from . import settings
app = Flask(__name__) app = Flask(__name__)
@app.route('/', methods=['POST']) class UnmonitoredRepository(Exception):
def view_root(): pass
class GitError(Exception):
def __init__(self, what):
self.what = what
def __str__(self):
return self.what
def get_hook(url):
''' Get the hook matching an URL, or raise UnmonitoredRepository '''
for hook in settings.HOOKS:
if hook['url'] == url:
return hook
raise UnmonitoredRepository
def repo_path(hook):
''' Get the path at which the hook's repo is cloned '''
return os.path.join(settings.CLONE_ROOT, hook['name'])
def update_repo(hook, clone_url):
''' Update (or clone) the given repository. May raise GitError. '''
path = repo_path(hook)
if os.path.isdir(os.path.join(path, '.git')): # Repo is already cloned
try:
subprocess.run(['git', 'clone', clone_url, path], check=True)
except subprocess.CalledProcessError:
raise GitError("Cannot clone {}".format(clone_url))
else: # Simply update
try:
subprocess.run(['git', '-C', path, 'reset', '--hard'],
check=True) # Just in case.
subprocess.run(['git', '-C', path, 'pull'], check=True)
except subprocess.CalledProcessError:
raise GitError("Cannot pull {}".format(hook['name']))
def gogs_payload(required):
def wrapper(fct):
payload = request.json payload = request.json
if payload is None: if payload is None:
return 'Expected json\n', 415 return 'Expected json\n', 415
print(payload)
for field in required + ['repository/html_url']:
path = field.split('/')
explore = payload
for section in path:
if section not in explore:
return (
'Invalid json: missing {}\n'.format('/'.join(path)),
400)
explore = explore[section]
try:
hook = get_hook(payload['repository']['html_url'])
except UnmonitoredRepository:
return 'Unmonitored repository\n', 403
return fct(payload, hook)
return wrapper
@app.route('/', methods=['POST'])
@gogs_payload(['repository/clone_url'])
def view_root(payload, hook):
clone_url = payload['repository']['clone_url']
try:
update_repo(hook, clone_url)
except GitError as error:
return 'Git error: {}\n'.format(error), 500
# TODO: make
return 'OK\n', 200 return 'OK\n', 200

View file

@ -14,3 +14,6 @@ HOOKS = [
'targets': ['all'], 'targets': ['all'],
}, },
] ]
# Directory in which the repositories are cloned
CLONE_ROOT = 'repos'