3131# "name" : "test_compile_mbed_dev",
3232# "lib" : "mbed-dev"
3333# }
34- # ]
34+ # ],
35+ # "target_list" : []
3536#}
3637#
3738# The mbed_repo_path field should be changed to point to where your local
4142# "test_compile_mbed_lib" and "test_compile_mbed_dev"
4243# The lib field in each says which type of mbed 2 library the app contains.
4344# 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"]
4449#
4550# Run the script from the mbed-os directory as follows:
4651# > python tools/check_release.py
5156# The lib files within the test apps are then updated to the corresponding version in
5257# the associated lib itself. The test apps are then committed and pushed back to the users
5358# 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.
5661#
5762# Uses the online compiler API at https://mbed.org/handbook/Compile-API
5863# Based on the example from https://mbed.org/teams/mbed/code/mbed-API-helper/
7681
7782def get_compilation_failure (messages ):
7883 """ 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
8288 Args:
8389 messages - json formatted text returned by the online compiler API.
8490
8591 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 .
8894
8995 """
9096 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 )
94117
95118 return "Internal"
96119
@@ -126,9 +149,9 @@ def invoke_api(payload, url, auth, polls, begin="start/"):
126149 result = False
127150 fail_type = None
128151
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.
132155 poll_delay = 15
133156 logging .debug ("Running with a poll for response delay of: %ss" , poll_delay )
134157
@@ -137,19 +160,21 @@ def invoke_api(payload, url, auth, polls, begin="start/"):
137160 time .sleep (poll_delay )
138161 r = requests .get (url + "output/%s" % uuid , auth = auth )
139162 response = r .json ()
140- if response ['result' ]['data' ]['task_complete' ]:
141-
163+
164+ data = response ['result' ]['data' ]
165+ if data ['task_complete' ]:
142166 # Task completed. Now determine the result. Should be one of :
143167 # 1) Successful compilation
144168 # 2) Failed compilation with an error message
145169 # 3) Internal failure of the online compiler
146- result = bool (response [ 'result' ][ ' data' ] ['compilation_success' ])
170+ result = bool (data ['compilation_success' ])
147171 if result :
148172 logging .info ("\t \t Compilation SUCCESSFUL\n " )
149173 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 ?
151176 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' ])
153178 break
154179 else :
155180 logging .info ("\t \t Compilation FAILURE\n " )
@@ -160,8 +185,10 @@ def invoke_api(payload, url, auth, polls, begin="start/"):
160185 return result , fail_type
161186
162187
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.
165192
166193 Args:
167194 target - Target to be built
@@ -196,7 +223,8 @@ def run_cmd(command, exit_on_failure=False):
196223 return_code = subprocess .call (command , shell = True )
197224
198225 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 ))
200228 if exit_on_failure :
201229 sys .exit (1 )
202230
@@ -223,16 +251,18 @@ def run_cmd_with_output(command, exit_on_failure=False):
223251 try :
224252 output = subprocess .check_output (command , shell = True )
225253 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 ))
227256 returncode = e .returncode
228257 if exit_on_failure :
229258 sys .exit (1 )
230259 return returncode , output
231260
232261def 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.
236266 Args:
237267 test - Mercurial test repo name
238268 user - Mercurial user name
@@ -270,7 +300,7 @@ def upgrade_test_repo(test, user, library, ref, repo_path):
270300
271301 os .rename (lib_file , bak_file )
272302 else :
273- logging .error ("!! Error trying to backup lib file prior to updating." )
303+ logging .error ("!! Failure to backup lib file prior to updating." )
274304 return False
275305
276306 # 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):
279309 lib_re = re .compile (exp )
280310 updated = False
281311
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
283314 with open (bak_file , 'r' ) as ip , open (lib_file , 'w' ) as op :
284315 for line in ip :
285316
@@ -297,8 +328,9 @@ def upgrade_test_repo(test, user, library, ref, repo_path):
297328 # Setup the default commit message
298329 commit_message = '"Updating ' + library + ' to ' + ref + '"'
299330
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.
302334 try :
303335 client .rawcommand (['commit' ,'-m ' + commit_message , lib_file ])
304336
@@ -362,11 +394,22 @@ def get_latest_library_versions(repo_path):
362394
363395 return mbed , mbed_dev
364396
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+
365406if __name__ == '__main__' :
366407
367408 parser = argparse .ArgumentParser (description = __doc__ ,
368409 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' )
370413 args = parser .parse_args ()
371414
372415 default = getattr (logging , 'INFO' )
@@ -376,15 +419,19 @@ def get_latest_library_versions(repo_path):
376419 logging .basicConfig (level = level )
377420
378421 # 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" )))
381424
382425 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+
388435 config = json_data ["config" ]
389436 test_list = json_data ["test_list" ]
390437 repo_path = config ["mbed_repo_path" ]
@@ -414,11 +461,15 @@ def get_latest_library_versions(repo_path):
414461 # First update test repos to latest versions of their embedded libraries
415462 for test in test_list :
416463 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 )
420469 retries = 10
421470 passes = 0
471+ failures = []
472+ skipped = []
422473
423474 # Compile each test for each supported target
424475 for test in tests :
@@ -432,17 +483,26 @@ def get_latest_library_versions(repo_path):
432483 # Internal compiler error thus retry
433484 continue
434485 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
437489
438490 passes += (int )(result )
439491 break
440492 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 " )
442495 total -= 1
496+ skipped .append ([test , target ])
443497
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+
444505 # 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 )
447508 sys .exit (not (pass_rate == 100 ))
448-
0 commit comments