Created
December 15, 2014 12:41
-
-
Save darobin/2017b147ed03e9ab4120 to your computer and use it in GitHub Desktop.
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
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