name: ESP32 Build & Release on: push: branches: - main jobs: build: runs-on: ubuntu-latest steps: # ------------------------------------------------------------ # Checkout # ------------------------------------------------------------ - name: Checkout uses: actions/checkout@v4 # ------------------------------------------------------------ # System dependencies # ------------------------------------------------------------ - name: Install system dependencies shell: bash run: | sudo apt-get update sudo apt-get install -y \ git \ wget \ flex \ bison \ gperf \ python3 \ python3-pip \ python3-venv \ cmake \ ninja-build \ ccache \ libffi-dev \ libssl-dev \ dfu-util # ------------------------------------------------------------ # Cache ESP-IDF and Espressif tools # ------------------------------------------------------------ - name: Cache ESP-IDF uses: actions/cache@v4 with: path: | ~/esp/esp-idf ~/.espressif key: esp-idf-5.5-esp32-${{ runner.os }} restore-keys: | esp-idf-5.5-esp32- # ------------------------------------------------------------ # Install ESP-IDF 5.5 # ------------------------------------------------------------ - name: Install ESP-IDF 5.5 shell: bash run: | mkdir -p "$HOME/esp" if [ ! -f "$HOME/esp/esp-idf/export.sh" ]; then echo "ESP-IDF not found in cache." echo "Cloning ESP-IDF 5.5..." git clone --recursive \ --branch v5.5 \ https://github.com/espressif/esp-idf.git \ "$HOME/esp/esp-idf" cd "$HOME/esp/esp-idf" ./install.sh esp32 else echo "Using cached ESP-IDF." fi # ------------------------------------------------------------ # Verify ESP-IDF # ------------------------------------------------------------ - name: Verify ESP-IDF shell: bash run: | source "$HOME/esp/esp-idf/export.sh" echo "ESP-IDF:" idf.py --version # ------------------------------------------------------------ # Build firmware # ------------------------------------------------------------ - name: Build firmware shell: bash run: | source "$HOME/esp/esp-idf/export.sh" idf.py set-target esp32 idf.py build # ------------------------------------------------------------ # Create merged firmware image # ------------------------------------------------------------ - name: Create merged firmware shell: bash run: | source "$HOME/esp/esp-idf/export.sh" idf.py merge-bin # ------------------------------------------------------------ # Prepare release artifacts # ------------------------------------------------------------ # ------------------------------------------------------------ # Prepare release artifacts & calculate hashes # ------------------------------------------------------------ - name: Prepare release shell: bash run: | mkdir -p release # Primary OTA application binary if [ -f build/mtg-rfid-companion.bin ]; then cp build/mtg-rfid-companion.bin release/mtg-rfid-companion.bin cp build/mtg-rfid-companion.bin release/firmware.bin else echo "ERROR: build/mtg-rfid-companion.bin not found!" exit 1 fi # Merged binary for USB factory flashing if [ -f build/merged-binary.bin ]; then cp build/merged-binary.bin release/merged-firmware.bin fi # ELF for debugging find build -maxdepth 1 -type f -name "*.elf" -exec cp {} release/ \; # Calculate hashes BIN_SHA256=$(sha256sum release/mtg-rfid-companion.bin | awk '{print $1}') IMG_SHA256=$(python3 -c "with open('release/mtg-rfid-companion.bin','rb') as f: f.seek(-32,2); print(f.read().hex())") echo "BIN_SHA256=${BIN_SHA256}" >> $GITHUB_ENV echo "IMG_SHA256=${IMG_SHA256}" >> $GITHUB_ENV echo "Firmware SHA256: ${BIN_SHA256}" > release/firmware.sha256 echo "Image SHA256: ${IMG_SHA256}" >> release/firmware.sha256 echo "Commit: ${{ github.sha }}" >> release/firmware.sha256 echo "OTA Release prepared:" echo " Binary: release/mtg-rfid-companion.bin" echo " File SHA-256: ${BIN_SHA256}" echo " Image SHA-256: ${IMG_SHA256}" ls -lh release/ # ------------------------------------------------------------ # Delete existing "latest" release # ------------------------------------------------------------ - name: Delete existing latest release shell: bash env: GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | API="${{ github.server_url }}/api/v1" echo "Removing existing latest release..." curl -fsSL \ -X DELETE \ -H "Authorization: token ${GITEA_TOKEN}" \ "${API}/repos/${{ github.repository }}/releases/tags/latest" \ || true # Delete the tag as well curl -fsSL \ -X DELETE \ -H "Authorization: token ${GITEA_TOKEN}" \ "${API}/repos/${{ github.repository }}/tags/latest" \ || true # ------------------------------------------------------------ # Create latest release # ------------------------------------------------------------ - name: Create latest release uses: akkuman/gitea-release-action@v1 with: server_url: ${{ github.server_url }} repository: ${{ github.repository }} token: ${{ secrets.GITHUB_TOKEN }} tag_name: latest name: "Latest ESP32 Firmware" body: | Automatically built from the `main` branch. Commit: ${{ github.sha }} SHA256: ${{ env.IMG_SHA256 }} File-SHA256: ${{ env.BIN_SHA256 }} ESP-IDF: 5.5 Target: ESP32 This release is automatically replaced on every push to `main`. files: | release/*