Rtos API example

Committer:
marcozecchini
Date:
Sat Feb 23 12:13:36 2019 +0000
Revision:
0:9fca2b23d0ba
final commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
marcozecchini 0:9fca2b23d0ba 1 # Script to check a new mbed 2 release by compiling a set of specified test apps
marcozecchini 0:9fca2b23d0ba 2 # for all currently supported platforms. Each test app must include an mbed library.
marcozecchini 0:9fca2b23d0ba 3 # This can either be the pre-compiled version 'mbed' or the source version 'mbed-dev'.
marcozecchini 0:9fca2b23d0ba 4 #
marcozecchini 0:9fca2b23d0ba 5 # Setup:
marcozecchini 0:9fca2b23d0ba 6 # 1. Set up your global .hgrc file
marcozecchini 0:9fca2b23d0ba 7 #
marcozecchini 0:9fca2b23d0ba 8 # If you don't already have a .hgrc file in your $HOME directory, create one there.
marcozecchini 0:9fca2b23d0ba 9 # Then add the following section:
marcozecchini 0:9fca2b23d0ba 10 #
marcozecchini 0:9fca2b23d0ba 11 # [auth]
marcozecchini 0:9fca2b23d0ba 12 # x.prefix = *
marcozecchini 0:9fca2b23d0ba 13 # x.username = <put your mbed org username here>
marcozecchini 0:9fca2b23d0ba 14 # x.password = <put your mbed org password here>
marcozecchini 0:9fca2b23d0ba 15 #
marcozecchini 0:9fca2b23d0ba 16 # This has 2 purposes, the first means you don't get prompted for your password
marcozecchini 0:9fca2b23d0ba 17 # whenever you run hg commands on the commandline. The second is that this script
marcozecchini 0:9fca2b23d0ba 18 # reads these details in order to fully automate the Mercurial commands.
marcozecchini 0:9fca2b23d0ba 19 #
marcozecchini 0:9fca2b23d0ba 20 # Edit "check_release.json". This has the following structure:
marcozecchini 0:9fca2b23d0ba 21 #{
marcozecchini 0:9fca2b23d0ba 22 # "config" : {
marcozecchini 0:9fca2b23d0ba 23 # "mbed_repo_path" : "C:/Users/annbri01/Work/Mercurial"
marcozecchini 0:9fca2b23d0ba 24 # },
marcozecchini 0:9fca2b23d0ba 25 # "test_list" : [
marcozecchini 0:9fca2b23d0ba 26 # {
marcozecchini 0:9fca2b23d0ba 27 # "name" : "test_compile_mbed_lib",
marcozecchini 0:9fca2b23d0ba 28 # "lib" : "mbed"
marcozecchini 0:9fca2b23d0ba 29 # },
marcozecchini 0:9fca2b23d0ba 30 # {
marcozecchini 0:9fca2b23d0ba 31 # "name" : "test_compile_mbed_dev",
marcozecchini 0:9fca2b23d0ba 32 # "lib" : "mbed-dev"
marcozecchini 0:9fca2b23d0ba 33 # }
marcozecchini 0:9fca2b23d0ba 34 # ],
marcozecchini 0:9fca2b23d0ba 35 # "target_list" : []
marcozecchini 0:9fca2b23d0ba 36 #}
marcozecchini 0:9fca2b23d0ba 37 #
marcozecchini 0:9fca2b23d0ba 38 # The mbed_repo_path field should be changed to point to where your local
marcozecchini 0:9fca2b23d0ba 39 # working directory is for Mercurial repositories.
marcozecchini 0:9fca2b23d0ba 40 # For each test app you wish to run, add an entry to the test list. The example
marcozecchini 0:9fca2b23d0ba 41 # above has 2 test apps
marcozecchini 0:9fca2b23d0ba 42 # "test_compile_mbed_lib" and "test_compile_mbed_dev"
marcozecchini 0:9fca2b23d0ba 43 # The lib field in each says which type of mbed 2 library the app contains.
marcozecchini 0:9fca2b23d0ba 44 # These test apps MUST be available as repos in the user's online Mercurial area.
marcozecchini 0:9fca2b23d0ba 45 # The target_list allows the user to override the set of targets/platforms used
marcozecchini 0:9fca2b23d0ba 46 # for the compilation.
marcozecchini 0:9fca2b23d0ba 47 # E.g to just compile for 2 targets, K64F and K22F :
marcozecchini 0:9fca2b23d0ba 48 # "target_list" : ["K64F", "K22F"]
marcozecchini 0:9fca2b23d0ba 49 #
marcozecchini 0:9fca2b23d0ba 50 # Run the script from the mbed-os directory as follows:
marcozecchini 0:9fca2b23d0ba 51 # > python tools/check_release.py
marcozecchini 0:9fca2b23d0ba 52 #
marcozecchini 0:9fca2b23d0ba 53 # It will look for local clones of the test app repos. If they don't exist
marcozecchini 0:9fca2b23d0ba 54 # it will clone them. It will then read the latest versions of mbed and mbed-dev
marcozecchini 0:9fca2b23d0ba 55 # (an assumption is made that both of these are already cloned in your Mercurial area).
marcozecchini 0:9fca2b23d0ba 56 # The lib files within the test apps are then updated to the corresponding version in
marcozecchini 0:9fca2b23d0ba 57 # the associated lib itself. The test apps are then committed and pushed back to the users
marcozecchini 0:9fca2b23d0ba 58 # fork.
marcozecchini 0:9fca2b23d0ba 59 # The test apps will then be compiled for all supported targets and a % result output at
marcozecchini 0:9fca2b23d0ba 60 # the end.
marcozecchini 0:9fca2b23d0ba 61 #
marcozecchini 0:9fca2b23d0ba 62 # Uses the online compiler API at https://mbed.org/handbook/Compile-API
marcozecchini 0:9fca2b23d0ba 63 # Based on the example from https://mbed.org/teams/mbed/code/mbed-API-helper/
marcozecchini 0:9fca2b23d0ba 64
marcozecchini 0:9fca2b23d0ba 65
marcozecchini 0:9fca2b23d0ba 66 import os, getpass, sys, json, time, requests, logging
marcozecchini 0:9fca2b23d0ba 67 from os.path import dirname, abspath, basename, join
marcozecchini 0:9fca2b23d0ba 68 import argparse
marcozecchini 0:9fca2b23d0ba 69 import subprocess
marcozecchini 0:9fca2b23d0ba 70 import re
marcozecchini 0:9fca2b23d0ba 71 import hglib
marcozecchini 0:9fca2b23d0ba 72 import argparse
marcozecchini 0:9fca2b23d0ba 73
marcozecchini 0:9fca2b23d0ba 74 # Be sure that the tools directory is in the search path
marcozecchini 0:9fca2b23d0ba 75 ROOT = abspath(join(dirname(__file__), ".."))
marcozecchini 0:9fca2b23d0ba 76 sys.path.insert(0, ROOT)
marcozecchini 0:9fca2b23d0ba 77
marcozecchini 0:9fca2b23d0ba 78 from tools.build_api import get_mbed_official_release
marcozecchini 0:9fca2b23d0ba 79
marcozecchini 0:9fca2b23d0ba 80 OFFICIAL_MBED_LIBRARY_BUILD = get_mbed_official_release('2')
marcozecchini 0:9fca2b23d0ba 81
marcozecchini 0:9fca2b23d0ba 82 def get_compilation_failure(messages):
marcozecchini 0:9fca2b23d0ba 83 """ Reads the json formatted 'messages' and checks for compilation errors.
marcozecchini 0:9fca2b23d0ba 84 If there is a genuine compilation error then there should be a new
marcozecchini 0:9fca2b23d0ba 85 message containing a severity field = Error and an accompanying message
marcozecchini 0:9fca2b23d0ba 86 with the compile error text. Any other combination is considered an
marcozecchini 0:9fca2b23d0ba 87 internal compile engine failure
marcozecchini 0:9fca2b23d0ba 88 Args:
marcozecchini 0:9fca2b23d0ba 89 messages - json formatted text returned by the online compiler API.
marcozecchini 0:9fca2b23d0ba 90
marcozecchini 0:9fca2b23d0ba 91 Returns:
marcozecchini 0:9fca2b23d0ba 92 Either "Error" or "Internal" to indicate an actual compilation error or an
marcozecchini 0:9fca2b23d0ba 93 internal IDE API fault.
marcozecchini 0:9fca2b23d0ba 94
marcozecchini 0:9fca2b23d0ba 95 """
marcozecchini 0:9fca2b23d0ba 96 for m in messages:
marcozecchini 0:9fca2b23d0ba 97 # Get message text if it exists
marcozecchini 0:9fca2b23d0ba 98 try:
marcozecchini 0:9fca2b23d0ba 99 message = m['message']
marcozecchini 0:9fca2b23d0ba 100 message = message + "\n"
marcozecchini 0:9fca2b23d0ba 101 except KeyError:
marcozecchini 0:9fca2b23d0ba 102 # Skip this message as it has no 'message' field
marcozecchini 0:9fca2b23d0ba 103 continue
marcozecchini 0:9fca2b23d0ba 104
marcozecchini 0:9fca2b23d0ba 105 # Get type of message text
marcozecchini 0:9fca2b23d0ba 106 try:
marcozecchini 0:9fca2b23d0ba 107 msg_type = m['type']
marcozecchini 0:9fca2b23d0ba 108 except KeyError:
marcozecchini 0:9fca2b23d0ba 109 # Skip this message as it has no 'type' field
marcozecchini 0:9fca2b23d0ba 110 continue
marcozecchini 0:9fca2b23d0ba 111
marcozecchini 0:9fca2b23d0ba 112 if msg_type == 'error' or msg_type == 'tool_error':
marcozecchini 0:9fca2b23d0ba 113 rel_log.error(message)
marcozecchini 0:9fca2b23d0ba 114 return "Error"
marcozecchini 0:9fca2b23d0ba 115 else:
marcozecchini 0:9fca2b23d0ba 116 rel_log.debug(message)
marcozecchini 0:9fca2b23d0ba 117
marcozecchini 0:9fca2b23d0ba 118 return "Internal"
marcozecchini 0:9fca2b23d0ba 119
marcozecchini 0:9fca2b23d0ba 120 def invoke_api(payload, url, auth, polls, begin="start/"):
marcozecchini 0:9fca2b23d0ba 121 """ Sends an API command request to the online IDE. Waits for a task completed
marcozecchini 0:9fca2b23d0ba 122 response before returning the results.
marcozecchini 0:9fca2b23d0ba 123
marcozecchini 0:9fca2b23d0ba 124 Args:
marcozecchini 0:9fca2b23d0ba 125 payload - Configuration parameters to be passed to the API
marcozecchini 0:9fca2b23d0ba 126 url - THe URL for the online compiler API
marcozecchini 0:9fca2b23d0ba 127 auth - Tuple containing authentication credentials
marcozecchini 0:9fca2b23d0ba 128 polls - Number of times to poll for results
marcozecchini 0:9fca2b23d0ba 129 begin - Default value = "start/", start command to be appended to URL
marcozecchini 0:9fca2b23d0ba 130
marcozecchini 0:9fca2b23d0ba 131 Returns:
marcozecchini 0:9fca2b23d0ba 132 result - True/False indicating the success/failure of the compilation
marcozecchini 0:9fca2b23d0ba 133 fail_type - the failure text if the compilation failed, else None
marcozecchini 0:9fca2b23d0ba 134 """
marcozecchini 0:9fca2b23d0ba 135
marcozecchini 0:9fca2b23d0ba 136 # send task to api
marcozecchini 0:9fca2b23d0ba 137 rel_log.debug(url + begin + "| data: " + str(payload))
marcozecchini 0:9fca2b23d0ba 138 r = requests.post(url + begin, data=payload, auth=auth)
marcozecchini 0:9fca2b23d0ba 139 rel_log.debug(r.request.body)
marcozecchini 0:9fca2b23d0ba 140
marcozecchini 0:9fca2b23d0ba 141 if r.status_code != 200:
marcozecchini 0:9fca2b23d0ba 142 rel_log.error("HTTP code %d reported.", r.status_code)
marcozecchini 0:9fca2b23d0ba 143 return False, "Internal"
marcozecchini 0:9fca2b23d0ba 144
marcozecchini 0:9fca2b23d0ba 145 response = r.json()
marcozecchini 0:9fca2b23d0ba 146 rel_log.debug(response)
marcozecchini 0:9fca2b23d0ba 147 uuid = response['result']['data']['task_id']
marcozecchini 0:9fca2b23d0ba 148 rel_log.debug("Task accepted and given ID: %s", uuid)
marcozecchini 0:9fca2b23d0ba 149 result = False
marcozecchini 0:9fca2b23d0ba 150 fail_type = None
marcozecchini 0:9fca2b23d0ba 151
marcozecchini 0:9fca2b23d0ba 152 # It currently seems to take the onlide IDE API ~30s to process the compile
marcozecchini 0:9fca2b23d0ba 153 # request and provide a response. Set the poll time to half that in case it
marcozecchini 0:9fca2b23d0ba 154 # does manage to compile quicker.
marcozecchini 0:9fca2b23d0ba 155 poll_delay = 15
marcozecchini 0:9fca2b23d0ba 156 rel_log.debug("Running with a poll for response delay of: %ss", poll_delay)
marcozecchini 0:9fca2b23d0ba 157
marcozecchini 0:9fca2b23d0ba 158 # poll for output
marcozecchini 0:9fca2b23d0ba 159 for check in range(polls):
marcozecchini 0:9fca2b23d0ba 160 time.sleep(poll_delay)
marcozecchini 0:9fca2b23d0ba 161
marcozecchini 0:9fca2b23d0ba 162 try:
marcozecchini 0:9fca2b23d0ba 163 r = requests.get(url + "output/%s" % uuid, auth=auth)
marcozecchini 0:9fca2b23d0ba 164
marcozecchini 0:9fca2b23d0ba 165 except ConnectionError:
marcozecchini 0:9fca2b23d0ba 166 return "Internal"
marcozecchini 0:9fca2b23d0ba 167
marcozecchini 0:9fca2b23d0ba 168 response = r.json()
marcozecchini 0:9fca2b23d0ba 169
marcozecchini 0:9fca2b23d0ba 170 data = response['result']['data']
marcozecchini 0:9fca2b23d0ba 171 if data['task_complete']:
marcozecchini 0:9fca2b23d0ba 172 # Task completed. Now determine the result. Should be one of :
marcozecchini 0:9fca2b23d0ba 173 # 1) Successful compilation
marcozecchini 0:9fca2b23d0ba 174 # 2) Failed compilation with an error message
marcozecchini 0:9fca2b23d0ba 175 # 3) Internal failure of the online compiler
marcozecchini 0:9fca2b23d0ba 176 result = bool(data['compilation_success'])
marcozecchini 0:9fca2b23d0ba 177 if result:
marcozecchini 0:9fca2b23d0ba 178 rel_log.info("COMPILATION SUCCESSFUL\n")
marcozecchini 0:9fca2b23d0ba 179 else:
marcozecchini 0:9fca2b23d0ba 180 # Did this fail due to a genuine compilation error or a failue of
marcozecchini 0:9fca2b23d0ba 181 # the api itself ?
marcozecchini 0:9fca2b23d0ba 182 rel_log.info("COMPILATION FAILURE\n")
marcozecchini 0:9fca2b23d0ba 183 fail_type = get_compilation_failure(data['new_messages'])
marcozecchini 0:9fca2b23d0ba 184 break
marcozecchini 0:9fca2b23d0ba 185 else:
marcozecchini 0:9fca2b23d0ba 186 rel_log.info("COMPILATION FAILURE\n")
marcozecchini 0:9fca2b23d0ba 187
marcozecchini 0:9fca2b23d0ba 188 if not result and fail_type == None:
marcozecchini 0:9fca2b23d0ba 189 fail_type = "Internal"
marcozecchini 0:9fca2b23d0ba 190
marcozecchini 0:9fca2b23d0ba 191 return result, fail_type
marcozecchini 0:9fca2b23d0ba 192
marcozecchini 0:9fca2b23d0ba 193
marcozecchini 0:9fca2b23d0ba 194 def build_repo(target, program, user, pw, polls=25,
marcozecchini 0:9fca2b23d0ba 195 url="https://developer.mbed.org/api/v2/tasks/compiler/"):
marcozecchini 0:9fca2b23d0ba 196 """ Wrapper for sending an API command request to the online IDE. Sends a
marcozecchini 0:9fca2b23d0ba 197 build request.
marcozecchini 0:9fca2b23d0ba 198
marcozecchini 0:9fca2b23d0ba 199 Args:
marcozecchini 0:9fca2b23d0ba 200 target - Target to be built
marcozecchini 0:9fca2b23d0ba 201 program - Test program to build
marcozecchini 0:9fca2b23d0ba 202 user - mbed username
marcozecchini 0:9fca2b23d0ba 203 pw - mbed password
marcozecchini 0:9fca2b23d0ba 204 polls - Number of times to poll for results
marcozecchini 0:9fca2b23d0ba 205 url - THe URL for the online compiler API
marcozecchini 0:9fca2b23d0ba 206
marcozecchini 0:9fca2b23d0ba 207 Returns:
marcozecchini 0:9fca2b23d0ba 208 result - True/False indicating the success/failure of the compilation
marcozecchini 0:9fca2b23d0ba 209 fail_type - the failure text if the compilation failed, else None
marcozecchini 0:9fca2b23d0ba 210 """
marcozecchini 0:9fca2b23d0ba 211 payload = {'clean':True, 'target':target, 'program':program}
marcozecchini 0:9fca2b23d0ba 212 auth = (user, pw)
marcozecchini 0:9fca2b23d0ba 213 return invoke_api(payload, url, auth, polls)
marcozecchini 0:9fca2b23d0ba 214
marcozecchini 0:9fca2b23d0ba 215 def run_cmd(command, exit_on_failure=False):
marcozecchini 0:9fca2b23d0ba 216 """ Passes a command to the system and returns a True/False result once the
marcozecchini 0:9fca2b23d0ba 217 command has been executed, indicating success/failure. Commands are passed
marcozecchini 0:9fca2b23d0ba 218 as a list of tokens.
marcozecchini 0:9fca2b23d0ba 219 E.g. The command 'git remote -v' would be passed in as ['git', 'remote', '-v']
marcozecchini 0:9fca2b23d0ba 220
marcozecchini 0:9fca2b23d0ba 221 Args:
marcozecchini 0:9fca2b23d0ba 222 command - system command as a list of tokens
marcozecchini 0:9fca2b23d0ba 223 exit_on_failure - If True exit the program on failure (default = False)
marcozecchini 0:9fca2b23d0ba 224
marcozecchini 0:9fca2b23d0ba 225 Returns:
marcozecchini 0:9fca2b23d0ba 226 result - True/False indicating the success/failure of the command
marcozecchini 0:9fca2b23d0ba 227 """
marcozecchini 0:9fca2b23d0ba 228 rel_log.debug('[Exec] %s', ' '.join(command))
marcozecchini 0:9fca2b23d0ba 229 return_code = subprocess.call(command, shell=True)
marcozecchini 0:9fca2b23d0ba 230
marcozecchini 0:9fca2b23d0ba 231 if return_code:
marcozecchini 0:9fca2b23d0ba 232 rel_log.warning("The command '%s' failed with return code: %s",
marcozecchini 0:9fca2b23d0ba 233 (' '.join(command), return_code))
marcozecchini 0:9fca2b23d0ba 234 if exit_on_failure:
marcozecchini 0:9fca2b23d0ba 235 sys.exit(1)
marcozecchini 0:9fca2b23d0ba 236
marcozecchini 0:9fca2b23d0ba 237 return return_code
marcozecchini 0:9fca2b23d0ba 238
marcozecchini 0:9fca2b23d0ba 239 def run_cmd_with_output(command, exit_on_failure=False):
marcozecchini 0:9fca2b23d0ba 240 """ Passes a command to the system and returns a True/False result once the
marcozecchini 0:9fca2b23d0ba 241 command has been executed, indicating success/failure. If the command was
marcozecchini 0:9fca2b23d0ba 242 successful then the output from the command is returned to the caller.
marcozecchini 0:9fca2b23d0ba 243 Commands are passed as a list of tokens.
marcozecchini 0:9fca2b23d0ba 244 E.g. The command 'git remote -v' would be passed in as ['git', 'remote', '-v']
marcozecchini 0:9fca2b23d0ba 245
marcozecchini 0:9fca2b23d0ba 246 Args:
marcozecchini 0:9fca2b23d0ba 247 command - system command as a list of tokens
marcozecchini 0:9fca2b23d0ba 248 exit_on_failure - If True exit the program on failure (default = False)
marcozecchini 0:9fca2b23d0ba 249
marcozecchini 0:9fca2b23d0ba 250 Returns:
marcozecchini 0:9fca2b23d0ba 251 result - True/False indicating the success/failure of the command
marcozecchini 0:9fca2b23d0ba 252 output - The output of the command if it was successful, else empty string
marcozecchini 0:9fca2b23d0ba 253 """
marcozecchini 0:9fca2b23d0ba 254 rel_log.debug('[Exec] %s', ' '.join(command))
marcozecchini 0:9fca2b23d0ba 255 returncode = 0
marcozecchini 0:9fca2b23d0ba 256 output = ""
marcozecchini 0:9fca2b23d0ba 257 try:
marcozecchini 0:9fca2b23d0ba 258 output = subprocess.check_output(command, shell=True)
marcozecchini 0:9fca2b23d0ba 259 except subprocess.CalledProcessError as e:
marcozecchini 0:9fca2b23d0ba 260 rel_log.warning("The command '%s' failed with return code: %s",
marcozecchini 0:9fca2b23d0ba 261 (' '.join(command), e.returncode))
marcozecchini 0:9fca2b23d0ba 262 returncode = e.returncode
marcozecchini 0:9fca2b23d0ba 263 if exit_on_failure:
marcozecchini 0:9fca2b23d0ba 264 sys.exit(1)
marcozecchini 0:9fca2b23d0ba 265 return returncode, output
marcozecchini 0:9fca2b23d0ba 266
marcozecchini 0:9fca2b23d0ba 267 def upgrade_test_repo(test, user, library, ref, repo_path):
marcozecchini 0:9fca2b23d0ba 268 """ Upgrades a local version of a test repo to the latest version of its
marcozecchini 0:9fca2b23d0ba 269 embedded library.
marcozecchini 0:9fca2b23d0ba 270 If the test repo is not present in the user area specified in the json
marcozecchini 0:9fca2b23d0ba 271 config file, then it will first be cloned.
marcozecchini 0:9fca2b23d0ba 272 Args:
marcozecchini 0:9fca2b23d0ba 273 test - Mercurial test repo name
marcozecchini 0:9fca2b23d0ba 274 user - Mercurial user name
marcozecchini 0:9fca2b23d0ba 275 library - library name
marcozecchini 0:9fca2b23d0ba 276 ref - SHA corresponding to the latest version of the library
marcozecchini 0:9fca2b23d0ba 277 repo_path - path to the user's repo area
marcozecchini 0:9fca2b23d0ba 278
marcozecchini 0:9fca2b23d0ba 279 Returns:
marcozecchini 0:9fca2b23d0ba 280 updated - True if library was updated, False otherwise
marcozecchini 0:9fca2b23d0ba 281 """
marcozecchini 0:9fca2b23d0ba 282 rel_log.info("Updating test repo: '%s' to SHA: %s", test, ref)
marcozecchini 0:9fca2b23d0ba 283 cwd = os.getcwd()
marcozecchini 0:9fca2b23d0ba 284
marcozecchini 0:9fca2b23d0ba 285 repo = "https://" + user + '@developer.mbed.org/users/' + user + '/code/' + test
marcozecchini 0:9fca2b23d0ba 286
marcozecchini 0:9fca2b23d0ba 287 # Clone the repo if it doesn't already exist
marcozecchini 0:9fca2b23d0ba 288 path = abspath(repo_path + '/' + test)
marcozecchini 0:9fca2b23d0ba 289 if not os.path.exists(path):
marcozecchini 0:9fca2b23d0ba 290 rel_log.info("Test repo doesn't exist, cloning...")
marcozecchini 0:9fca2b23d0ba 291 os.chdir(abspath(repo_path))
marcozecchini 0:9fca2b23d0ba 292 clone_cmd = ['hg', 'clone', repo]
marcozecchini 0:9fca2b23d0ba 293 run_cmd(clone_cmd, exit_on_failure=True)
marcozecchini 0:9fca2b23d0ba 294
marcozecchini 0:9fca2b23d0ba 295 os.chdir(path)
marcozecchini 0:9fca2b23d0ba 296
marcozecchini 0:9fca2b23d0ba 297 client = hglib.open(path)
marcozecchini 0:9fca2b23d0ba 298
marcozecchini 0:9fca2b23d0ba 299 lib_file = library + '.lib'
marcozecchini 0:9fca2b23d0ba 300 if os.path.isfile(lib_file):
marcozecchini 0:9fca2b23d0ba 301 # Rename command will fail on some OS's if the target file already exist,
marcozecchini 0:9fca2b23d0ba 302 # so ensure if it does, it is deleted first.
marcozecchini 0:9fca2b23d0ba 303 bak_file = library + '_bak'
marcozecchini 0:9fca2b23d0ba 304 if os.path.isfile(bak_file):
marcozecchini 0:9fca2b23d0ba 305 os.remove(bak_file)
marcozecchini 0:9fca2b23d0ba 306
marcozecchini 0:9fca2b23d0ba 307 os.rename(lib_file, bak_file)
marcozecchini 0:9fca2b23d0ba 308 else:
marcozecchini 0:9fca2b23d0ba 309 rel_log.error("Failure to backup lib file prior to updating.")
marcozecchini 0:9fca2b23d0ba 310 return False
marcozecchini 0:9fca2b23d0ba 311
marcozecchini 0:9fca2b23d0ba 312 # mbed 2 style lib file contains one line with the following format
marcozecchini 0:9fca2b23d0ba 313 # e.g. https://developer.mbed.org/users/<user>/code/mbed-dev/#156823d33999
marcozecchini 0:9fca2b23d0ba 314 exp = 'https://developer.mbed.org/users/' + user + '/code/' + library + '/#[A-Za-z0-9]+'
marcozecchini 0:9fca2b23d0ba 315 lib_re = re.compile(exp)
marcozecchini 0:9fca2b23d0ba 316 updated = False
marcozecchini 0:9fca2b23d0ba 317
marcozecchini 0:9fca2b23d0ba 318 # Scan through mbed-os.lib line by line, looking for lib version and update
marcozecchini 0:9fca2b23d0ba 319 # it if found
marcozecchini 0:9fca2b23d0ba 320 with open(bak_file, 'r') as ip, open(lib_file, 'w') as op:
marcozecchini 0:9fca2b23d0ba 321 for line in ip:
marcozecchini 0:9fca2b23d0ba 322
marcozecchini 0:9fca2b23d0ba 323 opline = line
marcozecchini 0:9fca2b23d0ba 324
marcozecchini 0:9fca2b23d0ba 325 regexp = lib_re.match(line)
marcozecchini 0:9fca2b23d0ba 326 if regexp:
marcozecchini 0:9fca2b23d0ba 327 opline = 'https://developer.mbed.org/users/' + user + '/code/' + library + '/#' + ref
marcozecchini 0:9fca2b23d0ba 328 updated = True
marcozecchini 0:9fca2b23d0ba 329
marcozecchini 0:9fca2b23d0ba 330 op.write(opline)
marcozecchini 0:9fca2b23d0ba 331
marcozecchini 0:9fca2b23d0ba 332 if updated:
marcozecchini 0:9fca2b23d0ba 333
marcozecchini 0:9fca2b23d0ba 334 # Setup the default commit message
marcozecchini 0:9fca2b23d0ba 335 commit_message = '"Updating ' + library + ' to ' + ref + '"'
marcozecchini 0:9fca2b23d0ba 336
marcozecchini 0:9fca2b23d0ba 337 # Setup and run the commit command. Need to use the rawcommand in the hglib
marcozecchini 0:9fca2b23d0ba 338 # for this in order to pass the string value to the -m option. run_cmd using
marcozecchini 0:9fca2b23d0ba 339 # subprocess does not like this syntax.
marcozecchini 0:9fca2b23d0ba 340 try:
marcozecchini 0:9fca2b23d0ba 341 client.rawcommand(['commit','-m '+commit_message, lib_file])
marcozecchini 0:9fca2b23d0ba 342
marcozecchini 0:9fca2b23d0ba 343 cmd = ['hg', 'push', '-f', repo]
marcozecchini 0:9fca2b23d0ba 344 run_cmd(cmd, exit_on_failure=True)
marcozecchini 0:9fca2b23d0ba 345
marcozecchini 0:9fca2b23d0ba 346 except:
marcozecchini 0:9fca2b23d0ba 347 rel_log.info("Lib file already up to date and thus nothing to commit")
marcozecchini 0:9fca2b23d0ba 348
marcozecchini 0:9fca2b23d0ba 349 os.chdir(cwd)
marcozecchini 0:9fca2b23d0ba 350 return updated
marcozecchini 0:9fca2b23d0ba 351
marcozecchini 0:9fca2b23d0ba 352 def get_sha(repo_path, library):
marcozecchini 0:9fca2b23d0ba 353 """ Gets the latest SHA for the library specified. The library is assumed to be
marcozecchini 0:9fca2b23d0ba 354 located at the repo_path. If a SHA cannot be obtained this script will exit.
marcozecchini 0:9fca2b23d0ba 355
marcozecchini 0:9fca2b23d0ba 356 Args:
marcozecchini 0:9fca2b23d0ba 357 library - library name
marcozecchini 0:9fca2b23d0ba 358 repo_path - path to the user's repo area
marcozecchini 0:9fca2b23d0ba 359
marcozecchini 0:9fca2b23d0ba 360 Returns:
marcozecchini 0:9fca2b23d0ba 361 sha - last commit SHA
marcozecchini 0:9fca2b23d0ba 362 """
marcozecchini 0:9fca2b23d0ba 363 cwd = os.getcwd()
marcozecchini 0:9fca2b23d0ba 364 sha = None
marcozecchini 0:9fca2b23d0ba 365 os.chdir(abspath(repo_path + '/' + library))
marcozecchini 0:9fca2b23d0ba 366
marcozecchini 0:9fca2b23d0ba 367 cmd = ['hg', 'log', '-l', '1']
marcozecchini 0:9fca2b23d0ba 368 ret, output = run_cmd_with_output(cmd, exit_on_failure=True)
marcozecchini 0:9fca2b23d0ba 369
marcozecchini 0:9fca2b23d0ba 370 # Output should contain a 4 line string of the form:
marcozecchini 0:9fca2b23d0ba 371 # changeset: 135:176b8275d35d
marcozecchini 0:9fca2b23d0ba 372 # tag: tip
marcozecchini 0:9fca2b23d0ba 373 # user: <>
marcozecchini 0:9fca2b23d0ba 374 # date: Thu Feb 02 16:02:30 2017 +0000
marcozecchini 0:9fca2b23d0ba 375 # summary: Release 135 of the mbed library
marcozecchini 0:9fca2b23d0ba 376 # All we want is the changeset string after version number
marcozecchini 0:9fca2b23d0ba 377
marcozecchini 0:9fca2b23d0ba 378 lines = output.split('\n')
marcozecchini 0:9fca2b23d0ba 379 fields = lines[0].split(':')
marcozecchini 0:9fca2b23d0ba 380 sha = fields[2]
marcozecchini 0:9fca2b23d0ba 381
marcozecchini 0:9fca2b23d0ba 382 os.chdir(cwd)
marcozecchini 0:9fca2b23d0ba 383 return sha
marcozecchini 0:9fca2b23d0ba 384
marcozecchini 0:9fca2b23d0ba 385 def get_latest_library_versions(repo_path):
marcozecchini 0:9fca2b23d0ba 386 """ Returns the latest library versions (SHAs) for 'mbed' and 'mbed-dev'.
marcozecchini 0:9fca2b23d0ba 387 If the SHAs cannot be obtained this script will exit.
marcozecchini 0:9fca2b23d0ba 388
marcozecchini 0:9fca2b23d0ba 389 Args:
marcozecchini 0:9fca2b23d0ba 390 repo_path - path to the user's repo area
marcozecchini 0:9fca2b23d0ba 391
marcozecchini 0:9fca2b23d0ba 392 Returns:
marcozecchini 0:9fca2b23d0ba 393 mbed - last commit SHA for mbed library
marcozecchini 0:9fca2b23d0ba 394 mbed_dev - last commit SHA for mbed_dev library
marcozecchini 0:9fca2b23d0ba 395
marcozecchini 0:9fca2b23d0ba 396 """
marcozecchini 0:9fca2b23d0ba 397
marcozecchini 0:9fca2b23d0ba 398 mbed = get_sha(repo_path, 'mbed')
marcozecchini 0:9fca2b23d0ba 399 mbed_dev = get_sha(repo_path, 'mbed-dev')
marcozecchini 0:9fca2b23d0ba 400
marcozecchini 0:9fca2b23d0ba 401 return mbed, mbed_dev
marcozecchini 0:9fca2b23d0ba 402
marcozecchini 0:9fca2b23d0ba 403 def log_results(lst, title):
marcozecchini 0:9fca2b23d0ba 404 if len(lst) == 0:
marcozecchini 0:9fca2b23d0ba 405 rel_log.info("%s - None", title)
marcozecchini 0:9fca2b23d0ba 406 else:
marcozecchini 0:9fca2b23d0ba 407 for entry in lst:
marcozecchini 0:9fca2b23d0ba 408 rel_log.info("%s - Test: %s, Target: %s", title, entry[0], entry[1])
marcozecchini 0:9fca2b23d0ba 409
marcozecchini 0:9fca2b23d0ba 410
marcozecchini 0:9fca2b23d0ba 411 if __name__ == '__main__':
marcozecchini 0:9fca2b23d0ba 412
marcozecchini 0:9fca2b23d0ba 413 parser = argparse.ArgumentParser(description=__doc__,
marcozecchini 0:9fca2b23d0ba 414 formatter_class=argparse.RawDescriptionHelpFormatter)
marcozecchini 0:9fca2b23d0ba 415 parser.add_argument('-l', '--log-level',
marcozecchini 0:9fca2b23d0ba 416 help="Level for providing logging output",
marcozecchini 0:9fca2b23d0ba 417 default='INFO')
marcozecchini 0:9fca2b23d0ba 418 args = parser.parse_args()
marcozecchini 0:9fca2b23d0ba 419
marcozecchini 0:9fca2b23d0ba 420 default = getattr(logging, 'INFO')
marcozecchini 0:9fca2b23d0ba 421 level = getattr(logging, args.log_level.upper(), default)
marcozecchini 0:9fca2b23d0ba 422
marcozecchini 0:9fca2b23d0ba 423 # Set logging level
marcozecchini 0:9fca2b23d0ba 424 logging.basicConfig(level=level)
marcozecchini 0:9fca2b23d0ba 425 rel_log = logging.getLogger("check-release")
marcozecchini 0:9fca2b23d0ba 426
marcozecchini 0:9fca2b23d0ba 427 # Read configuration data
marcozecchini 0:9fca2b23d0ba 428 with open(os.path.join(os.path.dirname(__file__), "check_release.json")) as config:
marcozecchini 0:9fca2b23d0ba 429 json_data = json.load(config)
marcozecchini 0:9fca2b23d0ba 430
marcozecchini 0:9fca2b23d0ba 431 supported_targets = []
marcozecchini 0:9fca2b23d0ba 432
marcozecchini 0:9fca2b23d0ba 433 if len(json_data["target_list"]) > 0:
marcozecchini 0:9fca2b23d0ba 434 # Compile user supplied subset of targets
marcozecchini 0:9fca2b23d0ba 435 supported_targets = json_data["target_list"]
marcozecchini 0:9fca2b23d0ba 436 else:
marcozecchini 0:9fca2b23d0ba 437 # Get a list of the officially supported mbed-os 2 targets
marcozecchini 0:9fca2b23d0ba 438 for tgt in OFFICIAL_MBED_LIBRARY_BUILD:
marcozecchini 0:9fca2b23d0ba 439 supported_targets.append(tgt[0])
marcozecchini 0:9fca2b23d0ba 440
marcozecchini 0:9fca2b23d0ba 441 ignore_list = []
marcozecchini 0:9fca2b23d0ba 442
marcozecchini 0:9fca2b23d0ba 443 if len(json_data["ignore_list"]) > 0:
marcozecchini 0:9fca2b23d0ba 444 # List of tuples of (test, target) to be ignored in this test
marcozecchini 0:9fca2b23d0ba 445 ignore_list = json_data["ignore_list"]
marcozecchini 0:9fca2b23d0ba 446
marcozecchini 0:9fca2b23d0ba 447 config = json_data["config"]
marcozecchini 0:9fca2b23d0ba 448 test_list = json_data["test_list"]
marcozecchini 0:9fca2b23d0ba 449 repo_path = config["mbed_repo_path"]
marcozecchini 0:9fca2b23d0ba 450 tests = []
marcozecchini 0:9fca2b23d0ba 451
marcozecchini 0:9fca2b23d0ba 452 # get username
marcozecchini 0:9fca2b23d0ba 453 cmd = ['hg', 'config', 'auth.x.username']
marcozecchini 0:9fca2b23d0ba 454 ret, output = run_cmd_with_output(cmd, exit_on_failure=True)
marcozecchini 0:9fca2b23d0ba 455 output = output.split('\n')
marcozecchini 0:9fca2b23d0ba 456 user = output[0]
marcozecchini 0:9fca2b23d0ba 457
marcozecchini 0:9fca2b23d0ba 458 # get password
marcozecchini 0:9fca2b23d0ba 459 cmd = ['hg', 'config', 'auth.x.password']
marcozecchini 0:9fca2b23d0ba 460 ret, output = run_cmd_with_output(cmd, exit_on_failure=True)
marcozecchini 0:9fca2b23d0ba 461 output = output.split('\n')
marcozecchini 0:9fca2b23d0ba 462 password = output[0]
marcozecchini 0:9fca2b23d0ba 463
marcozecchini 0:9fca2b23d0ba 464 mbed, mbed_dev = get_latest_library_versions(repo_path)
marcozecchini 0:9fca2b23d0ba 465
marcozecchini 0:9fca2b23d0ba 466 if not mbed or not mbed_dev:
marcozecchini 0:9fca2b23d0ba 467 rel_log.error("Could not obtain latest versions of library files!!")
marcozecchini 0:9fca2b23d0ba 468 exit(1)
marcozecchini 0:9fca2b23d0ba 469
marcozecchini 0:9fca2b23d0ba 470 rel_log.info("Latest mbed lib version = %s", mbed)
marcozecchini 0:9fca2b23d0ba 471 rel_log.info("Latest mbed-dev lib version = %s", mbed_dev)
marcozecchini 0:9fca2b23d0ba 472
marcozecchini 0:9fca2b23d0ba 473 # First update test repos to latest versions of their embedded libraries
marcozecchini 0:9fca2b23d0ba 474 for test in test_list:
marcozecchini 0:9fca2b23d0ba 475 tests.append(test['name'])
marcozecchini 0:9fca2b23d0ba 476 upgrade_test_repo(test['name'], user, test['lib'],
marcozecchini 0:9fca2b23d0ba 477 mbed if test['lib'] == "mbed" else mbed_dev,
marcozecchini 0:9fca2b23d0ba 478 repo_path)
marcozecchini 0:9fca2b23d0ba 479
marcozecchini 0:9fca2b23d0ba 480 total = len(supported_targets) * len(tests)
marcozecchini 0:9fca2b23d0ba 481 current = 0
marcozecchini 0:9fca2b23d0ba 482 retries = 10
marcozecchini 0:9fca2b23d0ba 483 passes = 0
marcozecchini 0:9fca2b23d0ba 484 failures = []
marcozecchini 0:9fca2b23d0ba 485 skipped = []
marcozecchini 0:9fca2b23d0ba 486
marcozecchini 0:9fca2b23d0ba 487 # Compile each test for each supported target
marcozecchini 0:9fca2b23d0ba 488 for test in tests:
marcozecchini 0:9fca2b23d0ba 489 for target in supported_targets:
marcozecchini 0:9fca2b23d0ba 490
marcozecchini 0:9fca2b23d0ba 491 combo = [test, target]
marcozecchini 0:9fca2b23d0ba 492
marcozecchini 0:9fca2b23d0ba 493 if combo in ignore_list:
marcozecchini 0:9fca2b23d0ba 494 rel_log.info("SKIPPING TEST: %s, TARGET: %s", test, target)
marcozecchini 0:9fca2b23d0ba 495 total -= 1
marcozecchini 0:9fca2b23d0ba 496 skipped.append(combo)
marcozecchini 0:9fca2b23d0ba 497 continue
marcozecchini 0:9fca2b23d0ba 498
marcozecchini 0:9fca2b23d0ba 499 current += 1
marcozecchini 0:9fca2b23d0ba 500 for retry in range(0, retries):
marcozecchini 0:9fca2b23d0ba 501 rel_log.info("COMPILING (%d/%d): TEST %s, TARGET: %s , attempt %u\n", current, total, test, target, retry)
marcozecchini 0:9fca2b23d0ba 502 result, mesg = build_repo(target, test, user, password)
marcozecchini 0:9fca2b23d0ba 503 if not result:
marcozecchini 0:9fca2b23d0ba 504 if mesg == 'Internal':
marcozecchini 0:9fca2b23d0ba 505 # Internal compiler error thus retry
marcozecchini 0:9fca2b23d0ba 506 continue
marcozecchini 0:9fca2b23d0ba 507 else:
marcozecchini 0:9fca2b23d0ba 508 # Actual error thus move on to next compilation
marcozecchini 0:9fca2b23d0ba 509 failures.append(combo)
marcozecchini 0:9fca2b23d0ba 510 break
marcozecchini 0:9fca2b23d0ba 511
marcozecchini 0:9fca2b23d0ba 512 passes += (int)(result)
marcozecchini 0:9fca2b23d0ba 513 break
marcozecchini 0:9fca2b23d0ba 514 else:
marcozecchini 0:9fca2b23d0ba 515 rel_log.error("Compilation failed due to internal errors.")
marcozecchini 0:9fca2b23d0ba 516 rel_log.error("Skipping test/target combination.")
marcozecchini 0:9fca2b23d0ba 517 total -= 1
marcozecchini 0:9fca2b23d0ba 518 skipped.append(combo)
marcozecchini 0:9fca2b23d0ba 519
marcozecchini 0:9fca2b23d0ba 520 rel_log.info(" SUMMARY OF COMPILATION RESULTS")
marcozecchini 0:9fca2b23d0ba 521 rel_log.info(" ------------------------------")
marcozecchini 0:9fca2b23d0ba 522 rel_log.info(" NUMBER OF TEST APPS: %d, NUMBER OF TARGETS: %d",
marcozecchini 0:9fca2b23d0ba 523 len(tests), len(supported_targets))
marcozecchini 0:9fca2b23d0ba 524 log_results(failures, " FAILED")
marcozecchini 0:9fca2b23d0ba 525 log_results(skipped, " SKIPPED")
marcozecchini 0:9fca2b23d0ba 526
marcozecchini 0:9fca2b23d0ba 527 # Output a % pass rate, indicate a failure if not 100% successful
marcozecchini 0:9fca2b23d0ba 528 pass_rate = (float(passes) / float(total)) * 100.0
marcozecchini 0:9fca2b23d0ba 529 rel_log.info(" PASS RATE %.1f %%\n", pass_rate)
marcozecchini 0:9fca2b23d0ba 530 sys.exit(not (pass_rate == 100))