name: Build and (Nightly) Pre-release on: workflow_dispatch: schedule: # daily at 03:00 UTC (adjust to your preferred time) - cron: '0 3 * * *' jobs: decide: name: Detect new commits on default branch runs-on: ubuntu-latest outputs: should_build: ${{ steps.decide.outputs.should_build }} default_branch: ${{ steps.decide.outputs.default_branch }} head_sha: ${{ steps.decide.outputs.head_sha }} short_sha: ${{ steps.decide.outputs.short_sha }} steps: - uses: actions/checkout@v4 with: { fetch-depth: 0 } - id: decide uses: actions/github-script@v7 with: script: | const owner = context.repo.owner; const repo = context.repo.repo; // Find default branch and its HEAD const repoInfo = await github.rest.repos.get({ owner, repo }); const defaultBranch = repoInfo.data.default_branch; const head = await github.rest.repos.getBranch({ owner, repo, branch: defaultBranch }); const headSha = head.data.commit.sha; const shortSha = headSha.slice(0,7); // Try get the existing nightly release (single static tag) let nightlyRelease = null; try { nightlyRelease = await github.rest.repos.getReleaseByTag({ owner, repo, tag: 'nightly' }); } catch (e) { if (e.status !== 404) throw e; } // Decide if we need to rebuild: compare short SHA in the release name // Name format we set: "_nightly" let shouldBuild = true; if (nightlyRelease) { const name = nightlyRelease.data.name || ''; const m = name.match(/^([0-9a-f]{7})_nightly$/i); if (m && m[1] === shortSha) { shouldBuild = false; // no new commits since last nightly } } core.setOutput('should_build', String(shouldBuild)); core.setOutput('default_branch', defaultBranch); core.setOutput('head_sha', headSha); core.setOutput('short_sha', shortSha); compile_sketch: name: build ${{ matrix.board.name }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: board: - { name: "Flipper Zero WiFi Dev Board", flag: "MARAUDER_FLIPPER", fbqn: "esp32:esp32:esp32s2:PartitionScheme=min_spiffs,FlashSize=4M,PSRAM=enabled", file_name: "flipper", tft: false, tft_file: "", build_dir: "esp32s2", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Flipper Zero Multi Board S3", flag: "MARAUDER_MULTIBOARD_S3", fbqn: "esp32:esp32:esp32s3:PartitionScheme=min_spiffs,FlashSize=4M", file_name: "multiboardS3", tft: false, tft_file: "", build_dir: "esp32s3", addr: "0x0", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "OG Marauder", flag: "MARAUDER_V4", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "old_hardware", tft: true, tft_file: "User_Setup_og_marauder.h", build_dir: "d32", addr: "0x1000", idf_ver: "3.3.4", nimble_ver: "master", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Marauder v6", flag: "MARAUDER_V6", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "v6", tft: true, tft_file: "User_Setup_og_marauder.h", build_dir: "d32", addr: "0x1000", idf_ver: "3.3.4", nimble_ver: "master", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Marauder v6.1", flag: "MARAUDER_V6_1", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "v6_1", tft: true, tft_file: "User_Setup_og_marauder.h", build_dir: "d32", addr: "0x1000", idf_ver: "3.3.4", nimble_ver: "master", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Marauder Kit", flag: "MARAUDER_KIT", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "kit", tft: true, tft_file: "User_Setup_og_marauder.h", build_dir: "d32", addr: "0x1000", idf_ver: "3.3.4", nimble_ver: "master", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Marauder Mini", flag: "MARAUDER_MINI", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "mini", tft: true, tft_file: "User_Setup_marauder_mini.h", build_dir: "d32", addr: "0x1000", idf_ver: "3.3.4", nimble_ver: "master", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "ESP32 LDDB", flag: "ESP32_LDDB", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "esp32_lddb", tft: false, tft_file: "", build_dir: "d32", addr: "0x1000", idf_ver: "3.3.4", nimble_ver: "master", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Marauder Dev Board Pro", flag: "MARAUDER_DEV_BOARD_PRO", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "marauder_dev_board_pro", tft: false, tft_file: "", build_dir: "d32", addr: "0x1000", idf_ver: "3.3.4", nimble_ver: "master", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "M5StickCPlus", flag: "MARAUDER_M5STICKC", fbqn: "esp32:esp32:m5stick-c:PartitionScheme=min_spiffs", file_name: "m5stickc_plus", tft: true, tft_file: "User_Setup_marauder_m5stickc.h", build_dir: "m5stick-c", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "M5StickCPlus 2", flag: "MARAUDER_M5STICKCP2", fbqn: "esp32:esp32:m5stick-c:PartitionScheme=min_spiffs", file_name: "m5stickc_plus2", tft: true, tft_file: "User_Setup_marauder_m5stickcp2.h", build_dir: "m5stick-c", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Rev Feather", flag: "MARAUDER_REV_FEATHER", fbqn: "esp32:esp32:esp32s2:PartitionScheme=min_spiffs,FlashSize=4M,PSRAM=enabled", file_name: "rev_feather", tft: true, tft_file: "User_Setup_marauder_rev_feather.h", build_dir: "esp32s2", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Marauder v7", flag: "MARAUDER_V7", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "marauder_v7", tft: true, tft_file: "User_Setup_dual_nrf24.h", build_dir: "d32", addr: "0x1000", idf_ver: "3.3.4", nimble_ver: "master", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Marauder CYD 2432S028", flag: "MARAUDER_CYD_MICRO", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "cyd_2432S028", tft: true, tft_file: "User_Setup_cyd_micro.h", build_dir: "d32", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Marauder CYD 2432S024 GUITION", flag: "MARAUDER_CYD_GUITION", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "cyd_2432S024_guition", tft: true, tft_file: "User_Setup_cyd_guition.h", build_dir: "d32", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Marauder CYD 2432S028 2 USB", flag: "MARAUDER_CYD_2USB", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "cyd_2432S028_2usb", tft: true, tft_file: "User_Setup_cyd_2usb.h", build_dir: "d32", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Marauder CYD 3.5inch", flag: "MARAUDER_CYD_3_5_INCH", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "cyd_3_5_inch", tft: true, tft_file: "User_Setup_cyd_3_5_inch.h", build_dir: "d32", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "M5Cardputer", flag: "MARAUDER_CARDPUTER", fbqn: "esp32:esp32:esp32s3:PartitionScheme=min_spiffs,FlashSize=8M,PSRAM=disabled", file_name: "m5cardputer", tft: true, tft_file: "User_Setup_marauder_m5cardputer.h", build_dir: "esp32s3", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "ESP32-C5-DevKitC-1", flag: "MARAUDER_C5", fbqn: "esp32:esp32:esp32c5:FlashSize=8M,PartitionScheme=min_spiffs,PSRAM=enabled", file_name: "esp32c5devkitc1", tft: false, tft_file: "", build_dir: "esp32c5", addr: "0x2000", idf_ver: "3.3.4", nimble_ver: "master", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } steps: - name: Checkout Code uses: actions/checkout@v3 - name: Install Arduino CLI run: | curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh echo "/home/runner/work/ESP32Marauder/ESP32Marauder/bin" >> $GITHUB_PATH export PATH=$PATH:/home/runner/work/ESP32Marauder/ESP32Marauder/bin arduino-cli version - name: Verify Installed Cores run: arduino-cli core list - name: Build TestFile with ESP32 v${{ matrix.board.idf_ver }} uses: ArminJo/arduino-test-compile@v3.2.1 with: sketch-names: TestFile.ino arduino-board-fqbn: esp32:esp32:esp32s2 arduino-platform: esp32:esp32@${{ matrix.board.idf_ver }} platform-url: https://github.com/espressif/arduino-esp32/releases/download/${{ matrix.board.idf_ver }}/package_esp32_dev_index.json - name: Verify Installed Cores Again run: arduino-cli core list - name: Show Arduino dir structure run: | find /home/runner/.arduino15/packages/esp32/hardware/ - name: Install ESP32Ping uses: actions/checkout@v2 with: repository: marian-craciunescu/ESP32Ping ref: 1.6 path: CustomESP32Ping - name: Install AsyncTCP uses: actions/checkout@v2 with: repository: ESP32Async/AsyncTCP ref: v3.4.8 path: CustomAsyncTCP - name: Install MicroNMEA uses: actions/checkout@v2 with: repository: stevemarple/MicroNMEA ref: v2.0.6 path: CustomMicroNMEA - name: Install ESPAsyncWebServer uses: actions/checkout@v2 with: repository: ESP32Async/ESPAsyncWebServer ref: v3.8.1 path: CustomESPAsyncWebServer - name: Install TFT_eSPI uses: actions/checkout@v2 with: repository: Bodmer/TFT_eSPI ref: V2.5.34 path: CustomTFT_eSPI - name: Install XPT2046_Touchscreen uses: actions/checkout@v2 with: repository: PaulStoffregen/XPT2046_Touchscreen ref: v1.4 path: CustomXPT2046_Touchscreen - name: Install lv_arduino uses: actions/checkout@v2 with: repository: lvgl/lv_arduino ref: 3.0.0 path: Customlv_arduino - name: Install JPEGDecoder uses: actions/checkout@v2 with: repository: Bodmer/JPEGDecoder ref: 1.8.0 path: CustomJPEGDecoder - name: Install NimBLE-Arduino uses: actions/checkout@v2 with: repository: h2zero/NimBLE-Arduino ref: ${{ matrix.board.nimble_ver }} path: CustomNimBLE-Arduino - name: Install Adafruit_NeoPixel uses: actions/checkout@v2 with: repository: adafruit/Adafruit_NeoPixel ref: 1.12.0 path: CustomAdafruit_NeoPixel - name: Install ArduinoJson uses: actions/checkout@v2 with: repository: bblanchon/ArduinoJson ref: v6.18.2 path: CustomArduinoJson - name: Install LinkedList uses: actions/checkout@v2 with: repository: ivanseidel/LinkedList ref: v1.3.3 path: CustomLinkedList - name: Install EspSoftwareSerial uses: actions/checkout@v2 with: repository: plerup/espsoftwareserial ref: 8.1.0 path: CustomEspSoftwareSerial - name: Install Adafruit_BusIO uses: actions/checkout@v2 with: repository: adafruit/Adafruit_BusIO ref: 1.15.0 path: CustomAdafruit_BusIO - name: Install Adafruit_MAX1704X uses: actions/checkout@v2 with: repository: adafruit/Adafruit_MAX1704X ref: 1.0.2 path: CustomAdafruit_MAX1704X - name: Show Libraries run: | find /home/runner/ -name "Custom*" - name: Configure TFT_eSPI run: | rm -f CustomTFT_eSPI/User_Setup_Select.h cp User*.h CustomTFT_eSPI/ pwd ls -la ls -la CustomTFT_eSPI - name: Install Esptool run: | pip install esptool - name: Modify platform.txt run: | if [[ ${{ matrix.board.idf_ver }} == "2.0.11" ]]; then for i in $(find /home/runner/.arduino15/packages/esp32/hardware/esp32/ -name "platform.txt"); do sed -i 's/compiler.c.elf.libs.esp32c3=/compiler.c.elf.libs.esp32c3=-zmuldefs /' "$i" sed -i 's/compiler.c.elf.libs.esp32s3=/compiler.c.elf.libs.esp32s3=-zmuldefs /' "$i" sed -i 's/compiler.c.elf.libs.esp32s2=/compiler.c.elf.libs.esp32s2=-zmuldefs /' "$i" sed -i 's/compiler.c.elf.libs.esp32=/compiler.c.elf.libs.esp32=-zmuldefs /' "$i" cat "$i" | grep compiler.c.elf.libs.esp32c3 cat "$i" | grep compiler.c.elf.libs.esp32s3 cat "$i" | grep compiler.c.elf.libs.esp32s2 cat "$i" | grep compiler.c.elf.libs.esp32 done fi if [[ ${{ matrix.board.idf_ver }} == "3.3.4" ]]; then for i in $(find /home/runner/.arduino15/packages/esp32/hardware/esp32/ -name "platform.txt"); do sed -i 's/compiler.c.elf.extra_flags=/compiler.c.elf.extra_flags=-Wl,-zmuldefs /' "$i" done fi - name: Configure TFT_eSPI (if needed) run: | pwd if [[ ${{ matrix.board.tft }} == true ]]; then find /home/runner/ -name "*TFT_eSPI*" sed -i 's/^\/\/#include <${{ matrix.board.tft_file }}>/#include <${{ matrix.board.tft_file }}>/' /home/runner/work/ESP32Marauder/ESP32Marauder/CustomTFT_eSPI/User_Setup_Select.h fi - name: Build Marauder for ${{ matrix.board.name }} uses: ArminJo/arduino-test-compile@v3.3.0 with: sketch-names: esp32_marauder.ino arduino-board-fqbn: ${{ matrix.board.fbqn }} extra-arduino-cli-args: "--warnings none --build-property compiler.cpp.extra_flags='-D${{ matrix.board.flag }}'" arduino-platform: esp32:esp32@${{ matrix.board.idf_ver }} platform-url: https://github.com/espressif/arduino-esp32/releases/download/${{ matrix.board.idf_ver }}/package_esp32_dev_index.json - name: Rename and Upload ${{ matrix.board.name }} Artifact run: | VERSION=$(grep '#define MARAUDER_VERSION' ./esp32_marauder/configs.h | sed -E 's/.*"v([^"]+)"/v\1/' | tr '.' '_') DATE=$(date +%Y%m%d) BUILD_DIR=./esp32_marauder/build/esp32.esp32.${{ matrix.board.build_dir }} INPUT_BIN=$BUILD_DIR/esp32_marauder.ino.bin OUTPUT_BIN=esp32_marauder_${VERSION}_beta_${DATE}_${{ matrix.board.file_name }}.bin mv "$INPUT_BIN" "$BUILD_DIR/$OUTPUT_BIN" echo "artifact_name=$OUTPUT_BIN" >> $GITHUB_ENV echo "artifact_path=$BUILD_DIR/$OUTPUT_BIN" >> $GITHUB_ENV echo "wild_card=esp32_marauder_${VERSION}_beta_${DATE}_*.bin" >> $GITHUB_ENV - name: Upload ${{ matrix.board.name }} Artifact uses: actions/upload-artifact@v4 with: name: ${{ env.artifact_name }} path: ${{ env.artifact_path }} retention-days: 5 post_compile_steps: name: Create Nightly Release runs-on: ubuntu-latest needs: [compile_sketch, decide] # create release if manual dispatch OR should_release decided true for scheduled run if: ${{ needs.decide.outputs.should_build == 'true' }} steps: - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 with: merge-multiple: true - name: Compute release title/tag id: meta shell: bash run: | VERSION=$(grep '#define MARAUDER_VERSION' ./esp32_marauder/configs.h | sed -E 's/.*"v([^"]+)"/v\1/' | tr '.' '_') DATE=$(date +%Y%m%d) SHORT_SHA="$(git rev-parse --short HEAD)" if [[ "${{ github.event_name }}" == "schedule" ]]; then echo "name=${SHORT_SHA}_nightly" >> $GITHUB_OUTPUT # keep your existing tag, or set one here: echo "tag=nightly-$(date -u +'%Y%m%d')-${SHORT_SHA}" >> $GITHUB_OUTPUT echo "prerelease=true" >> $GITHUB_OUTPUT else echo "name=${SHORT_SHA}" >> $GITHUB_OUTPUT echo "tag=manual-$(date -u +'%Y%m%d')-${SHORT_SHA}" >> $GITHUB_OUTPUT echo "prerelease=false" >> $GITHUB_OUTPUT fi echo "wild_card=esp32_marauder_${VERSION}_beta_${DATE}_*.bin" >> $GITHUB_ENV echo ${{ env.wild_card }} - name: Delete old assets on nightly release (if any) uses: actions/github-script@v7 with: script: | const owner = context.repo.owner; const repo = context.repo.repo; let rel; try { rel = await github.rest.repos.getReleaseByTag({ owner, repo, tag: 'nightly' }); } catch (e) { if (e.status === 404) { // No release yet — nothing to delete return; } throw e; } const assets = rel.data.assets || []; for (const a of assets) { await github.rest.repos.deleteReleaseAsset({ owner, repo, asset_id: a.id }); core.info(`Deleted old asset: ${a.name}`); } - name: Create Release uses: softprops/action-gh-release@v1 with: name: ${{ needs.decide.outputs.short_sha }}_nightly tag_name: nightly_${{ needs.decide.outputs.short_sha }} prerelease: true generate_release_notes: false draft: false files: | ${{ env.wild_card }} body: | [justcallmekokollc.com](https://justcallmekokollc.com) ### This is an automated pre-release / beta created by CI. ### Please see [GPS Modification](https://github.com/justcallmekoko/ESP32Marauder/wiki/gps-modification) to find out how to add GPS capabilities to your Marauder. **Flipper Zero Marauder Companion App:** **Be sure to install the latest version of the [Marauder Companion](https://github.com/0xchocolate/flipperzero-wifi-marauder/releases/latest) to use these new features on your Flipper Zero** **Additional Resources** **[Project Issues](https://github.com/justcallmekoko/ESP32Marauder/issues)** **[Install/Update Instructions](https://github.com/justcallmekoko/ESP32Marauder/wiki/update-firmware)** **[ESP32 Marauder companion app](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion/releases/latest)** **[My Discord](https://discord.com/servers/willstunforfood-776211399918878760)** **Note:** Nightly pre-releases are for testing and evaluation. Use them at your own risk. | Hardware | Binary Version | | -------- | -------------- | | v4 (OG) | `_old_hardware.bin` | | v6 | `_new_hardware.bin`/`_v6.bin` | | v6.1/v6.2 | `_v6_1.bin` | | v7 | `_v7.bin` | | Kit | `_kit.bin` | | Mini | `_mini.bin` | | Flipper Zero | `_flipper.bin` | | MutliBoard S3 | `_multiboardS3.bin` | | LDDB/NodeMCU/Wemos | `_lddb.bin` | | Dev Board Pro | `_marauder_dev_board_pro.bin` | | BFFB | `_marauder_dev_board_pro.bin` | | ESP32-S2 Reverse Feather | `_rev_feather.bin` | | CYD 2432S028(R) | `_cyd_2432S028.bin` | | RL Phantom | `_cyd_2432S024_guition.bin` | | CYD 2432S028 2 USB | `_cyd_2432S028_2usb.bin` | | M5 Cardputer | `_m5cardputer.bin` (Available on M5 Burner) | | ESP32-C5 DevKit | [`_esp32c5_devkit.bin`](https://github.com/justcallmekoko/ESP32Marauder/wiki/ESP32%E2%80%90C5%E2%80%90DevKitC%E2%80%901) | | AWOK V2/V3 screen (white usb) | `_v6_1.bin` | | AWOK V2 flipper (orange usb) | `_flipper.bin` | | AWOK V3 flipper (orange usb) | `_marauder_dev_board_pro.bin` |