Skip to content

Commit 89f11e9

Browse files
committed
Merge pull request ARMmbed#1367 from bridadan/parse_testreport
Add script that can upload build status and test reports to a CI database
2 parents 74b345e + 3e9b838 commit 89f11e9

File tree

1 file changed

+174
-0
lines changed

1 file changed

+174
-0
lines changed

workspace_tools/upload_results.py

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
"""
2+
mbed SDK
3+
Copyright (c) 2011-2013 ARM Limited
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
"""
17+
import sys
18+
import argparse
19+
import xml.etree.ElementTree as ET
20+
import requests
21+
import urlparse
22+
23+
def create_headers(args):
24+
return { 'X-Api-Key': args.api_key }
25+
26+
def finish_command(command, response):
27+
print(command, response.status_code, response.reason)
28+
print(response.text)
29+
30+
if response.status_code < 400:
31+
sys.exit(0)
32+
else:
33+
sys.exit(2)
34+
35+
def create_build(args):
36+
build = {}
37+
build['buildType'] = args.build_type
38+
build['number'] = args.build_number
39+
build['source'] = args.build_source
40+
build['status'] = 'running'
41+
42+
if build['buildType'] == 'Pull_Request':
43+
build['buildType'] = 'Pull Request'
44+
45+
r = requests.post(urlparse.urljoin(args.url, "api/builds"), headers=create_headers(args), json=build)
46+
47+
if r.status_code < 400:
48+
if args.property_file_format:
49+
print("MBED_BUILD_ID=" + r.text)
50+
else:
51+
print(r.text)
52+
53+
sys.exit(0)
54+
else:
55+
sys.exit(2)
56+
57+
def finish_build(args):
58+
data = {}
59+
data['status'] = 'completed'
60+
61+
r = requests.put(urlparse.urljoin(args.url, "api/builds/" + args.build_id), headers=create_headers(args), json=data)
62+
finish_command('finish-build', r)
63+
64+
def abort_build(args):
65+
data = {}
66+
data['status'] = 'aborted'
67+
68+
r = requests.put(urlparse.urljoin(args.url, "api/builds/" + args.build_id), headers=create_headers(args), json=data)
69+
finish_command('abort-build', r)
70+
71+
def add_test_runs(args):
72+
tree = None
73+
74+
try:
75+
tree = ET.parse(args.test_report)
76+
except:
77+
print(sys.exc_info()[0])
78+
print('Invalid path to test report.')
79+
sys.exit(1)
80+
81+
test_suites = tree.getroot()
82+
83+
ts_data = {}
84+
ts_data['testRuns'] = []
85+
86+
platforms_set = set()
87+
toolchains_set = set()
88+
testIds_set = set()
89+
hostOses_set = set()
90+
91+
hostOses_set.add(args.host_os)
92+
93+
for test_suite in test_suites:
94+
platform = ""
95+
toolchain = ""
96+
for properties in test_suite.findall('properties'):
97+
for property in properties.findall('property'):
98+
if property.attrib['name'] == 'target':
99+
platform = property.attrib['value']
100+
platforms_set.add(platform)
101+
elif property.attrib['name'] == 'toolchain':
102+
toolchain = property.attrib['value']
103+
toolchains_set.add(toolchain)
104+
105+
for test_case in test_suite.findall('testcase'):
106+
testRun = {}
107+
testRun['build'] = args.build_id
108+
testRun['hostOs'] = args.host_os
109+
testRun['platform'] = platform
110+
testRun['toolchain'] = toolchain
111+
testRun['test'] = test_case.attrib['classname'].split('.')[-1]
112+
113+
testIds_set.add(testRun['test'])
114+
115+
system_outs = test_case.findall('system-out')
116+
117+
if system_outs:
118+
testRun['output'] = system_outs[0].text
119+
else:
120+
testRun['output'] = ""
121+
122+
errors = test_case.findall('error')
123+
124+
if errors:
125+
testRun['pass'] = False
126+
testRun['result'] = errors[0].attrib['message']
127+
else:
128+
testRun['pass'] = True
129+
testRun['result'] = 'OK'
130+
131+
ts_data['testRuns'].append(testRun)
132+
133+
ts_data['platforms'] = list(platforms_set)
134+
ts_data['toolchains'] = list(toolchains_set)
135+
ts_data['testIds'] = list(testIds_set)
136+
ts_data['hostOses'] = list(hostOses_set)
137+
138+
r = requests.post(urlparse.urljoin(args.url, "api/testRuns"), headers=create_headers(args), json=ts_data)
139+
finish_command('add-test-runs', r)
140+
141+
def main(arguments):
142+
# Register and parse command line arguments
143+
parser = argparse.ArgumentParser()
144+
parser.add_argument('-u', '--url', required=True, help='url to ci site')
145+
parser.add_argument('-k', '--api-key', required=True, help='api-key for posting data')
146+
147+
subparsers = parser.add_subparsers(help='subcommand help')
148+
149+
create_build_parser = subparsers.add_parser('create-build', help='create a new build')
150+
create_build_parser.add_argument('-b', '--build-number', required=True, help='build number')
151+
create_build_parser.add_argument('-T', '--build-type', choices=['Nightly', 'Limited', 'Pull_Request'], required=True, help='type of build')
152+
create_build_parser.add_argument('-s', '--build-source', required=True, help='url to source of build')
153+
create_build_parser.add_argument('-p', '--property-file-format', action='store_true', help='print result in the property file format')
154+
create_build_parser.set_defaults(func=create_build)
155+
156+
finish_build_parser = subparsers.add_parser('finish-build', help='finish a running build')
157+
finish_build_parser.add_argument('-b', '--build-id', required=True, help='build id')
158+
finish_build_parser.set_defaults(func=finish_build)
159+
160+
abort_build_parser = subparsers.add_parser('abort-build', help='abort a running build')
161+
abort_build_parser.add_argument('-b', '--build-id', required=True, help='build id')
162+
abort_build_parser.set_defaults(func=abort_build)
163+
164+
add_test_runs_parser = subparsers.add_parser('add-test-runs', help='add test runs to a build')
165+
add_test_runs_parser.add_argument('-b', '--build-id', required=True, help='build id')
166+
add_test_runs_parser.add_argument('-t', '--test-report', required=True, help='path to junit xml test report')
167+
add_test_runs_parser.add_argument('-o', '--host-os', required=True, help='host os on which test was run')
168+
add_test_runs_parser.set_defaults(func=add_test_runs)
169+
170+
args = parser.parse_args(arguments)
171+
args.func(args)
172+
173+
if __name__ == '__main__':
174+
main(sys.argv[1:])

0 commit comments

Comments
 (0)