Last active
September 23, 2018 20:41
-
-
Save rubys/30e84daf5aa22025fe72 to your computer and use it in GitHub Desktop.
Allow git-multimail to run as a webhook for GitHub
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
from __future__ import print_function | |
# | |
# A simple CGI script useful for debugging GitHub web hooks | |
# https://developer.github.com/webhooks/ | |
# | |
import hashlib, hmac, json, os, sys, traceback | |
from subprocess import Popen, PIPE, STDOUT | |
try: | |
from html import escape # Python >= 3.2 | |
except ImportError: | |
from cgi import escape | |
try: | |
from urllib.parse import unquote_plus # Python 3 | |
except ImportError: | |
from urllib import unquote_plus | |
######################################################################## | |
# Shared secret with GitHub. Should NOT be encoded in this script. See: | |
# https://developer.github.com/webhooks/securing/ | |
token = os.environ.get('SECRET_TOKEN', '') | |
######################################################################## | |
if os.environ.get('REQUEST_METHOD', '').upper() == 'POST': | |
# read and decode event payload | |
payload = sys.stdin.read() | |
if payload.startswith('payload='): payload=unquote_plus(payload[8:]) | |
# compute signature | |
signature = 'sha1=' + hmac.new(token, payload, hashlib.sha1).hexdigest() | |
# write log | |
log = open('data/' + signature[5:], 'w') | |
log.write(json.dumps(dict(os.environ), indent=2, sort_keys=True)) | |
log.write("\n\nSignature expected: %s\n\n" % repr(signature)) | |
log.write(payload) | |
# validate signature | |
if not token or os.environ.get('HTTP_X_HUB_SIGNATURE', '') == signature: | |
try: | |
log.write("\n\nSignature OK") | |
# parse JSON | |
event = json.loads(payload) | |
# log parsed results | |
log.write("\n\nParsed event:\n") | |
log.write(json.dumps(event, indent=2)) | |
# Need to do the following in a local copy of the repository in question: | |
# 'git pull origin ' + event['ref'] | |
# gather and log input for post-receive | |
update = "%(before)s %(after)s %(ref)s\n" % event | |
log.write("\n\nData to be passed to post-receive hook:\n") | |
log.write(update) | |
# invoke post-receive hook | |
# NOTE: this is being stubbed with 'cat' for now | |
# NOTE: stderr will show up in the web server's error log | |
process = Popen(['cat'], stdin=PIPE, stdout=PIPE) | |
response = process.communicate(input=update)[0] | |
# log response | |
log.write("\nHook response:\n%s\n" % response) | |
log.write("\nExit code: %s\n" % process.returncode) | |
print("Status: 200 OK\r\nContent-Type: text/plain\r\n\r\nOK") | |
except: | |
print("Status: 500 Internal error\r\nContent-Type: text/plain\r\n\r") | |
traceback.print_exc(file=sys.stdout) | |
else: | |
log.write("\n\nBAD Signature") | |
print("Status: 422 BadSig\r\nContent-Type: text/plain\r\n\r\nBadSig") | |
else: | |
# Produce an HTML form useful for debugging purposes | |
# NOTE: will fail with a BAD Signature if a signature is configured | |
print("""Status: 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE html> | |
<html><head><title>test form</title></head><body><p>Payload:</p> | |
<form method=POST><textarea name=payload cols=80 rows=20></textarea> | |
<br><input type=submit><hr><table>""") | |
# Add a dump of CGI environment variables | |
for name, value in os.environ.iteritems(): | |
print("<tr><td>%s</td><td>%s</td></tr>" % (escape(name), escape(value))) | |
print("</table></body></html>") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment