Script to check a new SDK release by using the online compiler API to compile a simple program against various targets.

Revision:
0:bdd0ba470ddc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/check_release.py	Fri Aug 15 15:19:41 2014 +0100
@@ -0,0 +1,163 @@
+# Script to check a new SKD release
+# Compiles a simple 'blinky' example for as many platforms as possible
+# Reports errors or success
+# Uses the online compiler API at https://mbed.org/handbook/Compile-API
+# Based on the example from https://mbed.org/teams/mbed/code/mbed-API-helper/
+
+################################################################################
+# Configuration section
+
+# mbed_repo_path (optional): path to a github clone of the mbed repo. If found,
+#   build_release.py in that repo will be used for the list of targets to build.
+#   If not specified, target_mapping (below) will be used instead.
+# mbed_test_project_repo: repository of the program used for testing compilation
+# mbed_org_user: username for mbed.org
+# mbed_org_password (optional): password for 'mbed_org_user'
+
+mbed_repo_path = "c:/work/mbed/github"
+mbed_org_user = "bogdanm"
+mbed_test_project_repo = "https://mbed.org/users/bogdanm/code/test_new_lib_mylib"
+################################################################################
+
+from os.path import abspath, join, dirname
+import os, getpass, sys, json, time, requests, logging
+
+# Mapping between target name in offline build system and target name in online
+# build system. This really shouldn't be needed.
+target_mapping = {
+    'LPC11U24': 'mbed-LPC11U24',
+    'LPC1768': 'mbed-LPC1768',
+    'UBLOX_C027': 'u-blox-C027',
+    'ARCH_PRO': 'Seeeduino-Arch-Pro',
+    'LPC2368': 'mbed-LPC2368',
+    'LPC812': 'NXP-LPC800-MAX',
+    'LPC1347': 'DipCortex-M3',
+    'LPC4088': 'EA-LPC4088',
+    'LPC1114': 'LPC1114FN28',
+    'LPC11U35_401': 'EA-LPC11U35',
+    'LPC11U35_501': 'TG-LPC11U35-501',
+    'LPC1549': 'LPCXpresso1549',
+    'XADOW_M0': 'Seeed-Xadow-M0',
+    'ARCH_GPRS': 'Seeed-Arch-GPRS',
+    'KL05Z': 'FRDM-KL05Z',
+    'KL25Z': 'KL25Z',
+    'KL46Z': 'FRDM-KL46Z',
+    'K64F': 'FRDM-K64F',
+    'K20D50M': 'FRDM-K20D50M',
+    'NUCLEO_F030R8': 'ST-Nucleo-F030R8',
+    'NUCLEO_F072RB': 'ST-Nucleo-F072RB',
+    'NUCLEO_F103RB': 'ST-Nucleo-F103RB',
+    'NUCLEO_F302R8': 'ST-Nucleo-F302R8',
+    'NUCLEO_F334R8': 'ST-Nucleo-F334R8',
+    'NUCLEO_F401RE': 'ST-Nucleo-F401RE',
+    'NUCLEO_F411RE': 'ST-Nucleo-F411RE',
+    'NUCLEO_L053R8': 'ST-Nucleo-L053R8',
+    'NUCLEO_L152RE': 'ST-Nucleo-L152RE',
+    'NRF51822': 'Nordic-nRF51822',
+    'HRM1017': 'mbed-HRM1017',
+    'ARCH_BLE': 'Seeed-Arch-BLE',
+    'RBLAB_NRF51822': 'RedBearLab-nRF51822',
+    'LPC11U68': 'LPCXpresso11U68',
+    'GHI_MBUINO': 'Outrageous-Circuits-mBuino',
+}
+
+reverse_target_mapping = dict([(target_mapping[k], k) for k in target_mapping.keys()])
+
+# Get list of targets to build from build_release.py
+# And map the target names to the ones used in the online build system
+def get_target_list():
+    offline_list, online_list, skipped = [e[0] for e in OFFICIAL_MBED_LIBRARY_BUILD], [], []
+    for t in offline_list:
+        if target_mapping.has_key(t):
+            online_list.append(target_mapping[t])
+        else:
+            skipped.append(t)
+            logging.warn("Target '%s' not found" % t)
+    return online_list, skipped
+
+# Compile the test project for the given target
+def compile_for_target(target):
+    payload = {'clean': False, 'platform': target, 'repo': mbed_test_project_repo}
+    auth = (mbed_org_user, mbed_org_password)
+    r = requests.post("https://mbed.org/api/v2/tasks/compiler/start/", data = payload, auth = auth)
+    logging.debug("%s" % r.content)
+    if r.status_code != 200:
+        if r.content == "Authorization Required":
+            return False, "invalid username/password"
+        else:
+            return False, "Error while talking to the mbed API"
+    uuid = json.loads(r.content)['result']['data']['task_id']
+    logging.debug("Task accepted and given ID: %s" % uuid)
+    success, errors = False, []
+    # Poll for output
+    for check in range(0, 40):
+        logging.debug("Checking for output: cycle %s" % check)
+        time.sleep(2)
+        r = requests.get("https://mbed.org/api/v2/tasks/compiler/output/%s" % uuid, auth = auth)
+        logging.debug(r.content)
+        response = json.loads(r.content)
+        messages = response['result']['data']['new_messages']
+        for message in messages:
+            if message.get('severity', False) == 'error':
+                errors.append({"file": message["file"], "error": message["message"]})
+            elif message.get('type', False) == 'tool_error':
+                errors.append({"file": "", "error": message["message"]})
+        if response['result']['data']['task_complete']:
+            logging.info("Task completed.")
+            success = response['result']['data']['compilation_success']
+            logging.info("Compile success: %s" % success)
+            break
+    else:
+        errors = "Timeout"
+    return success, errors
+
+
+if '-d' in sys.argv:
+    logging.basicConfig(level = logging.DEBUG)
+    sys.argv.remove('-d')
+else:
+    logging.basicConfig(level = logging.WARN)
+
+# Try to get list of targets to build for from build_release.py
+if len(sys.argv) > 1:
+    targets, skipped = sys.argv[1:], []
+else:
+    try:
+        import sys
+        sys.path.insert(0, mbed_repo_path)
+        from workspace_tools.build_release import OFFICIAL_MBED_LIBRARY_BUILD
+        logging.info("Got target list from build_release.py")
+        targets, skipped = get_target_list() 
+    except:
+        logging.info("build_release.py not found, will try to build all known targets")
+        targets, skipped = target_mapping.values(), []
+   
+# Get password once
+try:
+    mbed_org_password
+except:
+    mbed_org_password = getpass.getpass("Password for '%s': " % mbed_org_user)
+
+if not mbed_test_project_repo.endswith('/'):
+    mbed_test_project_repo = mbed_test_project_repo + '/'
+ok, failed = [], []
+
+for t in targets:
+    sys.stdout.write("Compiling for target '%s' (%s) ... " % (t, reverse_target_mapping[t]))
+    sys.stdout.flush()
+    res, errors = compile_for_target(t)
+    if res:
+        print "OK"
+        ok.append(t)
+    else:
+        if type(errors) == type([]) and errors:
+            print "BUILD ERROR!"
+            for e in errors:
+                print "    '%s': %s" % (e["file"], e["error"])
+        else:
+            print "ERROR: '%s'" % errors
+        failed.append(t)
+
+print "Compiled OK       : " + (", ".join(ok) if ok else "none")
+print "Compilation errors: " + (", ".join(failed) if failed else "none")
+print "Skipped           : " + (", ".join(skipped) if skipped else "none")