Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-tools by
upload_results.py
00001 """ 00002 mbed SDK 00003 Copyright (c) 2011-2013 ARM Limited 00004 00005 Licensed under the Apache License, Version 2.0 (the "License"); 00006 you may not use this file except in compliance with the License. 00007 You may obtain a copy of the License at 00008 00009 http://www.apache.org/licenses/LICENSE-2.0 00010 00011 Unless required by applicable law or agreed to in writing, software 00012 distributed under the License is distributed on an "AS IS" BASIS, 00013 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 See the License for the specific language governing permissions and 00015 limitations under the License. 00016 """ 00017 import sys 00018 import argparse 00019 import xml.etree.ElementTree as ET 00020 import requests 00021 import urlparse 00022 00023 def create_headers(args): 00024 return { 'X-Api-Key': args.api_key } 00025 00026 def finish_command(command, response): 00027 print(command, response.status_code, response.reason) 00028 print(response.text) 00029 00030 if response.status_code < 400: 00031 sys.exit(0) 00032 else: 00033 sys.exit(2) 00034 00035 def create_build(args): 00036 build = {} 00037 build['buildType'] = args.build_type 00038 build['number'] = args.build_number 00039 build['source'] = args.build_source 00040 build['status'] = 'running' 00041 00042 r = requests.post(urlparse.urljoin(args.url, "api/builds"), headers=create_headers(args), json=build) 00043 00044 if r.status_code < 400: 00045 if args.property_file_format: 00046 print("MBED_BUILD_ID=" + r.text) 00047 else: 00048 print(r.text) 00049 00050 sys.exit(0) 00051 else: 00052 sys.exit(2) 00053 00054 def finish_build(args): 00055 data = {} 00056 data['status'] = 'completed' 00057 00058 r = requests.put(urlparse.urljoin(args.url, "api/builds/" + args.build_id), headers=create_headers(args), json=data) 00059 finish_command('finish-build', r) 00060 00061 def promote_build(args): 00062 data = {} 00063 data['buildType'] = 'Release' 00064 00065 r = requests.put(urlparse.urljoin(args.url, "api/builds/" + args.build_id), headers=create_headers(args), json=data) 00066 finish_command('promote-build', r) 00067 00068 def abort_build(args): 00069 data = {} 00070 data['status'] = 'aborted' 00071 00072 r = requests.put(urlparse.urljoin(args.url, "api/builds/" + args.build_id), headers=create_headers(args), json=data) 00073 finish_command('abort-build', r) 00074 00075 def add_project_runs (args): 00076 ''' 00077 ------------------------------------- 00078 Notes on 'project_run_data' structure: 00079 -------------------------------------- 00080 'projectRuns' - Tree structure used to keep track of what projects have 00081 been logged in different report files. The tree is organized as follows: 00082 00083 'projectRuns': { - Root element of tree 00084 00085 'hostOs': { - Host OS on which project was built/tested 00086 - ex. windows, linux, or mac 00087 00088 'platform': { - Platform for which project was built/tested 00089 (Corresponds to platform names in targets.py) 00090 - ex. K64F, LPC1768, NRF51822, etc. 00091 00092 'toolchain': { - Toolchain with which project was built/tested 00093 (Corresponds to TOOLCHAIN_CLASSES names in toolchains/__init__.py) 00094 - ex. ARM, uARM, GCC_ARM, etc. 00095 00096 'project': { - Project that was build/tested 00097 (Corresponds to test id in tests.py or library id in libraries.py) 00098 - For tests, ex. MBED_A1, MBED_11, DTCT_1 etc. 00099 - For libraries, ex. MBED, RTX, RTOS, etc. 00100 00101 }, 00102 ... 00103 }, 00104 ... 00105 }, 00106 ... 00107 } 00108 } 00109 00110 'platforms_set' - Set of all the platform names mentioned in the given report files 00111 00112 'toolchains_set' - Set of all the toolchain names mentioned in the given report files 00113 00114 'names_set' - Set of all the project names mentioned in the given report files 00115 00116 'hostOses_set' - Set of all the host names given (only given by the command line arguments) 00117 ''' 00118 00119 project_run_data = {} 00120 project_run_data['projectRuns'] = {} 00121 project_run_data['platforms_set'] = set() 00122 project_run_data['vendors_set'] = set() 00123 project_run_data['toolchains_set'] = set() 00124 project_run_data['names_set'] = set() 00125 project_run_data['hostOses_set'] = set() 00126 project_run_data['hostOses_set'].add(args.host_os) 00127 00128 add_report(project_run_data, args.build_report, True, args.build_id, args.host_os) 00129 00130 if (args.test_report): 00131 add_report(project_run_data, args.test_report, False, args.build_id, args.host_os) 00132 00133 ts_data = format_project_run_data(project_run_data) 00134 r = requests.post(urlparse.urljoin(args.url, "api/projectRuns"), headers=create_headers(args), json=ts_data) 00135 finish_command('add-project-runs', r) 00136 00137 def format_project_run_data(project_run_data): 00138 ts_data = {} 00139 ts_data['projectRuns'] = [] 00140 00141 for hostOs in project_run_data['projectRuns'].values(): 00142 for platform in hostOs.values(): 00143 for toolchain in platform.values(): 00144 for project in toolchain.values(): 00145 ts_data['projectRuns'].append(project) 00146 00147 ts_data['platforms'] = list(project_run_data['platforms_set']) 00148 ts_data['vendors'] = list(project_run_data['vendors_set']) 00149 ts_data['toolchains'] = list(project_run_data['toolchains_set']) 00150 ts_data['names'] = list(project_run_data['names_set']) 00151 ts_data['hostOses'] = list(project_run_data['hostOses_set']) 00152 00153 return ts_data 00154 00155 def find_project_run(projectRuns, project): 00156 keys = ['hostOs', 'platform', 'toolchain', 'project'] 00157 00158 elem = projectRuns 00159 00160 for key in keys: 00161 if not project[key] in elem: 00162 return None 00163 00164 elem = elem[project[key]] 00165 00166 return elem 00167 00168 def add_project_run(projectRuns, project): 00169 keys = ['hostOs', 'platform', 'toolchain'] 00170 00171 elem = projectRuns 00172 00173 for key in keys: 00174 if not project[key] in elem: 00175 elem[project[key]] = {} 00176 00177 elem = elem[project[key]] 00178 00179 elem[project['project']] = project 00180 00181 def update_project_run_results(project_to_update, project, is_build): 00182 if is_build: 00183 project_to_update['buildPass'] = project['buildPass'] 00184 project_to_update['buildResult'] = project['buildResult'] 00185 project_to_update['buildOutput'] = project['buildOutput'] 00186 else: 00187 project_to_update['testPass'] = project['testPass'] 00188 project_to_update['testResult'] = project['testResult'] 00189 project_to_update['testOutput'] = project['testOutput'] 00190 00191 def update_project_run(projectRuns, project, is_build): 00192 found_project = find_project_run(projectRuns, project) 00193 if found_project: 00194 update_project_run_results(found_project, project, is_build) 00195 else: 00196 add_project_run(projectRuns, project) 00197 00198 def add_report(project_run_data, report_file, is_build, build_id, host_os): 00199 tree = None 00200 00201 try: 00202 tree = ET.parse(report_file) 00203 except: 00204 print(sys.exc_info()[0]) 00205 print('Invalid path to report: %s', report_file) 00206 sys.exit(1) 00207 00208 test_suites = tree.getroot() 00209 00210 for test_suite in test_suites: 00211 platform = "" 00212 toolchain = "" 00213 vendor = "" 00214 for properties in test_suite.findall('properties'): 00215 for property in properties.findall('property'): 00216 if property.attrib['name'] == 'target': 00217 platform = property.attrib['value'] 00218 project_run_data['platforms_set'].add(platform) 00219 elif property.attrib['name'] == 'toolchain': 00220 toolchain = property.attrib['value'] 00221 project_run_data['toolchains_set'].add(toolchain) 00222 elif property.attrib['name'] == 'vendor': 00223 vendor = property.attrib['value'] 00224 project_run_data['vendors_set'].add(vendor) 00225 00226 for test_case in test_suite.findall('testcase'): 00227 projectRun = {} 00228 projectRun['build'] = build_id 00229 projectRun['hostOs'] = host_os 00230 projectRun['platform'] = platform 00231 projectRun['toolchain'] = toolchain 00232 projectRun['project'] = test_case.attrib['classname'].split('.')[-1] 00233 projectRun['vendor'] = vendor 00234 00235 project_run_data['names_set'].add(projectRun['project']) 00236 00237 should_skip = False 00238 skips = test_case.findall('skipped') 00239 00240 if skips: 00241 should_skip = skips[0].attrib['message'] == 'SKIP' 00242 00243 if not should_skip: 00244 system_outs = test_case.findall('system-out') 00245 00246 output = "" 00247 if system_outs: 00248 output = system_outs[0].text 00249 00250 if is_build: 00251 projectRun['buildOutput'] = output 00252 else: 00253 projectRun['testOutput'] = output 00254 00255 errors = test_case.findall('error') 00256 failures = test_case.findall('failure') 00257 projectRunPass = None 00258 result = None 00259 00260 if errors: 00261 projectRunPass = False 00262 result = errors[0].attrib['message'] 00263 elif failures: 00264 projectRunPass = False 00265 result = failures[0].attrib['message'] 00266 elif skips: 00267 projectRunPass = True 00268 result = skips[0].attrib['message'] 00269 else: 00270 projectRunPass = True 00271 result = 'OK' 00272 00273 if is_build: 00274 projectRun['buildPass'] = projectRunPass 00275 projectRun['buildResult'] = result 00276 else: 00277 projectRun['testPass'] = projectRunPass 00278 projectRun['testResult'] = result 00279 00280 update_project_run(project_run_data['projectRuns'], projectRun, is_build) 00281 00282 def main(arguments): 00283 # Register and parse command line arguments 00284 parser = argparse.ArgumentParser() 00285 parser.add_argument('-u', '--url', required=True, help='url to ci site') 00286 parser.add_argument('-k', '--api-key', required=True, help='api-key for posting data') 00287 00288 subparsers = parser.add_subparsers(help='subcommand help') 00289 00290 create_build_parser = subparsers.add_parser('create-build', help='create a new build') 00291 create_build_parser.add_argument('-b', '--build-number', required=True, help='build number') 00292 create_build_parser.add_argument('-T', '--build-type', choices=['Nightly', 'Limited', 'Pull_Request', 'Release_Candidate'], required=True, help='type of build') 00293 create_build_parser.add_argument('-s', '--build-source', required=True, help='url to source of build') 00294 create_build_parser.add_argument('-p', '--property-file-format', action='store_true', help='print result in the property file format') 00295 create_build_parser.set_defaults(func=create_build) 00296 00297 finish_build_parser = subparsers.add_parser('finish-build', help='finish a running build') 00298 finish_build_parser.add_argument('-b', '--build-id', required=True, help='build id') 00299 finish_build_parser.set_defaults(func=finish_build) 00300 00301 finish_build_parser = subparsers.add_parser('promote-build', help='promote a build to a release') 00302 finish_build_parser.add_argument('-b', '--build-id', required=True, help='build id') 00303 finish_build_parser.set_defaults(func=promote_build) 00304 00305 abort_build_parser = subparsers.add_parser('abort-build', help='abort a running build') 00306 abort_build_parser.add_argument('-b', '--build-id', required=True, help='build id') 00307 abort_build_parser.set_defaults(func=abort_build) 00308 00309 add_project_runs_parser = subparsers.add_parser('add-project-runs', help='add project runs to a build') 00310 add_project_runs_parser.add_argument('-b', '--build-id', required=True, help='build id') 00311 add_project_runs_parser.add_argument('-r', '--build-report', required=True, help='path to junit xml build report') 00312 add_project_runs_parser.add_argument('-t', '--test-report', required=False, help='path to junit xml test report') 00313 add_project_runs_parser.add_argument('-o', '--host-os', required=True, help='host os on which test was run') 00314 add_project_runs_parser.set_defaults(func=add_project_runs) 00315 00316 args = parser.parse_args(arguments) 00317 args.func(args) 00318 00319 if __name__ == '__main__': 00320 main(sys.argv[1:])
Generated on Thu Jun 15 2023 14:54:59 by
