Skip to content

feat: add support for Heltec WiFi LoRa 32 V3 with 8MB flash size over… #161

feat: add support for Heltec WiFi LoRa 32 V3 with 8MB flash size over…

feat: add support for Heltec WiFi LoRa 32 V3 with 8MB flash size over… #161

Workflow file for this run

name: CI
on:
push:
branches: [main, "feat/**", "fix/**", "p3/**"]
pull_request:
branches: [main]
env:
CARGO_TERM_COLOR: always
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
firmware-matrix:
name: Firmware matrix
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v6
- id: matrix
name: Load firmware matrix
run: |
MATRIX=$(python3 -c "import json,pathlib; print(json.dumps(json.loads(pathlib.Path('.github/firmware-matrix.json').read_text())))")
echo "matrix=$MATRIX" >> "$GITHUB_OUTPUT"
# ─── Rust: format, lint, test, FFI build ────────────────────────────────────
rust:
name: Rust checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Cache cargo registry
uses: actions/cache@v5
with:
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-
- name: Check formatting
run: cargo fmt --all -- --check
- name: Clippy (deny warnings)
run: cargo clippy --all-targets -- -D warnings
- name: Run tests
run: cargo test --all
# Validate that the FFI feature compiles (exercises the C-ABI surface)
- name: Build FFI feature
run: cargo build -p rivr_core --features ffi
# ─── C: acceptance + radio-recovery + replay + dutycycle tests ──────────────
c-tests:
name: C tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install build tools
run: sudo apt-get install -y gcc make
- name: Build and run all C test suites
run: make -C tests
- name: Build + run policy-engine tests (P2)
run: |
gcc -O2 -Ifirmware_core -DIRAM_ATTR="" \
firmware_core/policy.c \
tests/test_policy.c \
-o /tmp/test_policy && /tmp/test_policy
- name: Build + run OTA gate tests – signed (P2)
run: |
gcc -O2 -Ifirmware_core -DIRAM_ATTR="" -DRIVR_SIGNED_PROG -DRIVR_PUBKEY_PRODUCTION=1 \
firmware_core/ed25519_verify.c \
firmware_core/rivr_ota_core.c \
tests/test_ota.c \
-o /tmp/test_ota && timeout 60 /tmp/test_ota
- name: Build + run OTA gate tests – unsigned (P2)
run: |
gcc -O2 -Ifirmware_core -DIRAM_ATTR="" \
firmware_core/ed25519_verify.c \
firmware_core/rivr_ota_core.c \
tests/test_ota.c \
-o /tmp/test_ota_unsigned && /tmp/test_ota_unsigned
# ── ASan + UBSan (P3.2) ──────────────────────────────────────────────────
asan-tests:
name: ASan + UBSan C tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install GCC
run: sudo apt-get install -y gcc make
- name: Build + run core suites under ASan/UBSan
working-directory: tests
run: make asan
- name: Build + run policy under ASan/UBSan
run: |
gcc -O1 -g -fsanitize=address,undefined \
-Ifirmware_core -DIRAM_ATTR="" \
firmware_core/policy.c \
tests/test_policy.c \
-o /tmp/test_policy_asan && /tmp/test_policy_asan
- name: Build + run OTA under ASan/UBSan (signed)
run: |
gcc -O1 -g -fsanitize=address,undefined \
-Ifirmware_core -DIRAM_ATTR="" -DRIVR_SIGNED_PROG -DRIVR_PUBKEY_PRODUCTION=1 \
firmware_core/ed25519_verify.c \
firmware_core/rivr_ota_core.c \
tests/test_ota.c \
-o /tmp/test_ota_asan && timeout 60 /tmp/test_ota_asan
# ── Size regression (P3.1) ───────────────────────────────────────────────
size-check:
name: Size regression (+5% host binaries)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install GCC + make
run: sudo apt-get install -y gcc make
- name: Build host test binaries
working-directory: tests
run: make all
- name: Size regression check
run: bash tests/ci_size_check.sh tests/baselines/host_sizes.txt 5
# ── Determinism (P3.1) ───────────────────────────────────────────────────
determinism:
name: Replay determinism hash
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install GCC + make
run: sudo apt-get install -y gcc make
- name: Build replay test
working-directory: tests
run: make replay
- name: Compare against golden snapshot
run: bash tests/ci_determinism_check.sh tests/golden/replay_sha256.txt
# ── Firmware variants on GitHub-hosted runners ───────────────────────────
firmware:
name: Firmware ${{ matrix.pio_env }}
runs-on: ubuntu-latest
needs: firmware-matrix
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.firmware-matrix.outputs.matrix) }}
steps:
- uses: actions/checkout@v6
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Restore firmware build cache
uses: actions/cache@v5
with:
path: |
~/.cache/pip
~/.platformio
key: firmware-${{ matrix.pio_env }}-${{ runner.os }}-${{ hashFiles('.github/firmware-matrix.json', 'platformio.ini', 'variants/**/*.ini', 'Cargo.lock', 'firmware_core/CMakeLists.txt', 'sdkconfig/**', 'sdkconfig*') }}
restore-keys: |
firmware-${{ matrix.pio_env }}-${{ runner.os }}-
firmware-${{ runner.os }}-
- name: Install PlatformIO and esptool
run: |
pip install --upgrade pip
pip install platformio esptool
- name: Install Espressif Rust toolchain via espup
if: ${{ startsWith(matrix.rust_target, 'xtensa-') }}
run: |
cargo install espup --locked
espup install
source "$HOME/export-esp.sh"
[ -n "$LIBCLANG_PATH" ] && echo "LIBCLANG_PATH=$LIBCLANG_PATH" >> "$GITHUB_ENV"
[ -n "$CLANG_PATH" ] && echo "CLANG_PATH=$CLANG_PATH" >> "$GITHUB_ENV"
ESP_TOOLCHAIN=$(rustup toolchain list | awk '/^esp/ {print $1; exit}')
echo "RUSTUP_TOOLCHAIN=$ESP_TOOLCHAIN" >> "$GITHUB_ENV"
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
shell: bash
- name: Install ARM Rust target (nRF52 / RP2040)
if: ${{ matrix.rust_target == 'thumbv7em-none-eabihf' || matrix.rust_target == 'thumbv6m-none-eabi' }}
run: rustup target add ${{ matrix.rust_target }}
- name: Build Rust rivr_core (${{ matrix.rust_target }})
run: |
if [[ "${{ matrix.rust_target }}" == thumbv* ]]; then
cargo +stable build -p rivr_core \
--target ${{ matrix.rust_target }} \
--no-default-features \
--features ffi \
--release
else
source "$HOME/export-esp.sh"
cargo build -p rivr_core \
--target ${{ matrix.rust_target }} \
--no-default-features \
--features ffi \
--release \
-Zbuild-std=core,alloc,panic_abort
fi
shell: bash
- name: Build firmware (${{ matrix.pio_env }})
run: |
pio run -e ${{ matrix.pio_env }}