X-Git-Url: https://git.ralfj.de/git-mirror.git/blobdiff_plain/d82914054bb75574c2675649a943025e57fa8680..301520c0234eb50350361fac263bcebd2db139c2:/webhook-core.py?ds=inline diff --git a/webhook-core.py b/webhook-core.py index a9418bc..dcb7250 100755 --- a/webhook-core.py +++ b/webhook-core.py @@ -24,44 +24,66 @@ #============================================================================== # This is the hook called by GitHub as webhook. It updats the local repository, and then all the other mirrors. -import sys, traceback +import sys, traceback, json from git_mirror import * +def get_github_payload(repo, signature): + '''Return the github-style JSON encoded payload (as if we were called as a github webhook)''' + data = sys.stdin.buffer.read() + verify_signature = repo.compute_hmac(data) + if signature != "sha1="+verify_signature: + raise Exception("You are not GitHub!") + try: + data = json.loads(data.decode('utf-8')) + return data + except ValueError: + return {} # nothing read + + if __name__ == "__main__": + # call this with: repo = None # we will try to use this during exception handling try: repos = load_repos() - reponame = sys.argv[1] if len(sys.argv) > 1 else None + if len(sys.argv) < 4: + raise Exception("Usage: {0} ".format(os.path.basename(sys.argv[0]))) + reponame = sys.argv[1] + githubEvent = sys.argv[2] + githubSignature = sys.argv[3] if reponame not in repos: raise Exception("Repository missing or not found.") repo = repos[reponame] # now sync this repository - data = get_github_payload() - if 'zen' in data: + data = get_github_payload(repo, githubSignature) + if githubEvent == 'ping': # github sends this initially print("Content-Type: text/plain") print() - print("Welcome!") + print("Pong!") sys.exit(0) - ref = data["ref"] - oldsha = data["before"] - newsha = data["after"] - # validate the ref name - if re.match('refs/[a-z/]+', ref) is None: - raise Exception("Invalid ref name {0}".format(ref)) - # collect URLs of this repository, to find the mirror name - urls = [] - for key in ("git_url", "ssh_url", "clone_url"): - urls.append(data["repository"][key]) - mirror = repo.find_mirror_by_url(urls) - if mirror is None: - raise Exception("Could not find the mirror.") - repo.update_ref_from_mirror(ref, oldsha, newsha, mirror, suppress_stderr = True) - # print an answer - print("Content-Type: text/plain") - print() - print("Updated {0}:{1} from mirror {2} from {3} to {4}".format(reponame, ref, mirror, oldsha, newsha)) + elif githubEvent == 'push': + ref = data["ref"] + oldsha = data["before"] + newsha = data["after"] + # validate the ref name + if re.match('refs/[a-z/]+', ref) is None: + raise Exception("Invalid ref name {0}".format(ref)) + # collect URLs of this repository, to find the mirror name + urls = [] + for key in ("git_url", "ssh_url", "clone_url"): + urls.append(data["repository"][key]) + mirror = repo.find_mirror_by_url(urls) + if mirror is None: + raise Exception("Could not find the mirror.") + stdout = repo.update_ref_from_mirror(ref, oldsha, newsha, mirror, suppress_stderr = True) + # print an answer + print("Content-Type: text/plain") + print() + print("Updated {0}:{1} from mirror {2} from {3} to {4}".format(reponame, ref, mirror, oldsha, newsha)) + print(stdout) + else: + raise Exception("Unexpected github event {0}.".format(githubEvent)) except Exception as e: if repo is not None: repo.mail_owner("There was a problem running the git-mirror webhook:\n\n{0}".format(traceback.format_exc()))