##// END OF EJS Templates
Add option to test without posting results.
Thomas Kluyver -
Show More
@@ -7,7 +7,6 b' except NameError:'
7 pass
7 pass
8
8
9 import requests
9 import requests
10 import keyring
11 import getpass
10 import getpass
12 import json
11 import json
13
12
@@ -15,7 +14,14 b' import json'
15 # password
14 # password
16 fake_username = 'ipython_tools'
15 fake_username = 'ipython_tools'
17
16
17 token = None
18 def get_auth_token():
18 def get_auth_token():
19 global token
20
21 if token is not None:
22 return token
23
24 import keyring
19 token = keyring.get_password('github', fake_username)
25 token = keyring.get_password('github', fake_username)
20 if token is not None:
26 if token is not None:
21 return token
27 return token
@@ -28,9 +34,11 b' def get_auth_token():'
28
34
29 auth_request = {
35 auth_request = {
30 "scopes": [
36 "scopes": [
31 "public_repo"
37 "public_repo",
38 "gist"
32 ],
39 ],
33 "note": "IPython tools"
40 "note": "IPython tools",
41 "note_url": "https://github.com/ipython/ipython/tree/master/tools",
34 }
42 }
35 response = requests.post('https://api.github.com/authorizations',
43 response = requests.post('https://api.github.com/authorizations',
36 auth=(user, pw), data=json.dumps(auth_request))
44 auth=(user, pw), data=json.dumps(auth_request))
@@ -39,4 +47,34 b' def get_auth_token():'
39 keyring.set_password('github', fake_username, token)
47 keyring.set_password('github', fake_username, token)
40 return token
48 return token
41
49
50 def make_auth_header():
51 return {'Authorization': 'token ' + get_auth_token()}
52
53 def post_issue_comment(project, num, body):
54 url = 'https://api.github.com/repos/{project}/issues/{num}/comments'.format(project=project, num=num)
55 payload = json.dumps({'body': body})
56 r = requests.post(url, data=payload, headers=make_auth_header())
57
58 def post_gist(content, description='', filename='file', auth=False):
59 """Post some text to a Gist, and return the URL."""
60 post_data = json.dumps({
61 "description": description,
62 "public": True,
63 "files": {
64 filename: {
65 "content": content
66 }
67 }
68 }).encode('utf-8')
69
70 headers = make_auth_header() if auth else {}
71 response = requests.post("https://api.github.com/gists", data=post_data, headers=headers)
72 response.raise_for_status()
73 response_data = json.loads(response.text)
74 return response_data['html_url']
42
75
76 def get_pull_request(project, num):
77 url = "https://api.github.com/repos/{project}/pulls/{num}".format(project=project, num=num)
78 response = requests.get(url)
79 response.raise_for_status()
80 return json.loads(response.text)
@@ -10,14 +10,16 b' from __future__ import print_function'
10
10
11 import errno
11 import errno
12 from glob import glob
12 from glob import glob
13 import io
13 import json
14 import json
14 import os
15 import os
15 import re
16 import re
16 import requests
17 import requests
17 import shutil
18 import shutil
18 from subprocess import call, check_call, check_output, PIPE, STDOUT, CalledProcessError
19 from subprocess import call, check_call, check_output, PIPE, STDOUT, CalledProcessError
20 import sys
19
21
20 import gh_auth
22 import gh_api
21
23
22 basedir = os.path.join(os.path.expanduser("~"), ".ipy_pr_tests")
24 basedir = os.path.join(os.path.expanduser("~"), ".ipy_pr_tests")
23 repodir = os.path.join(basedir, "ipython")
25 repodir = os.path.join(basedir, "ipython")
@@ -66,10 +68,6 b' def setup():'
66 check_call(['git', 'pull', ipy_repository, 'master'])
68 check_call(['git', 'pull', ipy_repository, 'master'])
67 os.chdir(basedir)
69 os.chdir(basedir)
68
70
69 def get_pull_request(num):
70 url = "https://api.github.com/repos/{project}/pulls/{num}".format(project=gh_project, num=num)
71 return json.loads(requests.get(url).text)
72
73 missing_libs_re = re.compile(r"Tools and libraries NOT available at test time:\n"
71 missing_libs_re = re.compile(r"Tools and libraries NOT available at test time:\n"
74 r"\s*(.*?)\n")
72 r"\s*(.*?)\n")
75 def get_missing_libraries(log):
73 def get_missing_libraries(log):
@@ -108,22 +106,6 b' def run_tests(venv):'
108 except CalledProcessError as e:
106 except CalledProcessError as e:
109 return False, e.output.decode('utf-8')
107 return False, e.output.decode('utf-8')
110
108
111 def post_gist(content, description='IPython test log', filename="results.log"):
112 """Post some text to a Gist, and return the URL."""
113 post_data = json.dumps({
114 "description": description,
115 "public": True,
116 "files": {
117 filename: {
118 "content": content
119 }
120 }
121 }).encode('utf-8')
122
123 response = requests.post("https://api.github.com/gists", data=post_data)
124 response_data = json.loads(response.text)
125 return response_data['html_url']
126
127 def markdown_format(pr, results):
109 def markdown_format(pr, results):
128 def format_result(py, passed, gist_url, missing_libraries):
110 def format_result(py, passed, gist_url, missing_libraries):
129 s = "* %s: " % py
111 s = "* %s: " % py
@@ -149,18 +131,33 b' def markdown_format(pr, results):'
149
131
150 def post_results_comment(pr, results, num):
132 def post_results_comment(pr, results, num):
151 body = markdown_format(pr, results)
133 body = markdown_format(pr, results)
152 url = 'https://api.github.com/repos/{project}/issues/{num}/comments'.format(project=gh_project, num=num)
134 gh_api.post_issue_comment(gh_project, num, body)
153 payload = json.dumps({'body': body})
154 auth_token = gh_auth.get_auth_token()
155 headers = {'Authorization': 'token ' + auth_token}
156 r = requests.post(url, data=payload, headers=headers)
157
135
136 def print_results(pr, results):
137 print("\n")
138 if pr['mergeable']:
139 print("**Test results for commit %s merged into master**" % pr['head']['sha'][:7])
140 else:
141 print("**Test results for commit %s (can't merge cleanly)**" % pr['head']['sha'][:7])
142 print("Platform:", sys.platform)
143 for py, passed, gist_url, missing_libraries in results:
144 if passed:
145 print(py, ":", "OK")
146 else:
147 print(py, ":", "Failed")
148 print(" Test log:", gist_url)
149 if missing_libraries:
150 print(" Libraries not available:", missing_libraries)
151 print("Not available for testing:", ", ".join(unavailable_pythons))
158
152
159 if __name__ == '__main__':
153 def test_pr(num, post_results=True):
160 import sys
154 # Get Github authorisation first, so that the user is prompted straight away
161 num = sys.argv[1]
155 # if their login is needed.
156 if post_results:
157 gh_api.get_auth_token()
158
162 setup()
159 setup()
163 pr = get_pull_request(num)
160 pr = gh_api.get_pull_request(gh_project, num)
164 get_branch(repo=pr['head']['repo']['clone_url'],
161 get_branch(repo=pr['head']['repo']['clone_url'],
165 branch=pr['head']['ref'],
162 branch=pr['head']['ref'],
166 owner=pr['head']['repo']['owner']['login'],
163 owner=pr['head']['repo']['owner']['login'],
@@ -174,23 +171,27 b" if __name__ == '__main__':"
174 if passed:
171 if passed:
175 results.append((py, True, None, missing_libraries))
172 results.append((py, True, None, missing_libraries))
176 else:
173 else:
177 gist_url = post_gist(log)
174 if post_results:
178 results.append((py, False, gist_url, missing_libraries))
175 result_locn = gh_api.post_gist(log, description='IPython test log',
176 filename="results.log", auth=True)
177 else:
178 result_locn = os.path.join(venv, pr['head']['sha'][:7]+".log")
179 with io.open(result_locn, 'w', encoding='utf-8') as f:
180 f.write(log)
181 results.append((py, False, result_locn, missing_libraries))
179
182
180 print("\n")
183 print_results(pr, results)
181 if pr['mergeable']:
184 if post_results:
182 print("**Test results for commit %s merged into master**" % pr['head']['sha'][:7])
185 post_results_comment(pr, results, num)
183 else:
186 print("(Posted to Github)")
184 print("**Test results for commit %s (can't merge cleanly)**" % pr['head']['sha'][:7])
187
185 print("Platform:", sys.platform)
188
186 for py, passed, gist_url, missing_libraries in results:
189 if __name__ == '__main__':
187 if passed:
190 import argparse
188 print(py, ":", "OK")
191 parser = argparse.ArgumentParser(description="Test an IPython pull request")
189 else:
192 parser.add_argument('-l', '--local', action='store_true',
190 print(py, ":", "Failed")
193 help="Don't publish the results to Github")
191 print(" Test log:", gist_url)
194 parser.add_argument('number', type=int, help="The pull request number")
192 if missing_libraries:
195
193 print(" Libraries not available:", missing_libraries)
196 args = parser.parse_args()
194 print("Not available for testing:", ", ".join(unavailable_pythons))
197 test_pr(args.number, post_results=(not args.local))
195 post_results_comment(pr, results, num)
196 print("(Posted to Github)")
General Comments 0
You need to be logged in to leave comments. Login now