name: Run Unit Tests on: push: branches: - main - master - keymindCascade pull_request: workflow_dispatch: jobs: management-reports: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v6 with: python-version: '3.13' - name: Install real crypto implementations for cross-language tests run: | python3 -m pip install platformio pycryptodome==3.23.0 mkdir -p .pio/libdeps/management-test pio pkg install --global --library 'rweather/Crypto@0.4.0' --storage-dir .pio/libdeps/management-test - name: Verify protocol, encryption, scheduling and MQTT decoding run: | python3 -B test/test_management_report.py -v node test/test_management_decoder.js stm32-companion-smoke: runs-on: ubuntu-latest steps: - name: Clone Repo uses: actions/checkout@v4 - name: Setup Build Environment uses: ./.github/actions/setup-build-environment - name: Compile ordinary STM32 USB Companion with pinned core and RadioLib run: pio run -e RAK_3x72_companion_radio_usb bootloader-version: runs-on: ubuntu-latest steps: - name: Clone Repo uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v6 with: python-version: '3.13' - name: Verify bootloader version regressions without hardware or downloads run: python3 -B test/test_nrf52_bootloader_version.py -v - name: Install signed-package verification dependency run: python3 -m pip install cryptography - name: Verify old-firmware compatibility in both OTA launchers run: python3 -B -m unittest discover -s tools/lora_ota -p test_lora_ota_bootloader_version.py -v - name: Verify OTA orchestration and automatic relay policy cleanup run: python3 -B -m unittest discover -s tools/lora_ota -p 'test_lora_ota*.py' -v - name: Verify all signed OTAFIX 2.4.6 release images env: MESHCORE_BOOTLOADER_MOTA_ZIP: ${{ runner.temp }}/OTAFIX-2.4.6-bootloader-mota.zip # The test pins the archive SHA-256, verifies every .mota signature, # and checks the exact MeshTower V2 SD CRC from the bug report. run: | curl --fail --location --retry 3 --max-time 120 --output "$MESHCORE_BOOTLOADER_MOTA_ZIP" \ https://github.com/mikecarper/Adafruit_nRF52_Bootloader_OTAFIX/releases/download/0.11.0-OTAFIX2.4.6/OTAFIX-2.4.6-bootloader-mota.zip python3 -B test/test_nrf52_bootloader_version.py -v test: runs-on: ubuntu-latest steps: - name: Clone Repo uses: actions/checkout@v4 - name: Setup Build Environment uses: ./.github/actions/setup-build-environment - name: Verify ArduinoJson pin run: | python3 -B scripts/check_arduinojson_pin.py --self-test python3 -B scripts/check_arduinojson_pin.py - name: Run Unit Tests run: pio test -e native -e native_kiss_modem -vv - name: Verify filter playground modes and built-in defaults run: node scripts/test_filter_tool.js - name: Verify bridge filter wiring and shorthand permissions run: python3 -B test/test_transport_filter_wiring.py -v - name: Verify Companion contact and channel TX routing run: | sudo apt-get update sudo apt-get install -y libssl-dev python3 -B test/test_companion_tx_routing.py -v python3 -B test/test_companion_discovery.py -v python3 -B test/test_pico_ble_queues.py -v python3 -B test/test_companion_preferences_transaction.py -v python3 -B test/test_companion_radio_settings_transaction.py -v python3 -B test/test_companion_prefs_transactions.py -v python3 -B test/test_companion_primary_radio_persistence.py -v python3 -B test/test_companion_response_bounds.py -v python3 -B test/test_companion_uncached_storage.py -v python3 -B test/test_companion_ota_config.py -v python3 -B test/test_ota_identity_policy.py -v python3 -B test/test_companion_radio_gain_restore.py -v python3 -B test/test_common_radio_persistence.py -v python3 -B test/test_common_cli_save_results.py -v python3 -B test/test_common_prefs_commit.py -v python3 -B test/test_mqtt_prefs_commit.py -v python3 -B test/test_identity_and_settings_recovery.py -v python3 -B test/test_contact_cache.py -v - name: Verify receive recovery and pinned radio status transport run: | python3 -B test/test_radio_receive_contract.py python3 - <<'PY' from pathlib import Path import re import subprocess dependency = re.search(r'https://github.com/jgromes/RadioLib.git#[0-9a-f]{40}', Path('platformio.ini').read_text()).group(0) Path('.pio/libdeps/radio-status-test').mkdir(parents=True, exist_ok=True) subprocess.run(['pio', 'pkg', 'install', '--global', '--library', dependency, '--storage-dir', '.pio/libdeps/radio-status-test'], check=True) PY python3 -B test/test_sx126x_receive_mode.py - name: Verify temporary-radio timing and exact reply delivery run: | python3 -B test/test_carrier_wave.py python3 -B test/test_radio_profile_cli.py python3 -B test/test_radio_reply_mutation.py python3 -B test/test_radio_profile_scan.py python3 -B test/test_repeater_radio_timing_integration.py python3 -B test/test_temp_radio_reply_delivery_contract.py python3 -B test/test_reply_tx_integration.py python3 -B test/test_ota_speed.py -v python3 -B test/test_ota_apply_delivery.py -v python3 -B test/test_ota_install_preflight.py -v python3 -B test/test_ota_store_resume.py -v python3 -B test/test_ota_catalog_lifetime.py -v python3 -B test/test_ota_store_flash_nrf52_hybrid.py -v python3 -B test/test_ota_dev_staging.py -v python3 -B test/test_ota_dev_reboot_guard.py -v - name: Verify dual-profile switching and chirp timing working-directory: test run: >- python3 -B -m unittest -v test_sx1262_profile_switch test_sx1262_batched_modulation test_radio_chirp_math - name: Verify radio lab collectors and compiled experiment contracts run: | python3 -B -m unittest discover -s test -p 'test_profile_*.py' -v python3 -B -m unittest discover -s tools/hil -p 'test_*.py' -v - name: Verify ESP32 static DRAM budget run: | python3 -B test/test_esp32_dram.py python3 -B test/test_elrs_power.py python3 -B test/test_ota_heap_context.py python3 -B test/test_client_acl_spiffs.py python3 -B test/test_client_acl_cli.py -v - name: Verify ESP32 USB sleep and G3 button wake run: python3 -B test/test_esp32_usb_sleep.py - name: Verify GPS status distinguishes user settings from receiver sleep run: python3 -B test/test_gps_status.py - name: Verify Companion ASCII defaults and USB session cleanup run: | python3 -B test/test_companion_usb_default.py python3 -B test/test_nrf52_usb_client.py python3 -B test/test_esp32_usb_serial_hygiene.py python3 -B test/test_stm32_float_conversion.py - name: Verify Companion contact persistence and OTA sleep guards run: python3 -B test/test_companion_contact_sleep_contract.py -v - name: Verify Companion Bluetooth CLI connection protection run: python3 -B test/test_companion_bluetooth_control.py -v - name: Verify nRF52 SoftDevice LTO and persistent BLE subscriptions env: MESHCORE_REQUIRE_ARM_COMPILER: '1' MESHCORE_REQUIRE_DFU_EMULATOR: '1' run: | pio pkg install --global --tool 'platformio/toolchain-gccarmnoneeabi@1.140201.0' python3 -B test/test_nrf52_svc_compat.py -v python3 -B test/test_nrf52_ble_cccd_fix.py -v pip install unicorn==2.1.4 python3 -B test/test_nrf52_ble_dfu_fix.py -v - name: Verify WiFi, ESP-NOW and combined wireless controls run: | python3 -B test/test_wireless_control.py -v python3 -B test/test_serial_wifi_sessions.py -v python3 -B test/test_serial_ethernet_sessions.py -v python3 -B test/test_companion_wifi_session.py -v python3 -B test/test_espnow_radio_lifecycle.py -v - name: Verify message reader buttons, touch targets, and footer layouts working-directory: test run: >- python3 -B -m unittest test_message_navigation test_companion_reader test_reader_touch_coordinates test_touch_debug_overlay test_touch_debug_cli test_color_theme test_indicator_messages_profile test_t096_message_footer_profile test_indicator_display_profile test_indicator_render_profile test_indicator_exclusive_transport test_companion_transport_selector - name: Verify logging sleep guards and instructions run: | python3 -B test/test_logging_sleep_contract.py python3 -B test/test_picker_controls_generator.py node test/test_firmware_picker.js - name: Verify Full logging compiler flags and packaged capabilities run: | python3 -B test/test_full_build_flag_dedup.py python3 -B test/test_full_logging_compile.py python3 -B test/test_full_logging_resume.py python3 -B test/test_firmware_capabilities.py bash test/test_build_profiles.sh bash test/test_xiao_qspi_combined.sh - name: Verify nRF52 UF2-reset CLI coverage run: python3 -B test/test_nrf52_uf2reset_cli.py - name: Verify CLI setting dispatch and get-set coverage run: | python3 -B test/test_path_hash_cli.py python3 -B test/test_cli_settings_contract.py python3 -B test/test_local_cli_access.py python3 -B test/test_remote_cli_command_identity.py -v python3 -B test/test_replay_reset_integration.py -v - name: Verify firmware memory budgets and nRF52 Bluetooth startup run: | bash test/test_build_size_detection.sh python3 -B test/test_firmware_ram.py python3 -B test/test_neighbor_scope_storage.py python3 -B test/test_ed25519_compact.py python3 -B test/test_cascade_release_package.py python3 -B test/test_t096_full_memory.py python3 -B test/test_nrf52_ble_startup.py python3 -B test/test_nrf52_ble_trace.py python3 -B test/test_nrf52_ble_debug_tools.py python3 -B test/test_nrf52_usb_power.py python3 -B test/test_shared_mota_queue.py - name: Verify Companion Bluetooth settings and WebConfig run: | node test/test_notification_builder.js python3 -B test/test_notification_settings.py python3 -B test/test_display_power.py python3 -B test/test_companion_inbox.py python3 -B test/test_heltec_r8_external_power.py python3 -B test/test_bluetooth_mac_contract.py python3 -B test/test_companion_settings_persistence_contract.py python3 -B test/test_webconfig_ui.py python3 -B test/test_webconfig_gzip.py python3 -B test/test_webconfig_secret_masking.py python3 -B test/test_webconfig_ui_runtime.py - name: Upload Test Results # Upload test results even if the test step failed. if: always() uses: actions/upload-artifact@v4 with: name: test-results path: .pio/build/native/