From 6ceb0bb2a46fdc20a797fa3c92ace7080b3de62f 2012-05-02 22:04:37 From: Thomas Kluyver Date: 2012-05-02 22:04:37 Subject: [PATCH] PR tester can now post results to Github as a comment. --- diff --git a/tools/gh_auth.py b/tools/gh_auth.py new file mode 100644 index 0000000..60c1e6e --- /dev/null +++ b/tools/gh_auth.py @@ -0,0 +1,42 @@ +"""Functions for Github authorisation.""" +from __future__ import print_function + +try: + input = raw_input +except NameError: + pass + +import requests +import keyring +import getpass +import json + +# Keyring stores passwords by a 'username', but we're not storing a username and +# password +fake_username = 'ipython_tools' + +def get_auth_token(): + token = keyring.get_password('github', fake_username) + if token is not None: + return token + + print("Please enter your github username and password. These are not " + "stored, only used to get an oAuth token. You can revoke this at " + "any time on Github.") + user = input("Username: ") + pw = getpass.getpass("Password: ") + + auth_request = { + "scopes": [ + "public_repo" + ], + "note": "IPython tools" + } + response = requests.post('https://api.github.com/authorizations', + auth=(user, pw), data=json.dumps(auth_request)) + response.raise_for_status() + token = json.loads(response.text)['token'] + keyring.set_password('github', fake_username, token) + return token + + diff --git a/tools/test_pr.py b/tools/test_pr.py index 9796e64..65fbd96 100755 --- a/tools/test_pr.py +++ b/tools/test_pr.py @@ -13,6 +13,7 @@ from glob import glob import json import os import re +import requests import shutil from subprocess import call, check_call, check_output, PIPE, STDOUT, CalledProcessError try: @@ -20,9 +21,12 @@ try: except ImportError: from urllib2 import urlopen +import gh_auth + basedir = os.path.join(os.path.expanduser("~"), ".ipy_pr_tests") repodir = os.path.join(basedir, "ipython") ipy_repository = 'git://github.com/ipython/ipython.git' +gh_project="ipython/ipython" supported_pythons = ['python2.6', 'python2.7', 'python3.1', 'python3.2'] unavailable_pythons = [] @@ -66,8 +70,8 @@ def setup(): check_call(['git', 'pull', ipy_repository, 'master']) os.chdir(basedir) -def get_pull_request(num, project="ipython/ipython"): - url = "https://api.github.com/repos/{project}/pulls/{num}".format(project=project, num=num) +def get_pull_request(num): + url = "https://api.github.com/repos/{project}/pulls/{num}".format(project=gh_project, num=num) response = urlopen(url).read().decode('utf-8') return json.loads(response) @@ -102,7 +106,7 @@ def run_tests(venv): try: return True, check_output([iptest], stderr=STDOUT).decode('utf-8') except CalledProcessError as e: - return False, e.output + return False, e.output.decode('utf-8') def post_gist(content, description='IPython test log', filename="results.log"): """Post some text to a Gist, and return the URL.""" @@ -120,6 +124,34 @@ def post_gist(content, description='IPython test log', filename="results.log"): response_data = json.loads(response.read().decode('utf-8')) return response_data['html_url'] +def markdown_format(pr, results): + def format_result(py, passed, gist_url, missing_libraries): + s = "* %s: " % py + if passed: + s += "OK" + else: + s += "Failed, log at %s" % gist_url + if missing_libraries: + s += " (libraries not available: " + missing_libraries + ")" + return s + + lines = ["**Test results for commit %s merged into master**" % pr['head']['sha'][:7], + "Platform: " + sys.platform, + ""] + \ + [format_result(*r) for r in results] + \ + ["", + "Not available for testing:" + ", ".join(unavailable_pythons)] + return "\n".join(lines) + +def post_results_comment(pr, results, num): + body = markdown_format(pr, results) + url = 'https://api.github.com/repos/{project}/issues/{num}/comments'.format(project=gh_project, num=num) + payload = json.dumps({'body': body}) + auth_token = gh_auth.get_auth_token() + headers = {'Authorization': 'token ' + auth_token} + r = requests.post(url, data=payload, headers=headers) + + if __name__ == '__main__': import sys num = sys.argv[1] @@ -151,3 +183,5 @@ if __name__ == '__main__': if missing_libraries: print(" Libraries not available:", missing_libraries) print("Not available for testing:", ", ".join(unavailable_pythons)) + post_results_comment(pr, results, num) + print("(Posted to Github)")