Skip to content

Instantly share code, notes, and snippets.

@darobin
Created December 15, 2014 12:41
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 darobin/2017b147ed03e9ab4120 to your computer and use it in GitHub Desktop.
Save darobin/2017b147ed03e9ab4120 to your computer and use it in GitHub Desktop.
root@grumple:~# diff -bu /tmp/sync.py /u/www.w3c-test.org/webhook/sync.py
--- /tmp/sync.py 2014-12-15 12:28:50.233509316 +0000
+++ /u/www.w3c-test.org/webhook/sync.py 2014-05-29 12:05:59.613261034 +0000
@@ -8,10 +8,12 @@
import ConfigParser
import getpass
import hmac
+import itertools
+import lockfile
import requests
-config_path = "~/sync.ini"
+config_path = "/home/github/sync.ini"
class MasterCheckout(object):
def __init__(self, path):
@@ -89,9 +91,15 @@
return True
def get_authorised_users(config):
- resp = requests.get("https://api.github.com/repos/%s/%s/collaborators" % (config["org_name"], config["repo_name"]),
+ result = set()
+ for i in itertools.count(1):
+ resp = requests.get("https://api.github.com/repos/%s/%s/collaborators?per_page=100&page=%s" % (config["org_name"], config["repo_name"], i),
auth=(config["username"], config["password"]))
- return set(item["login"] for item in resp.json())
+ data = resp.json
+ result |= set(item["login"] for item in data)
+ if len(data) < 100:
+ break
+ return result
def process_pull_request(config, data, user_is_authorised):
base_path = config["base_path"]
@@ -144,10 +152,11 @@
return
else:
update_master(config["base_path"])
- pull_request_number = int(data["issue"]["pull_request"]["diff_url"].rsplit("/", 1)[1])
+ filename = data["issue"]["pull_request"]["html_url"].rsplit("/", 1)[1]
+ pull_request_number = int(os.path.splitext(filename)[0])
action_handlers = {"mirror":start_mirror,
"unmirror":end_mirror}
- action_handlers[command(comment)](base_path, pull_request_number, user_is_authorised)
+ action_handlers[command(comment)](config["base_path"], pull_request_number, user_is_authorised)
def update_master(base_path):
checkout = MasterCheckout(base_path)
@@ -163,23 +172,28 @@
if PullRequestCheckout.exists(base_path, number):
PullRequestCheckout(os.path.join(submissions_path, str(number)), number).update()
-def post_authentic(config, body):
- signature = os.environ.get("HTTP_X_HUB_SIGNATURE", None)
+def post_authentic(config, body, signature):
if not signature:
print >> sys.stderr, "Signature missing"
return False
expected = "sha1=%s" % hmac.new(config["secret"], body).hexdigest()
print >> sys.stderr, "Signature got %s, expected %s" %(signature, expected)
+ #XXX disable this for now
+ return True
return signature == expected
-def main(config):
- data = sys.stdin.read()
+def main(request, response):
+ config = get_config()
+ data = request.body
+ lock = lockfile.FileLock(config["lockfile"])
+ try:
+ lock.acquire(timeout=120)
if data:
print >> sys.stderr, data
-# if not post_authentic(config, data):
-# print >> sys.stderr, "Got message with incorrect signature"
-# return
+ if not post_authentic(config, data, request.headers["X-Hub-Signature"]):
+ print >> sys.stderr, "Got message with incorrect signature"
+ return
data = json.loads(data)
authorised_users = get_authorised_users(config)
@@ -187,21 +201,31 @@
if "commits" in data:
process_push(config)
else:
- user_is_authorised = data["user"]["login"] in authorised_users
- if "pull_request" in data:
- process_pull_request(config, data, user_is_authorised)
- elif "comment" in data:
- process_issue_comment(config, data, user_is_authorised)
- else:
+ handlers = {"pull_request":process_pull_request,
+ "comment":process_issue_comment}
+ found = False
+ for key, handler in handlers.iteritems():
+ if key in data:
+ found = True
+ user_is_authorised = data[key]["user"]["login"] in authorised_users
+ handler(config, data, user_is_authorised)
+ break
+
+ if not found:
print >> sys.stderr, "Unrecognised event type with keys %r" % (data.keys(),)
- else:
+
+ #else:
#This is a test, presumably, just update master
- update_master(config["base_path"])
- update_pull_requests(config["base_path"])
+ #update_master(config["base_path"])
+ #update_pull_requests(config["base_path"])
+ except lockfile.LockTimeout:
+ print >> sys.stderr, "Lock file detected for payload %s" % request.headers["X-GitHub-Delivery"]
+ sys.exit(1)
+ finally:
+ lock.release()
- print "Content-Type: text/plain"
- print "\r"
- print "Success"
+ response.headers.append("Content-Type", "text/plain")
+ return "Success"
def create_master(config):
base_path = config["base_path"]
@@ -213,7 +237,7 @@
def get_open_pull_request_numbers(config):
authorised_users = get_authorised_users(config)
pull_requests = requests.get("https://api.github.com/repos/%s/%s/pulls" % (config["org_name"], config["repo_name"]),
- auth=(config["username"], config["password"])).json()
+ auth=(config["username"], config["password"])).json
return [item["number"] for item in pull_requests if item["state"] == "open" and item["user"]["login"] in authorised_users]
def setup(config):
@@ -249,6 +273,3 @@
config = get_config()
if "--setup" in sys.argv:
setup(config)
- else:
- main(config)
-
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment