-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgithub-webhook.py
executable file
·97 lines (81 loc) · 2.3 KB
/
github-webhook.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/env python3
import logging
import os
import subprocess
from pathlib import Path
from threading import Thread
from flask import Flask, request
def decode(b: bytes) -> str:
try:
return b.decode()
except:
return repr(b)
def run_task():
completed_process = subprocess.run(
args.command,
shell=True,
input="",
stderr=subprocess.STDOUT,
stdout=subprocess.PIPE,
cwd=args.dir,
)
result = "Process {!r} finished with return code {}:\n{}".format(
completed_process.args,
completed_process.returncode,
decode(completed_process.stdout),
)
if completed_process.returncode == 0:
logging.info(result)
else:
logging.error(result)
app = Flask(__name__)
@app.route("/webhook", methods=["POST"])
def webhook():
# todo: secret
ref = request.json.get("ref")
expected = ["refs/heads/master", "refs/heads/main"]
if ref in expected:
thread = Thread(target=run_task)
thread.daemon = False
thread.start()
return f"Running {args.command!r}...", 202
else:
return f"Ref {ref!r} is not one of {expected}. Not doing anything.", 200
def get_parser(default_port, default_address="0.0.0.0"):
parser = argparse.ArgumentParser(
description="GitHub webhook handler. "
"Automatically runs a specified command "
"when receives a notification about a push to main/master."
)
parser.add_argument(
"--bind",
"-b",
help=f"address to bind to (default: {default_address})",
default=default_address,
)
parser.add_argument(
"--port",
"-p",
default=default_port,
type=int,
help=f"port to listen on (default: {default_port})",
)
parser.add_argument(
"--dir",
"-d",
default=os.getcwd(),
type=Path,
help="directory to execute command in",
)
parser.add_argument(
"command",
help=f"command to execute",
)
return parser
if __name__ == "__main__":
import argparse
import waitress
from paste.translogger import TransLogger
logging.basicConfig(level="INFO")
args = get_parser(default_port=11444).parse_args()
waitress.serve(TransLogger(app), host=args.bind, port=args.port)