Skip to content

Instantly share code, notes, and snippets.

@stas00
Forked from rubys/PushEvent.py
Created September 23, 2018 20:41
Show Gist options
  • Save stas00/007681c869705eec6d9a6921445af851 to your computer and use it in GitHub Desktop.
Save stas00/007681c869705eec6d9a6921445af851 to your computer and use it in GitHub Desktop.
Allow git-multimail to run as a webhook for GitHub
#!/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