31
31
# "name" : "test_compile_mbed_dev",
32
32
# "lib" : "mbed-dev"
33
33
# }
34
- # ]
34
+ # ],
35
+ # "target_list" : []
35
36
#}
36
37
#
37
38
# The mbed_repo_path field should be changed to point to where your local
41
42
# "test_compile_mbed_lib" and "test_compile_mbed_dev"
42
43
# The lib field in each says which type of mbed 2 library the app contains.
43
44
# These test apps MUST be available as repos in the user's online Mercurial area.
45
+ # The target_list allows the user to override the set of targets/platforms used
46
+ # for the compilation.
47
+ # E.g to just compile for 2 targets, K64F and K22F :
48
+ # "target_list" : ["K64F", "K22F"]
44
49
#
45
50
# Run the script from the mbed-os directory as follows:
46
51
# > python tools/check_release.py
51
56
# The lib files within the test apps are then updated to the corresponding version in
52
57
# the associated lib itself. The test apps are then committed and pushed back to the users
53
58
# fork.
54
- # The test apps will then be compiled for all supported targets and a % result output at the
55
- # end.
59
+ # The test apps will then be compiled for all supported targets and a % result output at
60
+ # the end.
56
61
#
57
62
# Uses the online compiler API at https://mbed.org/handbook/Compile-API
58
63
# Based on the example from https://mbed.org/teams/mbed/code/mbed-API-helper/
76
81
77
82
def get_compilation_failure (messages ):
78
83
""" Reads the json formatted 'messages' and checks for compilation errors.
79
- If there is a genuine compilation error then there should be a new message containing
80
- a severity field = Error and an accompanying message with the compile error text.
81
- Any other combination is considered an internal compile engine failure
84
+ If there is a genuine compilation error then there should be a new
85
+ message containing a severity field = Error and an accompanying message
86
+ with the compile error text. Any other combination is considered an
87
+ internal compile engine failure
82
88
Args:
83
89
messages - json formatted text returned by the online compiler API.
84
90
85
91
Returns:
86
- Either a string containing a compilation error or "Internal" to indicate an error with
87
- the online IDE API itself .
92
+ Either "Error" or "Internal" to indicate an actual compilation error or an
93
+ internal IDE API fault .
88
94
89
95
"""
90
96
for m in messages :
91
- if 'severity' in m and 'message' in m :
92
- if m ['severity' ] == 'error' :
93
- return m ['message' ]
97
+ # Get message text if it exists
98
+ try :
99
+ message = m ['message' ]
100
+ message = message + "\n "
101
+ except KeyError :
102
+ # Skip this message as it has no 'message' field
103
+ continue
104
+
105
+ # Get type of message text
106
+ try :
107
+ msg_type = m ['type' ]
108
+ except KeyError :
109
+ # Skip this message as it has no 'type' field
110
+ continue
111
+
112
+ if msg_type == 'error' or msg_type == 'tool_error' :
113
+ logging .error (message )
114
+ return "Error"
115
+ else :
116
+ logging .debug (message )
94
117
95
118
return "Internal"
96
119
@@ -126,9 +149,9 @@ def invoke_api(payload, url, auth, polls, begin="start/"):
126
149
result = False
127
150
fail_type = None
128
151
129
- # It currently seems to take the onlide IDE API ~30s to process the compile request and
130
- # provide a response. Set the poll time to half that in case it does manage to compile
131
- # quicker.
152
+ # It currently seems to take the onlide IDE API ~30s to process the compile
153
+ # request and provide a response. Set the poll time to half that in case it
154
+ # does manage to compile quicker.
132
155
poll_delay = 15
133
156
logging .debug ("Running with a poll for response delay of: %ss" , poll_delay )
134
157
@@ -137,19 +160,21 @@ def invoke_api(payload, url, auth, polls, begin="start/"):
137
160
time .sleep (poll_delay )
138
161
r = requests .get (url + "output/%s" % uuid , auth = auth )
139
162
response = r .json ()
140
- if response ['result' ]['data' ]['task_complete' ]:
141
-
163
+
164
+ data = response ['result' ]['data' ]
165
+ if data ['task_complete' ]:
142
166
# Task completed. Now determine the result. Should be one of :
143
167
# 1) Successful compilation
144
168
# 2) Failed compilation with an error message
145
169
# 3) Internal failure of the online compiler
146
- result = bool (response [ 'result' ][ ' data' ] ['compilation_success' ])
170
+ result = bool (data ['compilation_success' ])
147
171
if result :
148
172
logging .info ("\t \t Compilation SUCCESSFUL\n " )
149
173
else :
150
- # Did this fail due to a genuine compilation error or a failue of the api itself ?
174
+ # Did this fail due to a genuine compilation error or a failue of
175
+ # the api itself ?
151
176
logging .info ("\t \t Compilation FAILURE\n " )
152
- fail_type = get_compilation_failure (response [ 'result' ][ ' data' ] ['new_messages' ])
177
+ fail_type = get_compilation_failure (data ['new_messages' ])
153
178
break
154
179
else :
155
180
logging .info ("\t \t Compilation FAILURE\n " )
@@ -160,8 +185,10 @@ def invoke_api(payload, url, auth, polls, begin="start/"):
160
185
return result , fail_type
161
186
162
187
163
- def build_repo (target , program , user , pw , polls = 25 , url = "https://developer.mbed.org/api/v2/tasks/compiler/" ):
164
- """ Wrapper for sending an API command request to the online IDE. Sends a build request.
188
+ def build_repo (target , program , user , pw , polls = 25 ,
189
+ url = "https://developer.mbed.org/api/v2/tasks/compiler/" ):
190
+ """ Wrapper for sending an API command request to the online IDE. Sends a
191
+ build request.
165
192
166
193
Args:
167
194
target - Target to be built
@@ -196,7 +223,8 @@ def run_cmd(command, exit_on_failure=False):
196
223
return_code = subprocess .call (command , shell = True )
197
224
198
225
if return_code :
199
- logging .warning ("The command '%s' failed with return code: %s" , (' ' .join (command ), return_code ))
226
+ logging .warning ("The command '%s' failed with return code: %s" ,
227
+ (' ' .join (command ), return_code ))
200
228
if exit_on_failure :
201
229
sys .exit (1 )
202
230
@@ -223,16 +251,18 @@ def run_cmd_with_output(command, exit_on_failure=False):
223
251
try :
224
252
output = subprocess .check_output (command , shell = True )
225
253
except subprocess .CalledProcessError as e :
226
- logging .warning ("The command '%s' failed with return code: %s" , (' ' .join (command ), e .returncode ))
254
+ logging .warning ("The command '%s' failed with return code: %s" ,
255
+ (' ' .join (command ), e .returncode ))
227
256
returncode = e .returncode
228
257
if exit_on_failure :
229
258
sys .exit (1 )
230
259
return returncode , output
231
260
232
261
def upgrade_test_repo (test , user , library , ref , repo_path ):
233
- """ Upgrades a local version of a test repo to the latest version of its embedded library.
234
- If the test repo is not present in the user area specified in the json config file, then
235
- it will first be cloned.
262
+ """ Upgrades a local version of a test repo to the latest version of its
263
+ embedded library.
264
+ If the test repo is not present in the user area specified in the json
265
+ config file, then it will first be cloned.
236
266
Args:
237
267
test - Mercurial test repo name
238
268
user - Mercurial user name
@@ -270,7 +300,7 @@ def upgrade_test_repo(test, user, library, ref, repo_path):
270
300
271
301
os .rename (lib_file , bak_file )
272
302
else :
273
- logging .error ("!! Error trying to backup lib file prior to updating." )
303
+ logging .error ("!! Failure to backup lib file prior to updating." )
274
304
return False
275
305
276
306
# mbed 2 style lib file contains one line with the following format
@@ -279,7 +309,8 @@ def upgrade_test_repo(test, user, library, ref, repo_path):
279
309
lib_re = re .compile (exp )
280
310
updated = False
281
311
282
- # Scan through mbed-os.lib line by line, looking for lib version and update it if found
312
+ # Scan through mbed-os.lib line by line, looking for lib version and update
313
+ # it if found
283
314
with open (bak_file , 'r' ) as ip , open (lib_file , 'w' ) as op :
284
315
for line in ip :
285
316
@@ -297,8 +328,9 @@ def upgrade_test_repo(test, user, library, ref, repo_path):
297
328
# Setup the default commit message
298
329
commit_message = '"Updating ' + library + ' to ' + ref + '"'
299
330
300
- # Setup and run the commit command. Need to use the rawcommand in the hglib for this in order to pass
301
- # the string value to the -m option. run_cmd using subprocess does not like this syntax.
331
+ # Setup and run the commit command. Need to use the rawcommand in the hglib
332
+ # for this in order to pass the string value to the -m option. run_cmd using
333
+ # subprocess does not like this syntax.
302
334
try :
303
335
client .rawcommand (['commit' ,'-m ' + commit_message , lib_file ])
304
336
@@ -362,11 +394,22 @@ def get_latest_library_versions(repo_path):
362
394
363
395
return mbed , mbed_dev
364
396
397
+ def log_results (lst , title ):
398
+ logging .info (title )
399
+ if len (lst ) == 0 :
400
+ logging .info ("\t None\n " )
401
+ else :
402
+ for entry in lst :
403
+ logging .info ("\t Test: %s, Target: %s\n " , entry [0 ], entry [1 ])
404
+
405
+
365
406
if __name__ == '__main__' :
366
407
367
408
parser = argparse .ArgumentParser (description = __doc__ ,
368
409
formatter_class = argparse .RawDescriptionHelpFormatter )
369
- parser .add_argument ('-l' , '--log-level' , help = "Level for providing logging output" , default = 'INFO' )
410
+ parser .add_argument ('-l' , '--log-level' ,
411
+ help = "Level for providing logging output" ,
412
+ default = 'INFO' )
370
413
args = parser .parse_args ()
371
414
372
415
default = getattr (logging , 'INFO' )
@@ -376,15 +419,19 @@ def get_latest_library_versions(repo_path):
376
419
logging .basicConfig (level = level )
377
420
378
421
# Read configuration data
379
- json_data = json .load (open (os .path .join (os .path .dirname (__file__ ), "check_release.json" )))
380
-
422
+ json_data = json .load (open (os .path .join (os .path .dirname (__file__ ),
423
+ "check_release.json" )))
381
424
382
425
supported_targets = []
383
-
384
- # Get a list of the officially supported mbed-os 2 targets
385
- for tgt in OFFICIAL_MBED_LIBRARY_BUILD :
386
- supported_targets .append (tgt [0 ])
387
-
426
+
427
+ if len (json_data ["target_list" ]) > 0 :
428
+ # Compile user supplied subset of targets
429
+ supported_targets = json_data ["target_list" ]
430
+ else :
431
+ # Get a list of the officially supported mbed-os 2 targets
432
+ for tgt in OFFICIAL_MBED_LIBRARY_BUILD :
433
+ supported_targets .append (tgt [0 ])
434
+
388
435
config = json_data ["config" ]
389
436
test_list = json_data ["test_list" ]
390
437
repo_path = config ["mbed_repo_path" ]
@@ -414,11 +461,15 @@ def get_latest_library_versions(repo_path):
414
461
# First update test repos to latest versions of their embedded libraries
415
462
for test in test_list :
416
463
tests .append (test ['name' ])
417
- upgrade_test_repo (test ['name' ], user , test ['lib' ], mbed if test ['lib' ] == "mbed" else mbed_dev , repo_path )
418
-
419
- total = len (supported_targets )* len (tests )
464
+ upgrade_test_repo (test ['name' ], user , test ['lib' ],
465
+ mbed if test ['lib' ] == "mbed" else mbed_dev ,
466
+ repo_path )
467
+
468
+ total = len (supported_targets ) * len (tests )
420
469
retries = 10
421
470
passes = 0
471
+ failures = []
472
+ skipped = []
422
473
423
474
# Compile each test for each supported target
424
475
for test in tests :
@@ -432,17 +483,26 @@ def get_latest_library_versions(repo_path):
432
483
# Internal compiler error thus retry
433
484
continue
434
485
else :
435
- # Genuine compilation error, thus print it out
436
- logging .error ("\t \t Error: %s\n " , mesg )
486
+ # Actual error thus move on to next compilation
487
+ failures .append ([test , target ])
488
+ break
437
489
438
490
passes += (int )(result )
439
491
break
440
492
else :
441
- logging .error ("\t \t Program/Target compilation failed due to internal errors. Removing from considered list!\n " )
493
+ logging .error ("\t \t Compilation failed due to internal errors.\n " )
494
+ logging .error ("\t \t Skipping test/target combination!\n " )
442
495
total -= 1
496
+ skipped .append ([test , target ])
443
497
498
+ logging .info (" SUMMARY OF COMPILATION RESULTS" )
499
+ logging .info (" ------------------------------\n " )
500
+ logging .info (" NUMBER OF TEST APPS: %d, NUMBER OF TARGETS: %d\n " ,
501
+ len (tests ), len (supported_targets ))
502
+ log_results (failures , " FAILURES:\n " )
503
+ log_results (skipped , " SKIPPED:\n " )
504
+
444
505
# Output a % pass rate, indicate a failure if not 100% successful
445
- pass_rate = int ( passes / total ) * 100
446
- logging .info ("Pass percentage = %d \n " , pass_rate )
506
+ pass_rate = ( float ( passes ) / float ( total )) * 100.0
507
+ logging .info (" PASS RATE %.1f %% \n " , pass_rate )
447
508
sys .exit (not (pass_rate == 100 ))
448
-
0 commit comments