2024-02-07 14:49:55 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
import asyncio
|
|
|
|
import hashlib
|
2021-06-13 05:12:34 +02:00
|
|
|
import hmac
|
2024-02-07 14:49:55 +01:00
|
|
|
import os
|
2021-06-13 05:12:34 +02:00
|
|
|
import shlex
|
2021-06-13 04:50:21 +02:00
|
|
|
import tempfile
|
2021-05-21 18:14:58 +02:00
|
|
|
|
2024-02-07 14:49:55 +01:00
|
|
|
from make_readme import generate_READMEs
|
2023-10-31 16:04:28 +01:00
|
|
|
from sanic import Sanic, response
|
2021-06-13 05:12:34 +02:00
|
|
|
from sanic.response import text
|
|
|
|
|
|
|
|
app = Sanic(__name__)
|
2021-05-21 18:14:58 +02:00
|
|
|
|
2021-05-21 20:17:02 +02:00
|
|
|
github_webhook_secret = open("github_webhook_secret", "r").read().strip()
|
2021-05-21 18:14:58 +02:00
|
|
|
|
2021-05-21 20:12:00 +02:00
|
|
|
login = open("login").read().strip()
|
|
|
|
token = open("token").read().strip()
|
|
|
|
|
2021-05-21 18:14:58 +02:00
|
|
|
my_env = os.environ.copy()
|
|
|
|
my_env["GIT_TERMINAL_PROMPT"] = "0"
|
2021-09-04 00:42:51 +02:00
|
|
|
my_env["GIT_AUTHOR_NAME"] = "yunohost-bot"
|
2021-05-21 22:37:22 +02:00
|
|
|
my_env["GIT_AUTHOR_EMAIL"] = "yunohost@yunohost.org"
|
2021-09-04 00:42:51 +02:00
|
|
|
my_env["GIT_COMMITTER_NAME"] = "yunohost-bot"
|
2021-05-21 22:37:22 +02:00
|
|
|
my_env["GIT_COMMITTER_EMAIL"] = "yunohost@yunohost.org"
|
2021-05-21 18:14:58 +02:00
|
|
|
|
|
|
|
|
2021-06-13 05:12:34 +02:00
|
|
|
async def git(cmd, in_folder=None):
|
2021-05-21 18:14:58 +02:00
|
|
|
|
|
|
|
if not isinstance(cmd, list):
|
|
|
|
cmd = cmd.split()
|
|
|
|
if in_folder:
|
|
|
|
cmd = ["-C", in_folder] + cmd
|
|
|
|
cmd = ["git"] + cmd
|
2021-06-13 05:12:34 +02:00
|
|
|
cmd = " ".join(map(shlex.quote, cmd))
|
2021-06-14 16:34:26 +02:00
|
|
|
print(cmd)
|
2024-03-11 17:34:33 +01:00
|
|
|
command = await asyncio.create_subprocess_shell(
|
|
|
|
cmd,
|
|
|
|
env=my_env,
|
|
|
|
stdout=asyncio.subprocess.PIPE,
|
|
|
|
stderr=asyncio.subprocess.STDOUT,
|
|
|
|
)
|
2021-06-13 05:12:34 +02:00
|
|
|
data = await command.stdout.read()
|
|
|
|
return data.decode().strip()
|
|
|
|
|
|
|
|
|
|
|
|
@app.route("/github", methods=["GET"])
|
|
|
|
def main_route(request):
|
2024-03-11 17:34:33 +01:00
|
|
|
return text(
|
|
|
|
"You aren't supposed to go on this page using a browser, it's for webhooks push instead."
|
|
|
|
)
|
2021-05-21 18:14:58 +02:00
|
|
|
|
|
|
|
|
2021-06-13 05:12:34 +02:00
|
|
|
@app.route("/github", methods=["POST"])
|
|
|
|
async def on_push(request):
|
|
|
|
header_signature = request.headers.get("X-Hub-Signature")
|
|
|
|
if header_signature is None:
|
|
|
|
print("no header X-Hub-Signature")
|
2023-10-31 16:04:28 +01:00
|
|
|
return response.json({"error": "No X-Hub-Signature"}, 403)
|
2021-05-21 18:14:58 +02:00
|
|
|
|
2021-06-13 05:12:34 +02:00
|
|
|
sha_name, signature = header_signature.split("=")
|
|
|
|
if sha_name != "sha1":
|
|
|
|
print("signing algo isn't sha1, it's '%s'" % sha_name)
|
2023-10-31 16:04:28 +01:00
|
|
|
return response.json({"error": "Signing algorightm is not sha1 ?!"}, 501)
|
2021-05-21 18:14:58 +02:00
|
|
|
|
2021-06-13 05:12:34 +02:00
|
|
|
# HMAC requires the key to be bytes, but data is string
|
2024-03-11 17:34:33 +01:00
|
|
|
mac = hmac.new(
|
|
|
|
github_webhook_secret.encode(), msg=request.body, digestmod=hashlib.sha1
|
|
|
|
)
|
2021-06-13 05:12:34 +02:00
|
|
|
|
|
|
|
if not hmac.compare_digest(str(mac.hexdigest()), str(signature)):
|
2023-10-31 16:04:28 +01:00
|
|
|
return response.json({"error": "Bad signature ?!"}, 403)
|
2021-06-13 05:12:34 +02:00
|
|
|
|
|
|
|
data = request.json
|
2021-05-21 18:14:58 +02:00
|
|
|
|
|
|
|
repository = data["repository"]["full_name"]
|
|
|
|
branch = data["ref"].split("/", 2)[2]
|
|
|
|
|
2021-06-14 16:34:26 +02:00
|
|
|
print(f"{repository} -> branch '{branch}'")
|
|
|
|
|
2021-06-13 04:50:21 +02:00
|
|
|
with tempfile.TemporaryDirectory() as folder:
|
2024-03-11 17:34:33 +01:00
|
|
|
await git(
|
|
|
|
[
|
|
|
|
"clone",
|
|
|
|
f"https://{login}:{token}@github.com/{repository}",
|
|
|
|
"--single-branch",
|
|
|
|
"--branch",
|
|
|
|
branch,
|
|
|
|
folder,
|
|
|
|
]
|
|
|
|
)
|
2021-05-21 22:37:22 +02:00
|
|
|
generate_READMEs(folder)
|
2021-05-21 18:14:58 +02:00
|
|
|
|
2021-06-13 05:12:34 +02:00
|
|
|
await git(["add", "README*.md"], in_folder=folder)
|
2021-05-21 20:12:00 +02:00
|
|
|
|
2024-03-11 17:34:33 +01:00
|
|
|
diff_not_empty = await asyncio.create_subprocess_shell(
|
|
|
|
" ".join(["git", "diff", "HEAD", "--compact-summary"]),
|
|
|
|
cwd=folder,
|
|
|
|
stdout=asyncio.subprocess.PIPE,
|
|
|
|
stderr=asyncio.subprocess.STDOUT,
|
|
|
|
)
|
2021-06-13 05:12:34 +02:00
|
|
|
diff_not_empty = await diff_not_empty.stdout.read()
|
|
|
|
diff_not_empty = diff_not_empty.decode().strip()
|
2021-05-21 22:37:22 +02:00
|
|
|
if not diff_not_empty:
|
2021-06-14 16:34:26 +02:00
|
|
|
print("nothing to do")
|
2021-06-13 05:12:34 +02:00
|
|
|
return text("nothing to do")
|
|
|
|
|
2024-03-11 17:34:33 +01:00
|
|
|
await git(
|
|
|
|
[
|
|
|
|
"commit",
|
|
|
|
"-a",
|
|
|
|
"-m",
|
|
|
|
"Auto-update README",
|
|
|
|
"--author='yunohost-bot <yunohost@yunohost.org>'",
|
|
|
|
],
|
|
|
|
in_folder=folder,
|
|
|
|
)
|
2021-06-13 05:12:34 +02:00
|
|
|
await git(["push", "origin", branch, "--quiet"], in_folder=folder)
|
2021-05-21 18:14:58 +02:00
|
|
|
|
2021-06-13 05:12:34 +02:00
|
|
|
return text("ok")
|
2021-06-13 04:50:21 +02:00
|
|
|
|
2021-05-21 18:14:58 +02:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2021-05-21 20:12:00 +02:00
|
|
|
app.run(host="0.0.0.0", port=8123)
|