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