82 lines
1.9 KiB
Python
82 lines
1.9 KiB
Python
import hashlib
|
|
import hmac
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import threading
|
|
|
|
import flask
|
|
|
|
HOST = os.getenv("WEBHOOK_HOST", "0.0.0.0")
|
|
PORT = os.getenv("WEBHOOK_PORT", 6000)
|
|
|
|
CONFIG_FILE = os.getenv("CONFIG_FILE", "./test/config.json")
|
|
|
|
app = flask.Flask(__name__)
|
|
|
|
|
|
class HttpError(Exception):
|
|
def __init__(self, status, msg):
|
|
self.status = status
|
|
self.msg = msg
|
|
|
|
|
|
def _load_config():
|
|
with open(CONFIG_FILE) as f:
|
|
return json.load(f)
|
|
|
|
|
|
@app.route("/<user>/<repo>/deploy", methods=['POST'])
|
|
def deploy(user, repo):
|
|
try:
|
|
response = _deploy(user, repo)
|
|
status = 200
|
|
except HttpError as e:
|
|
response = e.msg
|
|
status = e.status
|
|
except Exception:
|
|
response = "Internal Error"
|
|
status = 500
|
|
raise
|
|
return flask.Response(response, status=status)
|
|
|
|
|
|
def _deploy(user, repo):
|
|
payload = flask.request.json
|
|
repo_full_name = payload['repository']['full_name']
|
|
|
|
if repo_full_name != '/'.join([user, repo]):
|
|
raise HttpError(400, "Endpoint doesn't match repository")
|
|
|
|
config = _load_config().get(user, {}).get(repo)
|
|
if not config:
|
|
raise HttpError(400, f"Configuration not found for {user}/{repo}")
|
|
|
|
secret = config['secret'].encode('utf-8')
|
|
signature = hmac.new(secret, flask.request.data, hashlib.sha256).hexdigest()
|
|
h_signature = flask.request.headers.get('X-Gitea-Signature')
|
|
|
|
if h_signature != signature:
|
|
raise HttpError(403, "Unauthorized: Signatures don't match")
|
|
|
|
th = threading.Thread(target=_deploy_script, kwargs=dict(config=config))
|
|
th.setDaemon(True)
|
|
th.start()
|
|
|
|
return "OK"
|
|
|
|
|
|
def _deploy_script(config):
|
|
print("Running deploy script ...")
|
|
cmd = [config['deploy_script']]
|
|
subprocess.call(cmd, env=config.get('env'))
|
|
print("Deployed!")
|
|
|
|
|
|
def run():
|
|
app.run(host=HOST, port=PORT, debug=True)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
run()
|