|
| 1 | +name: Note Binary CI |
| 2 | + |
| 3 | +on: |
| 4 | + pull_request: |
| 5 | + branches: [ master ] |
| 6 | + workflow_dispatch: |
| 7 | + schedule: |
| 8 | + # * is a special character in YAML so you have to quote this string |
| 9 | + - cron: '45 4 * * 1' # 4.45am every Monday |
| 10 | + |
| 11 | +permissions: |
| 12 | + checks: write |
| 13 | + |
| 14 | +jobs: |
| 15 | + md5srv-test: |
| 16 | + uses: ./.github/workflows/md5srv-tests.yml |
| 17 | + |
| 18 | + notecard-binary-test: |
| 19 | + # needs: md5srv-test |
| 20 | + runs-on: [self-hosted, swan, notecard, stlink, notecard-serial, md5srv, notehub-client] |
| 21 | + defaults: |
| 22 | + run: |
| 23 | + shell: bash |
| 24 | + env: |
| 25 | + NOTEHUB: "notehub.io" |
| 26 | + NOTEHUB_API: "api.notefile.net" |
| 27 | + NOTEHUB_ROUTE_TIMEOUT: 180 |
| 28 | + PIO_PROJECT_DIR: ./test/hitl/card.binary |
| 29 | + NOTEHUB_PROXY_ROUTE_ALIAS: card.binary.${{github.run_id}} |
| 30 | + NOTEHUB_PROXY_ROUTE_LABEL: card.binary.proxy.${{github.run_id}} |
| 31 | + NOTEHUB_HTTP_ROUTE_LABEL: card.binary.http.${{github.run_id}} |
| 32 | + |
| 33 | + # Troubleshooting helpers |
| 34 | + # DELETE_NOTEHUB_ROUTES set to false to see the created routes on notehub |
| 35 | + DELETE_NOTEHUB_ROUTES: true |
| 36 | + # CREATE_NOTEHUB_ROUTES set to false to use the already created routes on notehub |
| 37 | + CREATE_NOTEHUB_ROUTES: true |
| 38 | + # FLASH_TEST_FIRMWARE set to false to skip flashing firmware to the Host (Swan). |
| 39 | + # Be sure to press reset on Swan before running the workflow unless you deliberately want to skip running the tests. |
| 40 | + FLASH_TEST_FIRMWARE: true |
| 41 | + # START_MD5SRV set to false to skip starting the MD5 server. There should be one |
| 42 | + # already running locally with MD5SRV_PORT/ADDRESS/TOKEN set correspondingly. |
| 43 | + START_MD5SRV: true |
| 44 | + # START_LOCALTUNNEL, set to false to skip starting the localtunnel. |
| 45 | + START_LOCALTUNNEL: false |
| 46 | + # START_TUNNELMOLE: set to false to skip starting tunnel mole. |
| 47 | + START_TUNNELMOLE: true |
| 48 | + # When neither tunneling solution is used (because they're already instantiated outside of the workflow) |
| 49 | + # be sure to set MD5SRV_URL in the environment |
| 50 | + steps: |
| 51 | + - name: Checkout |
| 52 | + uses: actions/checkout@v3 |
| 53 | + - name: Generate MD5 Server Token |
| 54 | + run: | |
| 55 | + [ -n "$MD5SRV_TOKEN" ] || echo "MD5SRV_TOKEN=`uuidgen`" >> $GITHUB_ENV |
| 56 | + # propagate the environment variable so that it's available in the `env` context |
| 57 | + echo "MD5SRV_PORT=$MD5SRV_PORT" >> $GITHUB_ENV |
| 58 | + - name: Check Env Vars |
| 59 | + run: | |
| 60 | + . scripts/check_runner_config.sh |
| 61 | + echo NOTEHUB_PROXY_ROUTE_ALIAS=$NOTEHUB_PROXY_ROUTE_ALIAS |
| 62 | + - name: Prep MD5 Server |
| 63 | + uses: pyTooling/Actions/[email protected] |
| 64 | + with: |
| 65 | + main: | |
| 66 | + [ -e md5srv-files ] || mkdir md5srv-files |
| 67 | + rm -rf md5srv-files/* |
| 68 | + md5url=http://${MD5SRV_ADDRESS}:${MD5SRV_PORT}/ |
| 69 | + post: | |
| 70 | + # the JarvusInnovations/background-action@v1 that launches the background |
| 71 | + # process doesn't clean them up. We do that here. MD5SRV_PID is set in the |
| 72 | + # ./scripts/run_md5srv.sh script |
| 73 | + echo Stop MD5 Server |
| 74 | + [ -n "$MD5SRV_PID" ] || (echo "MD5SRV_PID not set" && exit 1) |
| 75 | + [ -z "$MD5SRV_PID" ] || kill $MD5SRV_PID |
| 76 | + rm -rf md5srv-files |
| 77 | +
|
| 78 | + - name: Install PlatformIO dependencies |
| 79 | + if: env.FLASH_TEST_FIRMWARE!='false' |
| 80 | + run: | |
| 81 | + python3 -m venv venv # python venv is also used by the md5server, so this comes first. |
| 82 | + source venv/bin/activate |
| 83 | + pip install platformio |
| 84 | + cd $PIO_PROJECT_DIR |
| 85 | + pio pkg install -l "Blues Wireless Notecard" -e debug |
| 86 | + # Remove the bundled note-c and put the local working copy there |
| 87 | + NOTE_C_DEP="$GITHUB_WORKSPACE/$PIO_PROJECT_DIR/.pio/libdeps/debug/Blues Wireless Notecard/src/note-c" |
| 88 | + rm -rf "$NOTE_C_DEP" |
| 89 | + mkdir "$NOTE_C_DEP" |
| 90 | + # copy only files in note-c |
| 91 | + find "$GITHUB_WORKSPACE" -maxdepth 1 -type f -exec cp "{}" "${NOTE_C_DEP}" \; |
| 92 | +
|
| 93 | + - name: Start MD5 Server |
| 94 | + uses: JarvusInnovations/background-action@v1 |
| 95 | + with: |
| 96 | + run: | |
| 97 | + bash ./scripts/run_md5srv.sh |
| 98 | + wait-on: |
| 99 | + # just a dummy wait-on since this is required. |
| 100 | + file:${{github.workspace}}/scripts/run_md5srv.sh |
| 101 | + |
| 102 | + # When done this way, the background process is terminated at the end of the step, |
| 103 | + # At least when running with `act`. The same may be true of github runners also. |
| 104 | + # - name: Start MD5 Server |
| 105 | + # uses: pyTooling/Actions/[email protected] |
| 106 | + # with: |
| 107 | + # main: | |
| 108 | + # ./run_md5srv.sh |
| 109 | + # echo "MD5SRV_PID=$MD5SRV_PID" |
| 110 | + # echo "MD5SRV_PID=$MD5SRV_PID" >> $GITHUB_ENV |
| 111 | + # echo "writing server log to `realpath md5srv.log`" |
| 112 | + # md5url=http://${MD5SRV_ADDRESS}:${MD5SRV_PORT}/ |
| 113 | + # post: | |
| 114 | + # echo Stop MD5 Server |
| 115 | + # [ -n "$MD5SRV_PID" ] || (echo "MD5SRV_PID not set" && exit 1) |
| 116 | + # # [ -z "$MD5SRV_PID" ] || kill $MD5SRV_PID |
| 117 | + # rm -rf md5srv-files |
| 118 | + |
| 119 | + - name: Build and Upload Test Firmware |
| 120 | + if: env.FLASH_TEST_FIRMWARE!='false' |
| 121 | + run: | |
| 122 | + source venv/bin/activate |
| 123 | + export PLATFORMIO_BUILD_FLAGS="'-D NOTEHUB_PROXY_ROUTE_ALIAS=\"$NOTEHUB_PROXY_ROUTE_ALIAS\"' '-D PRODUCT_UID=\"$NOTEHUB_PRODUCT_UID\"'" |
| 124 | + echo "build flags $PLATFORMIO_BUILD_FLAGS" |
| 125 | + timeout 10 ./scripts/wait_for_file.sh "$STLINK_PROGRAMMER_PORT" |
| 126 | + platformio test -e debug --without-testing --upload-port "$STLINK_PROGRAMMER_PORT" --project-dir "$PIO_PROJECT_DIR" |
| 127 | + timeout 10 ./scripts/wait_for_file.sh "$SWAN_SERIAL" |
| 128 | +
|
| 129 | + - name: Start localtunnel |
| 130 | + if: env.START_LOCALTUNNEL!='false' |
| 131 | + id: localtunnel |
| 132 | + uses: Rei-x/expose-localtunnel-action@main |
| 133 | + with: |
| 134 | + ports: ${{ env.MD5SRV_PORT }} |
| 135 | + - name: Fetch localtunnel URL |
| 136 | + if: env.START_LOCALTUNNEL!='false' |
| 137 | + run: | |
| 138 | + MD5SRV_URL="${{steps.localtunnel.outputs.url-1}}" |
| 139 | + echo "MD5SRV_URL=$MD5SRV_URL" >> $GITHUB_ENV |
| 140 | +
|
| 141 | + - name: Prep tunnelmole |
| 142 | + if: env.START_TUNNELMOLE!='false' |
| 143 | + uses: pyTooling/Actions/[email protected] |
| 144 | + with: |
| 145 | + main: | |
| 146 | + [ ! -e tmole.log ] || rm tmole.log |
| 147 | + sleep 2 # otherwise it thinks we exited early |
| 148 | + post: | |
| 149 | + # the JarvusInnovations/background-action@v1 that launches the background |
| 150 | + # process doesn't clean them up. We do that here. TMOLE_PID is set in the |
| 151 | + # ./scripts/run_tunnelmole.sh script |
| 152 | + echo Stop Tunnelmole |
| 153 | + [ -n "$TMOLE_PID" ] || (echo "TMOLE_PID not set" && exit 1) |
| 154 | + [ -z "$TMOLE_PID" ] || kill $TMOLE_PID |
| 155 | + # Remove the tmole_ready file, which may be leftover from a prior |
| 156 | + # run. |
| 157 | + rm -f $GITHUB_WORKSPACE/tmole_ready |
| 158 | +
|
| 159 | + - name: Start tunnelmole |
| 160 | + uses: JarvusInnovations/background-action@v1 |
| 161 | + if: env.START_TUNNELMOLE!='false' |
| 162 | + with: |
| 163 | + run: | |
| 164 | + bash ./scripts/run_tunnelmole.sh |
| 165 | + log-output-if: true |
| 166 | + wait-on: |
| 167 | + file:${{github.workspace}}/tmole_ready |
| 168 | + |
| 169 | + - name: Check server is available |
| 170 | + run: | |
| 171 | + # the request will return a 401 from md5srv, but that's expected without the access token |
| 172 | + # Curl still returns success because it could contact the server |
| 173 | + code=`curl -s -o /dev/null -w "%{http_code}" $MD5SRV_URL` |
| 174 | + [ "$code" -lt "500" ] || ( echo "5xx error ($code) from tunnel." && exit 1 ) |
| 175 | +
|
| 176 | + - name: Create Notehub accesss token |
| 177 | + if: env.CREATE_NOTEHUB_ROUTES!='false' |
| 178 | + run: | |
| 179 | + curl -f -X POST \ |
| 180 | + -L 'https://${{env.NOTEHUB}}/oauth2/token' \ |
| 181 | + -H 'content-type: application/x-www-form-urlencoded' \ |
| 182 | + -d grant_type=client_credentials \ |
| 183 | + -d client_id=$NOTEHUB_CLIENT_ID \ |
| 184 | + -d client_secret=$NOTEHUB_CLIENT_SECRET | \ |
| 185 | + { token=$(jq -r .access_token); echo "NOTEHUB_ACCESS_TOKEN=$token" >> $GITHUB_ENV; } |
| 186 | +
|
| 187 | + - name: Create Notehub HTTP Route |
| 188 | + if: env.CREATE_NOTEHUB_ROUTES!='false' |
| 189 | + uses: pyTooling/Actions/[email protected] |
| 190 | + with: |
| 191 | + main: | |
| 192 | + # ?note=1 instructs the MD5 server to process the content as an event, extracting the path |
| 193 | + # from the event body. |
| 194 | + route_req=`jq -n --arg TOKEN "$MD5SRV_TOKEN" --arg LABEL "$NOTEHUB_HTTP_ROUTE_LABEL" --arg URL "$MD5SRV_URL/?note=1" --argjson TIMEOUT $NOTEHUB_ROUTE_TIMEOUT \ |
| 195 | + '{ "label":$LABEL, "type":"http", "http":{ "timeout":$TIMEOUT, "filter": { "type":"include", "files": ["cardbinary.qo"] }, "url":$URL, "http_headers": { "X-Access-Token":$TOKEN } } }'` |
| 196 | + echo $route_req |
| 197 | + route=`echo "$route_req" | curl -s -f -X POST -L "https://$NOTEHUB_API/v1/projects/${NOTEHUB_PROJECT_UID}/routes" \ |
| 198 | + -H "Authorization: Bearer $NOTEHUB_ACCESS_TOKEN" -d @-` |
| 199 | + echo $route |
| 200 | + route_uid=`echo $route | jq -r .uid` |
| 201 | + [ -n "$route_uid" ] |
| 202 | + echo "NOTEHUB_HTTP_ROUTE_UID=$route_uid" >> $GITHUB_ENV |
| 203 | + post: | |
| 204 | + echo Delete Notehub HTTP Route |
| 205 | + [ "$DELETE_NOTEHUB_ROUTES" == "false" ] || ([ -n "$NOTEHUB_HTTP_ROUTE_UID" ] && curl -f -s -X DELETE \ |
| 206 | + -L "https://$NOTEHUB_API/v1/projects/$NOTEHUB_PROJECT_UID/routes/$NOTEHUB_HTTP_ROUTE_UID" \ |
| 207 | + -H "Authorization: Bearer $NOTEHUB_ACCESS_TOKEN") |
| 208 | +
|
| 209 | + - name: Create Notehub Proxy Route |
| 210 | + if: env.CREATE_NOTEHUB_ROUTES!='false' |
| 211 | + uses: pyTooling/Actions/[email protected] |
| 212 | + with: |
| 213 | + main: | |
| 214 | + ALIAS=$NOTEHUB_PROXY_ROUTE_ALIAS |
| 215 | + route=`jq -n --arg TOKEN "$MD5SRV_TOKEN" --arg LABEL "$NOTEHUB_PROXY_ROUTE_LABEL" --arg URL "$MD5SRV_URL" --arg ALIAS "$ALIAS" --argjson TIMEOUT $NOTEHUB_ROUTE_TIMEOUT \ |
| 216 | + '{ "label":$LABEL, "type":"proxy", "proxy":{ "timeout":$TIMEOUT, "url":$URL, "alias":$ALIAS, "http_headers": { "X-Access-Token":$TOKEN } } }' \ |
| 217 | + | curl -s -f -X POST -L "https://api.notefile.net/v1/projects/${NOTEHUB_PROJECT_UID}/routes" \ |
| 218 | + -H "Authorization: Bearer $NOTEHUB_ACCESS_TOKEN" -d @-` |
| 219 | + echo $route |
| 220 | + route_uid=`echo $route | jq -r .uid` |
| 221 | + [ -n $route_uid ] |
| 222 | + echo "NOTEHUB_PROXY_ROUTE_UID=$route_uid" >> $GITHUB_ENV |
| 223 | + echo "NOTEHUB_PROXY_ROUTE_ALIAS=$ALIAS" >> $GITHUB_ENV |
| 224 | + post: | |
| 225 | + echo Delete Notehub Proxy Route |
| 226 | + [ "$DELETE_NOTEHUB_ROUTES" == "false" ] || ([ -n "$NOTEHUB_PROXY_ROUTE_UID" ] && curl -f -s -X DELETE \ |
| 227 | + -L "https://api.notefile.net/v1/projects/$NOTEHUB_PROJECT_UID/routes/$NOTEHUB_PROXY_ROUTE_UID" \ |
| 228 | + -H "Authorization: Bearer $NOTEHUB_ACCESS_TOKEN") |
| 229 | +
|
| 230 | + - name: Run Tests |
| 231 | + run: | |
| 232 | + source venv/bin/activate |
| 233 | + cd $PIO_PROJECT_DIR |
| 234 | + platformio test -v -e debug \ |
| 235 | + --without-building --without-uploading \ |
| 236 | + --test-port "$SWAN_SERIAL" \ |
| 237 | + --json-output-path test.json \ |
| 238 | + --junit-output-path test.xml \ |
| 239 | +
|
| 240 | + - name: Publish Test Report |
| 241 | + uses: mikepenz/action-junit-report@v3 |
| 242 | + env: |
| 243 | + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 244 | + if: env.GITHUB_TOKEN && (success() || failure()) # always run even if the previous step fails |
| 245 | + with: |
| 246 | + report_paths: '**/test/hitl/card.binary/test*.xml' |
| 247 | + check_name: Notecard Binary HIL Tests |
| 248 | + require_tests: true |
0 commit comments