From 24a4ba547fc460037ab0e54fcf256b49bc3e368d Mon Sep 17 00:00:00 2001 From: Chris Evich Date: Thu, 1 Mar 2018 14:25:00 -0500 Subject: [PATCH] Add util to retrieve github integration status This can be used (for example) to gate further testing upon success of integrated tasks, such as travis CI results or CLA checking. Signed-off-by: Chris Evich --- utils/github_ref_status.py | 73 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100755 utils/github_ref_status.py diff --git a/utils/github_ref_status.py b/utils/github_ref_status.py new file mode 100755 index 00000000..54d10c28 --- /dev/null +++ b/utils/github_ref_status.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python2 + +""" +Retrieve Status + Context from a github ref (branch, sha) + +Depends on : python & python-requests (2.7) +""" + +import os +import sys +import argparse +try: + import json +except ImportError: + import simplejson as json +import requests + +EPILOG="""Example Usage, block further testing of a PR until Travis CI passes: + +$ ./github_ref_status.py -t -o acme -r anvil | \\ + grep -q 'success overall' && run_more_tests.sh + +""" + +def parse_argv(argv=None): + parser = argparse.ArgumentParser(description=__doc__, + epilog=EPILOG, + formatter_class=argparse.RawTextHelpFormatter) + parser.add_argument('-t', '--token', required=True, + help="Access token for github") + parser.add_argument('-o', '--owner', required=True, + help="Owner name of the repository (left side of slash)") + parser.add_argument('-r', '--repo', required=True, + help="Repository name (right side of slash)") + parser.add_argument('-s', '--showtarget', action='store_true', default=False, + help="Show the 'target' url for each status item") + parser.add_argument('ref', help="SHA, a branch name, or a tag name.") + return parser.parse_args(argv[1:]) + + +def main(argv=None): + options = parse_argv(argv) + if options.showtarget: + stdout = lambda context, state, target: sys.stdout.write("{0} {1} {2}\n".format(context, state, target)) + else: + stdout = lambda context, state, target: sys.stdout.write("{0} {1}\n".format(state, context)) + + # Ref: https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref + url = ("https://api.github.com/repos/{0}/{1}/commits/{2}/status" + "".format(options.owner, options.repo, options.ref)) + target = ("https://github.com/{0}/{1}/commits/{2}" + "".format(options.owner, options.repo, options.ref)) + response = requests.get(url, headers=dict(Authorization="token {0}".format(options.token))) + if response.status_code != 200: + raise ValueError("Response code {0} != 200 while retrieving {1}." + "".format(response.status_code, url)) + response_json = response.json() + overall_state = response_json.get("state") + if not overall_state: + raise ValueError("Response good, but does not include an overall state (yet).") + stdout("overall", overall_state, target) + statuses = response_json.get("statuses", []) + # N/B: Does not cope with any pagination + # Ref: https://developer.github.com/v3/guides/traversing-with-pagination/ + for status in statuses: + context = status.get("context", "") + state = status.get("state", "") + target = status.get("target_url", target) + stdout(context, state, target) + + +if __name__ == '__main__': + main(sys.argv)