From 914762dd6fcf25f57f95c7376d5856e929d57d1f Mon Sep 17 00:00:00 2001 From: pszafer Date: Mon, 26 Jan 2026 08:36:08 +0100 Subject: [PATCH] attempt to autodeploy esphome firmware --- .github/workflows/build-firmware.yml | 194 +++++++++++++++++++++++++++ create_firmware.py | 18 ++- 2 files changed, 207 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/build-firmware.yml diff --git a/.github/workflows/build-firmware.yml b/.github/workflows/build-firmware.yml new file mode 100644 index 0000000..a1aef88 --- /dev/null +++ b/.github/workflows/build-firmware.yml @@ -0,0 +1,194 @@ +name: Build ESPHome Firmware + +on: + push: + tags: + - 'v*' + workflow_dispatch: + inputs: + version: + description: 'Version tag (e.g., 2026.1.2)' + required: true + default: '2026.1.2' + +env: + ESPHOME_VERSION: "2024.12.4" + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - yaml_file: boneio-dimmer_gen2_2rgbw-v0_1.yaml + chip_family: ESP32-S3 + - yaml_file: boneio-dimmer_gen2_8ch-v0_1.yaml + chip_family: ESP32-S3 + - yaml_file: boneio-32x10_lights_v0_7.yaml + chip_family: ESP32 + - yaml_file: boneio-32x10_switches_v0_7.yaml + chip_family: ESP32 + - yaml_file: boneio-24x16_switches_v0_7.yaml + chip_family: ESP32 + - yaml_file: boneio-cover_v0_7.yaml + chip_family: ESP32 + - yaml_file: boneio-cover_mix_lights_v0_7.yaml + chip_family: ESP32 + - yaml_file: boneio-cover_mix_switches_v0_7.yaml + chip_family: ESP32 + - yaml_file: boneio-8x10A_gen2_lights-v0_1.yaml + chip_family: ESP32-S3 + - yaml_file: boneio-mosfet48_lights_v0_7.yaml + chip_family: ESP32 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install ESPHome + run: pip install esphome==${{ env.ESPHOME_VERSION }} + + - name: Build firmware + run: esphome compile ${{ matrix.yaml_file }} + + - name: Get firmware name from YAML + id: get_name + run: | + NAME=$(grep -m1 'name:' ${{ matrix.yaml_file }} | sed 's/.*name:\s*//' | tr -d ' ') + echo "firmware_name=$NAME" >> $GITHUB_OUTPUT + echo "chip_family=${{ matrix.chip_family }}" >> $GITHUB_OUTPUT + + - name: Copy firmware to output + run: | + mkdir -p output + FIRMWARE_NAME="${{ steps.get_name.outputs.firmware_name }}" + cp .esphome/build/${FIRMWARE_NAME}/.pioenvs/${FIRMWARE_NAME}/firmware.factory.bin output/${FIRMWARE_NAME}.bin + + - name: Upload firmware artifact + uses: actions/upload-artifact@v4 + with: + name: firmware-${{ steps.get_name.outputs.firmware_name }} + path: output/*.bin + + - name: Upload chip family info + run: echo "${{ matrix.chip_family }}" > output/${{ steps.get_name.outputs.firmware_name }}.chip + + - name: Upload chip info artifact + uses: actions/upload-artifact@v4 + with: + name: chip-${{ steps.get_name.outputs.firmware_name }} + path: output/*.chip + + deploy: + needs: build + runs-on: ubuntu-latest + permissions: + contents: write + pages: write + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Download firmware artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + pattern: firmware-* + merge-multiple: true + + - name: Download chip info artifacts + uses: actions/download-artifact@v4 + with: + path: chip-info + pattern: chip-* + merge-multiple: true + + - name: Get version + id: version + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT + else + echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT + fi + + - name: Prepare GitHub Pages content + run: | + mkdir -p gh-pages/firmware + cp artifacts/*.bin gh-pages/firmware/ + + # Generate manifest JSON files for ESP Web Tools + for bin in gh-pages/firmware/*.bin; do + FIRMWARE_NAME=$(basename "$bin" .bin) + CHIP_FAMILY="ESP32" + if [ -f "chip-info/${FIRMWARE_NAME}.chip" ]; then + CHIP_FAMILY=$(cat "chip-info/${FIRMWARE_NAME}.chip") + elif [[ "$FIRMWARE_NAME" == *"gen2"* ]]; then + CHIP_FAMILY="ESP32-S3" + fi + + cat > gh-pages/${FIRMWARE_NAME}.json << EOF + { + "name": "boneIO ESPHome", + "version": "${{ steps.version.outputs.version }}", + "home_assistant_domain": "esphome", + "funding_url": "https://esphome.io/guides/supporters.html", + "new_install_prompt_erase": false, + "builds": [ + { + "chipFamily": "${CHIP_FAMILY}", + "parts": [ + { + "path": "firmware/${FIRMWARE_NAME}.bin", + "offset": 0 + } + ] + } + ] + } + EOF + done + + # Create version file + echo "${{ steps.version.outputs.version }}" > gh-pages/version.txt + + # Create index with firmware list + cat > gh-pages/index.html << 'EOF' + + + boneIO Firmware + +

boneIO ESPHome Firmware

+ + + + EOF + + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./gh-pages + force_orphan: true + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: v${{ steps.version.outputs.version }} + name: Firmware v${{ steps.version.outputs.version }} + files: artifacts/*.bin + generate_release_notes: true diff --git a/create_firmware.py b/create_firmware.py index 1857521..07554a9 100644 --- a/create_firmware.py +++ b/create_firmware.py @@ -32,15 +32,23 @@ exclude_files = [ ] include_files = [ - "boneio-8x10A_gen2_lights-v0_1.yaml", - # "boneio-dimmer_gen2_2rgbw-v0_1.yaml", + # "boneio-8x10A_gen2_lights-v0_1.yaml", + "boneio-dimmer_gen2_2rgbw-v0_1.yaml", + "boneio-dimmer_gen2_8ch-v0_1" ] +GITHUB_PAGES_URL = "https://boneio-eu.github.io/esphome" +FIRMWARE_VERSION = "2026.1.2" + + def json_pattern(firmware_name, chip_family="ESP32"): + # GitHub Pages supports CORS - works with ESP Web Tools + firmware_path = f"{GITHUB_PAGES_URL}/firmware/{firmware_name}.bin" + return { "name": "ESPHome", - "version": "2025.11.2", + "version": FIRMWARE_VERSION, "home_assistant_domain": "esphome", "funding_url": "https://esphome.io/guides/supporters.html", "new_install_prompt_erase": False, @@ -49,7 +57,7 @@ def json_pattern(firmware_name, chip_family="ESP32"): "chipFamily": chip_family, "parts": [ { - "path": f"/fwesp/firmware/{firmware_name}.bin", + "path": firmware_path, "offset": 0, } ], @@ -84,7 +92,7 @@ for file in glob.glob("*.yaml"): print("No file found.") break firmware_path = f"{cwd}/.esphome/build/{filename}/.pioenvs/{filename}/firmware.factory.bin" - cmd = f'docker run --rm -p 6052:6052 -v "{cwd}":/config -it ghcr.io/esphome/esphome compile {file}' + cmd = f'docker run --rm -p 6053:6052 -v "{cwd}":/config -it ghcr.io/esphome/esphome compile {file}' print(cmd) result = subprocess.run( cmd,