feat: improve static random address generation for BLE on ESP32 variants #53
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ╔══════════════════════════════════════════════════════════════════════════╗ | |
| # ║ Rivr – Firmware Release Pipeline ║ | |
| # ║ ║ | |
| # ║ Triggered by: git tag push matching v* (e.g. v1.2.0) ║ | |
| # ║ ║ | |
| # ║ Pipeline overview: ║ | |
| # ║ 1. Build all firmware variants in parallel (matrix) ║ | |
| # ║ 2. Each job caches pip and PlatformIO layers ║ | |
| # ║ 3. Rust rivr_core is cross-compiled for the matching Xtensa target ║ | |
| # ║ 4. scripts/package_firmware.py assembles a user-ready ZIP per variant ║ | |
| # ║ containing: binaries, exact flash-layout JSON, merged image, ║ | |
| # ║ flash scripts, README ║ | |
| # ║ 5. A follow-up job collects all ZIPs and publishes the GitHub Release ║ | |
| # ╚══════════════════════════════════════════════════════════════════════════╝ | |
| name: Release | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| # All jobs need write permission to create the GitHub Release and attach assets. | |
| permissions: | |
| contents: write | |
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: true | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Build matrix – loaded from versioned repo metadata | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| jobs: | |
| firmware-matrix: | |
| name: Firmware matrix | |
| runs-on: ubuntu-latest | |
| outputs: | |
| matrix: ${{ steps.matrix.outputs.matrix }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - 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" | |
| build: | |
| name: Build ${{ matrix.artifact }} | |
| runs-on: ubuntu-latest | |
| needs: firmware-matrix | |
| strategy: | |
| fail-fast: false # keep other variants building if one fails | |
| matrix: ${{ fromJSON(needs.firmware-matrix.outputs.matrix) }} | |
| steps: | |
| # ── 1. Checkout ────────────────────────────────────────────────────── | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Install Rust stable | |
| uses: dtolnay/rust-toolchain@stable | |
| # ── 2. Python (required by PlatformIO, ESP-IDF, esptool) ───────────── | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| # ── 3. Install PlatformIO + esptool ─────────────────────────────────── | |
| # | |
| # esptool is installed here so it is available to both: | |
| # - The ESP-IDF build system (called internally by PlatformIO) | |
| # - scripts/package_firmware.py (for merge_bin) | |
| - name: Install PlatformIO and esptool | |
| run: | | |
| pip install --upgrade pip | |
| pip install platformio esptool | |
| # ── 4. Install Espressif Rust toolchain (Xtensa) or ARM target ────── | |
| - name: Install Espressif Rust toolchain via espup | |
| if: ${{ matrix.rust_target != 'thumbv7em-none-eabihf' }} | |
| 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" | |
| # Discover toolchain name (e.g. "esp" or "esp-1.84.0.0") from rustup | |
| ESP_TOOLCHAIN=$(rustup toolchain list | grep -E '^esp' | awk '{print $1}' | head -n1) | |
| echo "Activating Xtensa toolchain: $ESP_TOOLCHAIN" | |
| echo "RUSTUP_TOOLCHAIN=$ESP_TOOLCHAIN" >> "$GITHUB_ENV" | |
| echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" | |
| shell: bash | |
| - name: Install ARM Rust target for nRF52 | |
| if: ${{ matrix.rust_target == 'thumbv7em-none-eabihf' }} | |
| run: rustup target add thumbv7em-none-eabihf | |
| # ── 5. Restore build cache ──────────────────────────────────────────── | |
| # | |
| # Key includes the PIO env name so cache from one variant is not | |
| # accidentally reused by a different variant (different toolchain flags). | |
| - name: Restore 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 }}- | |
| # ── 6. Build Rust rivr_core for the matching target ────────────────── | |
| - name: Build Rust rivr_core (${{ matrix.rust_target }}) | |
| run: | | |
| if [[ "${{ matrix.rust_target }}" == "thumbv7em-none-eabihf" ]]; 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 | |
| # ── 7. Build firmware with PlatformIO ──────────────────────────────── | |
| - name: Build firmware (${{ matrix.pio_env }}) | |
| run: pio run -e ${{ matrix.pio_env }} | |
| # ── 8. Package firmware ZIP ─────────────────────────────────────────── | |
| # | |
| # scripts/package_firmware.py: | |
| # - Copies bootloader.bin, partitions.bin, firmware.bin (→ rivr_<variant>.bin) | |
| # - Writes rivr_<variant>.json with exact flash settings + offsets | |
| # - Generates rivr_<variant>_full.bin via esptool merge_bin | |
| # - Writes flash.sh (Linux/macOS) and flash.bat (Windows) | |
| # - Writes README.txt with flashing instructions | |
| # - Creates rivr_<variant>.zip containing the above | |
| - name: Package firmware ZIP (${{ matrix.artifact }}) | |
| run: | | |
| python scripts/package_firmware.py \ | |
| ${{ matrix.pio_env }} \ | |
| ${{ matrix.artifact }} | |
| # ── 9. Upload per-variant ZIP artifact ─────────────────────────────── | |
| # | |
| # Each matrix job uploads its own ZIP; the release job below downloads | |
| # all of them and attaches them to the GitHub Release. | |
| - name: Upload firmware ZIP artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: rivr_${{ matrix.artifact }} | |
| path: rivr_${{ matrix.artifact }}.zip | |
| if-no-files-found: error | |
| retention-days: 7 | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| # Release job – runs after all build matrix jobs succeed | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| release: | |
| name: Publish GitHub Release | |
| runs-on: ubuntu-latest | |
| needs: build # wait for all matrix builds to finish | |
| steps: | |
| # ── 10. Checkout (needed for bundle script + bundles JSON) ──────────── | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| # ── 11. Download all firmware ZIPs ──────────────────────────────────── | |
| # | |
| # pattern: "rivr_*" matches every artifact uploaded by the build matrix. | |
| # merge-multiple: true flattens them into the zips/ directory. | |
| - name: Download all firmware ZIPs | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: rivr_* | |
| path: zips | |
| merge-multiple: true | |
| - name: List collected ZIPs | |
| run: ls -lh zips/ | |
| # ── 12. Assemble per-board bundle ZIPs ──────────────────────────────── | |
| # | |
| # scripts/bundle_firmware.py reads .github/firmware-bundles.json and | |
| # combines client / client_ble / repeater per-variant ZIPs into a single | |
| # board-level bundle ZIP (rivr_<board>_bundle.zip). | |
| # These are the files linked from the download page. | |
| - name: Create board bundle ZIPs | |
| run: | | |
| python3 scripts/bundle_firmware.py \ | |
| zips \ | |
| .github/firmware-bundles.json \ | |
| zips | |
| - name: List all ZIPs (variants + bundles) | |
| run: ls -lh zips/ | |
| # ── 13. Create GitHub Release and attach ZIPs ───────────────────────── | |
| # | |
| # softprops/action-gh-release creates the release from the pushed tag and | |
| # attaches every .zip file found in zips/ — both per-variant and bundles. | |
| # Release notes are auto-generated from git log between tags. | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: "Rivr ${{ github.ref_name }}" | |
| draft: false | |
| prerelease: ${{ contains(github.ref_name, '-rc') || contains(github.ref_name, '-beta') || contains(github.ref_name, '-alpha') }} | |
| generate_release_notes: true | |
| files: zips/*.zip | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |