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

check_release.py

Committer:
Bogdan Marinescu
Date:
2014-08-15
Revision:
0:bdd0ba470ddc

File content as of revision 0:bdd0ba470ddc:

# 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")