Skip to content

Instantly share code, notes, and snippets.

@davesteele
Last active April 23, 2020 14:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davesteele/d0df57602c947c9e01948c467ba696ac to your computer and use it in GitHub Desktop.
Save davesteele/d0df57602c947c9e01948c467ba696ac to your computer and use it in GitHub Desktop.
Automatic git commit submission to Discord
#!/usr/bin/python3
from collections import namedtuple
from datetime import datetime
import re
import requests
import subprocess
import sys
"""
This is intended to run as a git "post-receive" hook. It extracts information
from the most recent commit, and sends it via a Discord web-hook. Commit
messages and branch names are summarized.
Example output:
Author: David
Commit: 530c499
Branch: US2011
ShortDescription: <redacted>
"""
discord_hook_url = "<place Discord webhook here>"
def parse_branch(words):
for word in words:
word = re.sub(r"\)", "", word)
word = re.sub(r"\(", "", word)
for whole_name in ["sprint-", "master"]:
if word.startswith(whole_name):
return [word]
for partial_re in ["^(US[0-9]+)", "^\'(US[0-9]+)"]:
if re.match(partial_re, word):
return [re.match(partial_re, word).group(1)]
return ["<none/unknown>"]
def parse_desc(words):
msg = " ".join(words)
match = re.match("^Merge branch (.+) into (.+)$", msg)
if match:
src = parse_branch([match.group(1)])[0]
dst = parse_branch([match.group(2)])[0]
msg = "Merge branch {} into {}".format(src, dst)
return msg.split(" ")
match = re.search("Code Review", msg, re.IGNORECASE)
if match:
return "Code Review".split(" ")
return ["<redacted>"]
ParseSpec = namedtuple("ParseSpec", ["header", "proc", "func"])
parse_dict = {
"Author": ParseSpec("Author: ", "[words[1]]", None),
"Commit": ParseSpec("commit ", "[words[1][0:7]]", None),
"Branch": ParseSpec("commit ", "words[2:]", parse_branch),
"ShortDescription": ParseSpec(" ", "", parse_desc),
}
def proc_spec(txt, parse_spec):
for line in txt.split("\n"):
if re.match("^" + parse_spec.header, line):
words = line.strip().split(" ")
if parse_spec.proc:
words = eval(parse_spec.proc)
if parse_spec.func:
words = parse_spec.func(words)
return " ".join(words)
return ""
def commit_text(commit_id=""):
if commit_id:
cmd = "git log -1 --decorate " + commit_id
else:
cmd = "git log --all -1 --decorate"
cp = subprocess.run(cmd, stdout=subprocess.PIPE, shell=True, encoding="utf-8")
return cp.stdout
def commit_info(commit_text):
result = {x: proc_spec(commit_text, y) for x, y in parse_dict.items()}
return result
def info_text(commit_dict):
return "\n".join("%s: %s" % (x, y) for x, y in commit_dict.items())
def submit_to_discord(hook_url, text):
submission = {"content": text}
r = requests.post(hook_url, data=submission)
def main():
timestamp = str(datetime.now())
for char in [" ", ":"]:
timestamp = re.sub(char, "-", timestamp)
commit_id =""
try:
commit_id = sys.argv[1]
except:
pass
commit_txt = commit_text(commit_id)
commit_summary = info_text(commit_info(commit_txt))
# print(commit_txt)
# print(commit_summary)
submit_to_discord(discord_hook_url, commit_summary)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment