ci: disable ble ota delta testing, add v2 and local testing support
What changed, and why it matters
This commit only changes internal continuous-integration (CI) scripts that run automated hardware-in-the-loop tests for Blockstream Jade firmware updates. It disables Bluetooth OTA delta testing when the required Bluetooth tool is missing, adds support for the newer Jade v2 hardware, and lets developers run the same scripts locally. There is no change to the firmware, wallet logic, cryptography, or any code that end users run, so this commit does not create or fix a security vulnerability.
No security action required. Treat as a normal CI/maintenance commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff modifies .gitlab/flash.yml and ota_delta_ci.sh. It removes commented-out flock-based serial-port locking, passes an explicit target chip (esp32/esp32s3) and –skipble to ota_delta_ci.sh, adds v2 CI jobs, and makes the shell script fall back to /dev/ttyACM0 and a local Python virtualenv when the CI environment is not present. The script now skips BLE OTA if /usr/bin/bt-agent is unavailable and adjusts jade_ota.py arguments accordingly. These are build/test infrastructure changes only; no runtime firmware or cryptographic code is touched.
Changed components
gitlab/flash.ymlota_delta_ci.shInspect captured patch +69 / −22
diff --git a/gitlab/flash.yml b/gitlab/flash.yml
index eb93672..c48da3c 100644
--- a/gitlab/flash.yml
+++ b/gitlab/flash.yml
@@ -40,8 +40,6 @@ flash_qemu_psram_unamalgamated:
- mv $(echo $CI_JOB_NAME | sed "s/^${CI_JOB_STAGE}/build_test/") build
- cp -a build/sdkconfig ./
- ./ci_flash.sh esp32 --skipble
- # FIXME: re-enable once gitlab is known to properly kill processes
- #- ./tools/flock.sh $JADESERIALPORT ./ci_flash.sh esp32 --skipble
# FIXME: Remove gcov from ./ci_flash.sh and then skip submodules here
# FIXME: Fix v1.0 flashing
allow_failure: true
@@ -70,9 +68,7 @@ flash_jade_ota_delta_ci:
script:
- mv build_test_jade_ci build
- mv build_test_jade_noradio_ci build_noradio
- - ./ota_delta_ci.sh
- # FIXME: re-enable once gitlab is known to properly kill processes
- #- ./tools/flock.sh $JADESERIALPORT ./ota_delta_ci.sh
+ - ./ota_delta_ci.sh esp32 --skipble
# Jade v1.1
.flash_jade_v1_1_template:
@@ -104,9 +100,7 @@ flash_jade_ota_delta_v1_1_ci:
script:
- mv build_test_jade_v1_1_ci build
- mv build_test_jade_v1_1_noradio_ci build_noradio
- - ./ota_delta_ci.sh
- # FIXME: re-enable once gitlab is known to properly kill processes
- #- ./tools/flock.sh $JADESERIALPORT ./ota_delta_ci.sh
+ - ./ota_delta_ci.sh esp32 --skipble
# Jade v2.0
.flash_jade_v2_template:
@@ -119,11 +113,29 @@ flash_jade_ota_delta_v1_1_ci:
- mv $(echo $CI_JOB_NAME | sed "s/^${CI_JOB_STAGE}/build_test/") build
- cp build/sdkconfig ./
- ./ci_flash.sh esp32s3 --skipble
- # FIXME: re-enable once gitlab is known to properly kill processes
- #- ./tools/flock.sh $JADESERIALPORT ./ci_flash.sh esp32s3 --skipble
flash_jade_v2_ci:
extends: .flash_jade_v2_template
needs: [ test_libjade, build_test_jade_v2_ci ]
-# FIXME: add noradio and delta flashing for v2.0
+flash_jade_v2_noradio_ci:
+ extends: .flash_jade_v2_template
+ needs:
+ - job: build_test_jade_v2_noradio_ci
+ artifacts: true
+ - job: flash_jade_v2_ci
+ artifacts: false
+
+flash_jade_ota_delta_v2_ci:
+ extends: .flash_jade_v2_template
+ needs:
+ - job: build_test_jade_v2_ci
+ artifacts: true
+ - job: build_test_jade_v2_noradio_ci
+ artifacts: true
+ - job: flash_jade_v2_noradio_ci
+ artifacts: false
+ script:
+ - mv build_test_jade_v2_ci build
+ - mv build_test_jade_v2_noradio_ci build_noradio
+ - ./ota_delta_ci.sh esp32s3 --skipble
diff --git a/ota_delta_ci.sh b/ota_delta_ci.sh
index 93e580f..5e2c7c9 100755
--- a/ota_delta_ci.sh
+++ b/ota_delta_ci.sh
@@ -5,22 +5,58 @@ if [[ -z ${JADESERIALPORT} ]]; then
echo "Serial port \"${JADESERIALPORT}\" isn't valid, using defaults"
if [ "$(uname)" == "Darwin" ]; then
JADESERIALPORT=/dev/cu.SLAB_USBtoUART
- else
+ elif [ -c /dev/ttyUSB0 ]; then
JADESERIALPORT=/dev/ttyUSB0
+ else
+ JADESERIALPORT=/dev/ttyACM0
fi
echo "Serial port set to default \"${JADESERIALPORT}\""
fi
-# first we reset the device
-python ${IDF_PATH}/components/esptool_py/esptool/esptool.py --chip esp32 --port ${JADESERIALPORT} --baud 2000000 --before default_reset erase_flash
+TARGET_CHIP=${1:-esp32}
+BUILD_DIR=build
+SKIP_ARGS=$2
+
+# Reset the device and then flash the ble-enabled variant
+if [ "$TARGET_CHIP" = "esp32" ]; then
+ python ${IDF_PATH}/components/esptool_py/esptool/esptool.py --chip ${TARGET_CHIP} --port ${JADESERIALPORT} --baud 2000000 --before default_reset erase_flash
+ python ${IDF_PATH}/components/esptool_py/esptool/esptool.py --chip ${TARGET_CHIP} --port ${JADESERIALPORT} --baud 2000000 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0xE000 ${BUILD_DIR}/ota_data_initial.bin 0x1000 ${BUILD_DIR}/bootloader/bootloader.bin 0x10000 ${BUILD_DIR}/jade.bin 0x9000 ${BUILD_DIR}/partition_table/partition-table.bin
+else
+ python ${IDF_PATH}/components/esptool_py/esptool/esptool.py --chip ${TARGET_CHIP} --port ${JADESERIALPORT} --baud 460800 --before default_reset erase_flash
+ python ${IDF_PATH}/components/esptool_py/esptool/esptool.py --chip ${TARGET_CHIP} --port ${JADESERIALPORT} --baud 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 80m --flash_size 8MB 0x0 ${BUILD_DIR}/bootloader/bootloader.bin 0x20000 ${BUILD_DIR}/jade.bin 0x8000 ${BUILD_DIR}/partition_table/partition-table.bin 0x1a000 ${BUILD_DIR}/ota_data_initial.bin
+fi
-# then we flash the ble-enabled variant
-python ${IDF_PATH}/components/esptool_py/esptool/esptool.py --chip esp32 --port ${JADESERIALPORT} --baud 2000000 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0xE000 build/ota_data_initial.bin 0x1000 build/bootloader/bootloader.bin 0x10000 build/jade.bin 0x9000 build/partition_table/partition-table.bin
+sleep 1
# Setup the python environment
-source ~/venv3/bin/activate
+if [ -r ~/venv3/bin/activate ]; then
+ # Assume we are running under the CI: pinserver requirements are already installed
+ source ~/venv3/bin/activate
+else
+ # Install and activate a local venv
+ if [ ! -r ./venv3/bin/activate ]; then
+ virtualenv -p python3 venv3
+ fi
+ source ./venv3/bin/activate
+ pip install -r pinserver/requirements.txt
+fi
pip install --require-hashes -r requirements.txt
+# NOTE: tools/fwprep.py should have run in the build step and produced the compressed firmware file
+if [ ! -x /usr/bin/bt-agent ]; then
+ echo "bt-agent not available, skipping bluetooth OTA"
+ SKIP_ARGS="--skipble"
+fi
+
+SKIP_SERIAL="--skipserial"
+if [ "$SKIP_ARGS" = "--skipble" ]; then
+ # Don't skip serial, and instead skip ble
+ SKIP_SERIAL=""
+else
+ # Get the BLE ID from serial as this is faster
+ SKIP_ARGS="--bleidfromserial"
+fi
+
# Build the bsdiff tool in the 'tools' directory (source file in the build dir)
gcc -O2 -DBSDIFF_EXECUTABLE -o ./tools/bsdiff build/bsdiff.c
@@ -37,11 +73,11 @@ mkdir -p ${PATCHDIR}
./tools/mkpatch.py ${FW_NORADIO} ${FW_BLE} ${PATCHDIR} --force # makes both directions
sleep 2
-# first we ota to noradio via ble
+# first we ota to noradio via ble (or serial if skipping ble)
# NOTE: the filename is of the pattern: 'final-from-base' - hence noradio*ble*patch.bin
FW_PATCH=$(ls ${PATCHDIR}/*_noradio_*_ble*_patch.bin)
cp "${FW_NORADIO}.hash" "${FW_PATCH}.hash"
-python jade_ota.py --log=INFO --skipserial --bleidfromserial --serialport=${JADESERIALPORT} --fwfile=${FW_PATCH}
+python jade_ota.py --log=INFO ${SKIP_SERIAL} ${SKIP_ARGS} --serialport=${JADESERIALPORT} --fwfile=${FW_PATCH}
# then we test the same exact firmware via serial
FW_PATCH=$(ls ${PATCHDIR}/*_noradio_*_noradio*_patch.bin)
@@ -55,8 +91,7 @@ cp "${FW_BLE}.hash" "${FW_PATCH}.hash"
python jade_ota.py --log=INFO --skipble --serialport=${JADESERIALPORT} --fwfile=${FW_PATCH}
sleep 2
-# finally we test the same exact firmware via ble
+# finally we test the same exact firmware via ble (or serial if skipping ble)
FW_PATCH=$(ls ${PATCHDIR}/*_ble_*_ble*_patch.bin)
-python jade_ota.py --log=INFO --skipserial --bleidfromserial --serialport=${JADESERIALPORT} --fwfile=${FW_PATCH}
+python jade_ota.py --log=INFO ${SKIP_SERIAL} ${SKIP_ARGS} --serialport=${JADESERIALPORT} --fwfile=${FW_PATCH}
sleep 2
-
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.