Unwrap payload and git clone
This commit is contained in:
parent
c059cb650d
commit
f25c79cdc2
2 changed files with 85 additions and 6 deletions
84
gogsmaker.py
84
gogsmaker.py
|
@ -2,16 +2,92 @@
|
|||
|
||||
A webhook-handler for Gogs running `make` when needed. """
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
from flask import Flask, request
|
||||
from .settings import HOOKS
|
||||
from . import settings
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
@app.route('/', methods=['POST'])
|
||||
def view_root():
|
||||
class UnmonitoredRepository(Exception):
|
||||
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
|
||||
if payload is None:
|
||||
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
|
||||
|
|
|
@ -14,3 +14,6 @@ HOOKS = [
|
|||
'targets': ['all'],
|
||||
},
|
||||
]
|
||||
|
||||
# Directory in which the repositories are cloned
|
||||
CLONE_ROOT = 'repos'
|
||||
|
|
Loading…
Reference in a new issue