Skip to content

Commit e3dbb82

Browse files
committed
Fixed/improved error parsing from API messages.
Fixed results output summary. General tidy up of long lines. Added a new field to json file, target_list, to allow the user to override the set of targets used for the compilation.
1 parent 415486e commit e3dbb82

File tree

2 files changed

+109
-48
lines changed

2 files changed

+109
-48
lines changed

tools/check_release.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"name" : "test_compile_mbed_dev",
1212
"lib" : "mbed-dev"
1313
}
14-
]
14+
],
15+
"target_list" : []
1516
}
1617

tools/check_release.py

Lines changed: 107 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
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
@@ -41,6 +42,10 @@
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
@@ -51,8 +56,8 @@
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/
@@ -76,21 +81,39 @@
7681

7782
def 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\tCompilation 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\tCompilation 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\tCompilation 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

232261
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.
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("\tNone\n")
401+
else:
402+
for entry in lst:
403+
logging.info("\tTest: %s, Target: %s\n", entry[0], entry[1])
404+
405+
365406
if __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\tError: %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\tProgram/Target compilation failed due to internal errors. Removing from considered list!\n")
493+
logging.error("\t\tCompilation failed due to internal errors.\n")
494+
logging.error("\t\tSkipping 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

Comments
 (0)