Skip to content

Commit b50f499

Browse files
authored
Make changes to support HitL testing. (#69)
1 parent 044eae6 commit b50f499

29 files changed

+1717
-98
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#
2+
3+
name: HIL-circuitpython
4+
5+
on:
6+
pull_request:
7+
branches: [ main ]
8+
paths:
9+
# This is quite a big job so run only when files affecting it change.
10+
- .github/workflows/hil-circuitpython.yml
11+
- examples/notecard-basics/cpy_example.py
12+
- test/hitl/**
13+
- test/scripts/usbmount
14+
- test/scripts/check_cpy*.*
15+
- notecard/**
16+
17+
workflow_dispatch:
18+
inputs:
19+
flash_device:
20+
required: false
21+
type: boolean
22+
default: true
23+
24+
jobs:
25+
test:
26+
runs-on: [self-hosted, linux, circuitpython, swan-3.0, notecard-serial]
27+
defaults:
28+
run:
29+
shell: bash
30+
strategy:
31+
matrix:
32+
CIRCUITPYTHON_VERSION: [8.2.2]
33+
flash_device: # has to be an array - use the input from workflow_dispatch if present, otherwlse true
34+
- ${{ github.event.inputs.flash_device=='' && true || github.event.inputs.flash_device }}
35+
lock_cpy_filesystem: [true]
36+
env:
37+
USB_MSD_ATTACH_TIME: 15
38+
CIRCUITPYTHON_UF2: "adafruit-circuitpython-swan_r5-en_US-${{ matrix.CIRCUITPYTHON_VERSION }}.uf2"
39+
CIRCUITPYTHON_VERSION: ${{ matrix.CIRCUITPYTHON_VERSION}}
40+
steps:
41+
- name: Checkout Code
42+
uses: actions/checkout@v3
43+
44+
- name: Set Env Vars
45+
run: |
46+
# environment variables set in a step cannot be used until subsequent steps
47+
echo "CIRCUITPYTHON_UF2_URL=https://downloads.circuitpython.org/bin/swan_r5/en_US/${CIRCUITPYTHON_UF2}" >> $GITHUB_ENV
48+
49+
- name: Check Runner Config
50+
run: test/scripts/check_cpy_runner_config.sh
51+
52+
- name: Download Latest Bootloader
53+
env:
54+
REPO: adafruit/tinyuf2
55+
ASSET: tinyuf2-swan_r5
56+
if: ${{ matrix.flash_device }}
57+
run: |
58+
echo "retrieving the latest release from ${REPO}"
59+
wget -q -O latest.json "https://api.github.com/repos/${REPO}/releases/latest"
60+
61+
echo "extracting asset details for ${ASSET}"
62+
asset_file="${ASSET}_asset.json"
63+
jq -r --arg ASSET "$ASSET" '.assets[] | select(.name | startswith($ASSET))' latest.json > $asset_file
64+
65+
# extract the name and download url without double quotes
66+
download_name=$(jq -r '.name' $asset_file)
67+
download_url=$(jq -r '.browser_download_url' $asset_file)
68+
echo "Downloading release from $download_url"
69+
wget -q -N $download_url
70+
unzip -o $download_name
71+
binfile=$(basename $download_name .zip).bin
72+
echo "TINYUF2_BIN=$binfile" >> $GITHUB_ENV
73+
74+
- name: Download CircuitPython v${{ env.CIRCUITPYTHON_VERSION }}
75+
if: ${{ matrix.flash_device }}
76+
run: |
77+
echo "Downloading CircuitPython for Swan from $CIRCUITPYTHON_UF2_URL"
78+
wget -q -N "$CIRCUITPYTHON_UF2_URL"
79+
80+
- name: Erase device and program bootloader
81+
if: ${{ matrix.flash_device }}
82+
run: |
83+
# cannot use st-flash - every 2nd programing incorrectly puts the device in DFU mode
84+
# st-flash --reset write $binfile 0x8000000
85+
# Have to use the version of openocd bundled with the STM32 platform in PlatformIO, which (presumably) has the stm32 extensions compiled in
86+
~/.platformio/packages/tool-openocd/bin/openocd \
87+
-d2 -s ~/.platformio/packages/tool-openocd/openocd/scripts \
88+
-f interface/stlink.cfg -c "transport select hla_swd" -f target/stm32l4x.cfg \
89+
-c "init; halt; stm32l4x mass_erase 0" \
90+
-c "program $TINYUF2_BIN 0x8000000 verify reset; shutdown"
91+
92+
- name: Program CircuitPython
93+
if: ${{ matrix.flash_device }}
94+
run: |
95+
# wait for the bootloader drive to appear
96+
timeout $USB_MSD_ATTACH_TIME bash test/scripts/wait_for_file.sh "$CPY_FS_UF2"
97+
98+
# The bootloader reboots quickly once the whole file has been received,
99+
# causing an input/output error to be reported.
100+
# Ignore that, and fail if the CIRCUITPY filesystem doesn't appear
101+
echo "Uploading CircuitPython binary..."
102+
cp "$CIRCUITPYTHON_UF2" "$CPY_FS_UF2" || true
103+
echo Ignore the input/output error above. Waiting for device to boot.
104+
timeout $USB_MSD_ATTACH_TIME bash test/scripts/wait_for_file.sh "$CPY_FS_CIRCUITPY"
105+
echo "CircuitPython binary uploaded and running."
106+
107+
- name: Make CircuitPython filesystem writeable to pyboard
108+
if: ${{ matrix.lock_cpy_filesystem }}
109+
run: |
110+
timeout $USB_MSD_ATTACH_TIME bash test/scripts/wait_for_file.sh "$CPY_FS_CIRCUITPY"
111+
112+
# only copy if it's changed or not present. After the device has reset, no further changes can be made
113+
# until the filesystem is erased. This allows the workflow to be rerun flash_device=false
114+
diff test/hitl/boot.py "$CPY_FS_CIRCUITPY/boot.py" || cp test/hitl/boot.py "$CPY_FS_CIRCUITPY"
115+
116+
# reset the device (todo move this blob to a utility script)
117+
~/.platformio/packages/tool-openocd/bin/openocd \
118+
-d2 -s ~/.platformio/packages/tool-openocd/openocd/scripts \
119+
-f interface/stlink.cfg -c "transport select hla_swd" -f target/stm32l4x.cfg \
120+
-c "init; halt; reset; shutdown"
121+
122+
# wait for the device to come back
123+
timeout $USB_MSD_ATTACH_TIME bash test/scripts/wait_for_file.sh "$CPY_FS_CIRCUITPY"
124+
125+
- name: Setup Python
126+
run: |
127+
python3 -m venv .venv-runner
128+
. .venv-runner/bin/activate
129+
pip install -r test/hitl/requirements.txt
130+
131+
- name: Setup 'note-python' on device
132+
if: ${{ ! matrix.lock_cpy_filesystem }}
133+
run: |
134+
mkdir -p ${CPY_FS_CIRCUITPY}/lib/notecard
135+
cp notecard/*.py ${CPY_FS_CIRCUITPY}/lib/notecard/
136+
cp examples/notecard-basics/cpy_example.py ${CPY_FS_CIRCUITPY}/example.py
137+
138+
- name: Run CircuitPython Tests
139+
run: |
140+
. .venv-runner/bin/activate
141+
${{ ! matrix.lock_cpy_filesystem }} && skipsetup=--skipsetup
142+
pytest $skipsetup "--productuid=$CPY_PRODUCT_UID" "--port=$CPY_SERIAL" --platform=circuitpython test/hitl
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
name: HIL-micropython
2+
3+
on:
4+
pull_request:
5+
branches: [ main ]
6+
paths:
7+
- .github/workflows/hil-micropython.yml
8+
- test/hitl/**
9+
- notecard/**
10+
- examples/notecard-basics/mpy_example.py
11+
- test/scripts/check_mpy*.*
12+
13+
workflow_dispatch:
14+
inputs:
15+
flash_device:
16+
required: false
17+
type: boolean
18+
default: true
19+
20+
jobs:
21+
test:
22+
runs-on:
23+
- self-hosted
24+
- linux
25+
- ${{ matrix.MPY_BOARD }}
26+
- notecard-serial
27+
- micropython
28+
defaults:
29+
run:
30+
shell: bash
31+
strategy:
32+
matrix:
33+
MICROPYTHON_VERSION: [1.20.0]
34+
MICROPYTHON_DATE: [20230426]
35+
MICROPYTHON_MCU: [esp32]
36+
MPY_BOARD: [huzzah32] # the --mpyboard parameter to the tests
37+
flash_device: # has to be an array - use the input from workflow_dispatch if present, otherwlse true
38+
- ${{ github.event.inputs.flash_device=='' && true || github.event.inputs.flash_device }}
39+
env:
40+
VENV: .venv-runner-mpy
41+
USB_MSD_ATTACH_TIME: 15
42+
MICROPYTHON_BIN: "${{matrix.MICROPYTHON_MCU}}-${{matrix.MICROPYTHON_DATE}}-v${{matrix.MICROPYTHON_VERSION}}.bin"
43+
MICROPYTHON_VERSION: ${{matrix.MICROPYTHON_VERSION}}
44+
steps:
45+
- name: Checkout Code
46+
uses: actions/checkout@v3
47+
48+
- name: Set Env Vars
49+
run: |
50+
# environment variables set in a step cannot be used until subsequent steps
51+
echo "MICROPYTHON_BIN_URL=https://micropython.org/resources/firmware/${{env.MICROPYTHON_BIN}}" >> $GITHUB_ENV
52+
53+
- name: Check Runner Config
54+
run: test/scripts/check_mpy_runner_config.sh
55+
56+
- name: Download MicroPython v${{ env.MICROPYTHON_VERSION }}
57+
if: ${{ matrix.flash_device }}
58+
run: |
59+
echo "Downloading MicroPython for ESP32 from $MICROPYTHON_BIN_URL"
60+
wget -q -N "$MICROPYTHON_BIN_URL"
61+
62+
- name: Setup Python
63+
run: |
64+
python3 -m venv ${{ env.VENV }}
65+
. ${{ env.VENV }}/bin/activate
66+
# esptool installed directly because it's only a dependency of this workflow
67+
# while requirements.txt are dependencies of the tests in test/hitl
68+
pip install -r test/hitl/requirements.txt esptool
69+
70+
- name: Erase device and Program Micropython
71+
if: ${{ matrix.flash_device }}
72+
run: |
73+
. ${{ env.VENV }}/bin/activate
74+
# esptool requires the flash to be erased first
75+
esptool.py --chip esp32 -p ${MPY_SERIAL} erase_flash
76+
timeout 10 bash test/scripts/wait_for_file.sh "$MPY_SERIAL"
77+
78+
esptool.py --chip esp32 --port ${MPY_SERIAL} --baud 460800 write_flash -z 0x1000 ${{ env.MICROPYTHON_BIN }}
79+
timeout 10 bash test/scripts/wait_for_file.sh "$MPY_SERIAL"
80+
81+
# wait for MicroPython to complete initial setup
82+
echo "help()" >> "$MPY_SERIAL"
83+
sleep 10
84+
85+
- name: Run MicroPython Tests
86+
run: |
87+
. ${{ env.VENV }}/bin/activate
88+
pytest "--productuid=$MPY_PRODUCT_UID" "--port=$MPY_SERIAL" --platform=micropython --mpyboard=${{ matrix.MPY_BOARD }} test/hitl

.github/workflows/python-ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ jobs:
7878
DD_SERVICE: note-python
7979
DD_ENV: ci
8080
run: |
81-
coverage run -m pytest --ddtrace --ddtrace-patch-all
81+
coverage run -m pytest --ddtrace --ddtrace-patch-all --ignore=test/hitl
8282
- name: Publish to Coveralls
8383
env:
8484
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.pre-commit-config.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# See https://pre-commit.com for more information
2+
# See https://pre-commit.com/hooks.html for more hooks
3+
repos:
4+
- repo: https://github.com/pre-commit/pre-commit-hooks
5+
rev: v4.4.0
6+
hooks:
7+
- id: trailing-whitespace
8+
- id: end-of-file-fixer
9+
- id: check-yaml
10+
- id: check-added-large-files
11+
12+
- repo: local
13+
hooks:
14+
- id: Formatting
15+
name: Formatting
16+
entry: make precommit
17+
language: python # This sets up a virtual environment
18+
additional_dependencies: [flake8, pydocstyle]

Makefile

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,46 @@
11
# define VENV_NAME to use a specific virtual environment. It defaults to `env`.
22
VENV_NAME?=env
3-
VENV_ACTIVATE=. $(VENV_NAME)/bin/activate
3+
VENV_ACTIVATE=$(VENV_NAME)/bin/activate
44
PYTHON=python
5-
VENV =
5+
# the target to activate the virtual environment. Only defined if it exists.
66

7-
# check if the VENV file exists
8-
ifneq ("$(wildcard $(PVENV_ACTIVATE))","")
9-
VENV = venv
10-
PYTHON = ${VENV_NAME}/bin/python3
7+
# check if the VENV file exists, if it does assume that's been made active
8+
ifneq ("$(wildcard ${VENV_ACTIVATE})","")
9+
RUN_VENV_ACTIVATE=. ${VENV_ACTIVATE}
10+
PYTHON = ${VENV_NAME}/bin/python3
1111
endif
1212

13-
default: docstyle flake8 test
13+
default: precommit
1414

15-
venv: $(VENV_NAME)/bin/activate
15+
precommit: docstyle flake8
1616

17-
test: $(VENV)
18-
${PYTHON} -m pytest test --cov=notecard
17+
test:
18+
${RUN_VENV_ACTIVATE}
19+
${PYTHON} -m pytest test --cov=notecard --ignore=test/hitl
1920

20-
docstyle: $(VENV)
21-
${PYTHON} -m pydocstyle notecard/ examples/
21+
docstyle:
22+
${RUN_VENV_ACTIVATE}
23+
${PYTHON} -m pydocstyle notecard/ examples/ mpy_board/
2224

23-
flake8: $(VENV)
24-
# E722 Do not use bare except, specify exception instead https://www.flake8rules.com/rules/E722.html
25-
# F401 Module imported but unused https://www.flake8rules.com/rules/F401.html
26-
# F403 'from module import *' used; unable to detect undefined names https://www.flake8rules.com/rules/F403.html
27-
# W503 Line break occurred before a binary operator https://www.flake8rules.com/rules/W503.html
28-
# E501 Line too long (>79 characters) https://www.flake8rules.com/rules/E501.html
29-
${PYTHON} -m flake8 test/ notecard/ examples/ --count --ignore=E722,F401,F403,W503,E501 --show-source --statistics
25+
flake8:
26+
${RUN_VENV_ACTIVATE}
27+
# E722 Do not use bare except, specify exception instead https://www.flake8rules.com/rules/E722.html
28+
# F401 Module imported but unused https://www.flake8rules.com/rules/F401.html
29+
# F403 'from module import *' used; unable to detect undefined names https://www.flake8rules.com/rules/F403.html
30+
# W503 Line break occurred before a binary operator https://www.flake8rules.com/rules/W503.html
31+
# E501 Line too long (>79 characters) https://www.flake8rules.com/rules/E501.html
32+
${PYTHON} -m flake8 test/ notecard/ examples/ mpy_board/ --count --ignore=E722,F401,F403,W503,E501 --show-source --statistics
3033

31-
coverage: $(VENV)
32-
${PYTHON} -m pytest test --doctest-modules --junitxml=junit/test-results.xml --cov=notecard --cov-report=xml --cov-report=html
34+
coverage:
35+
${RUN_VENV_ACTIVATE}
36+
${PYTHON} -m pytest test --ignore=test/hitl --doctest-modules --junitxml=junit/test-results.xml --cov=notecard --cov-report=xml --cov-report=html
3337

34-
run_build: $(VENV)
38+
run_build:
39+
${RUN_VENV_ACTIVATE}
3540
${PYTHON} -m setup sdist bdist_wheel
3641

37-
deploy: $(VENV)
42+
deploy:
43+
${RUN_VENV_ACTIVATE}
3844
${PYTHON} -m twine upload -r "pypi" --config-file .pypirc 'dist/*'
3945

40-
.PHONY: venv test coverage run_build deploy
46+
.PHONY: precommit venv test coverage run_build deploy

README.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,11 @@ The documentation for this library can be found
136136
The [examples](examples/) directory contains examples for using this
137137
library with:
138138

139-
- [Serial](examples/notecard-basics/serial-example.py)
140-
- [I2C](examples/notecard-basics/i2c-example.py)
141-
- [RaspberryPi](examples/notecard-basics/rpi-example.py)
142-
- [CircuitPython](examples/notecard-basics/cpy-example.py)
143-
- [MicroPython](examples/notecard-basics/mpy-example.py)
139+
- [Serial](examples/notecard-basics/serial_example.py)
140+
- [I2C](examples/notecard-basics/i2c_example.py)
141+
- [RaspberryPi](examples/notecard-basics/rpi_example.py)
142+
- [CircuitPython](examples/notecard-basics/cpy_example.py)
143+
- [MicroPython](examples/notecard-basics/mpy_example.py)
144144

145145
## Contributing
146146

@@ -170,6 +170,21 @@ Alternatively, you can inspect the contents of the [Makefile](Makefile) and run
170170
`Makefile` run against every pull request, so your best bet is to ensure these
171171
tests are successful before submitting your PR.
172172

173+
## Installing the `pre-commit` Hook
174+
175+
Please run
176+
177+
`pre-commit install`
178+
179+
Before committing to this repo. It will catch a lot of common errors that you can fix locally.
180+
181+
You may also run the pre-commit checks before committing with
182+
183+
`pre-commit run`
184+
185+
Note that `pre-commit run` only considers staged changes, so be sure all
186+
changes are staged before running this.
187+
173188
## More Information
174189

175190
For additional Notecard SDKs and Libraries, see:

examples/notecard-basics/board.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""
2+
Define peripherals for different types of boards.
3+
4+
This module, or it's variants are used by the mpy_example to use the appropriate
5+
UART or I2C configuration for the particular board being used.
6+
The values here are defaults. The definitions for real boards are located in ./mpy_board/*
7+
at the root of the repo.
8+
"""
9+
10+
11+
"""
12+
The UART instance to use that is connected to Notecard.
13+
"""
14+
UART = 2
15+
16+
"""
17+
The I2C ID and SDL and SDA pins of the I2C bus connected to Notecard
18+
"""
19+
I2C_ID = 0
20+
SCL = 0
21+
SDA = 0

0 commit comments

Comments
 (0)