Skip to content

feat(ci): multi-chip support with auto-detection for WiFiProvisioning #10

feat(ci): multi-chip support with auto-detection for WiFiProvisioning

feat(ci): multi-chip support with auto-detection for WiFiProvisioning #10

# GitHub Actions workflow for compiling Arduino firmware
# 用于编译 Arduino 固件的 GitHub Actions 工作流
#
# This workflow automatically compiles ONLY the firmware that was modified.
# 此工作流自动只编译被修改的固件。
#
# Smart build detection:
# 智能构建检测:
# - If library source (src/) changes: rebuild ALL firmware
# 如果库源码(src/)更改:重新构建所有固件
# - If specific example changes: rebuild ONLY that firmware
# 如果特定示例更改:只重新构建该固件
# - Manual trigger: can choose to build all or specific firmware
# 手动触发:可以选择构建所有或特定固件
name: Build Firmware
on:
push:
branches: [main, master]
paths:
- 'arduino/**'
- '.github/workflows/build-firmware.yml'
pull_request:
paths:
- 'arduino/**'
workflow_dispatch: # Allow manual trigger | 允许手动触发
inputs:
build_all:
description: 'Build all firmware (ignore change detection)'
required: false
default: 'false'
type: boolean
firmware:
description: 'Specific firmware to build (leave empty for auto-detect)'
required: false
default: ''
type: string
env:
ARDUINO_CLI_VERSION: "0.35.3"
ESP32_CORE_VERSION: "3.3.4" # Lock ESP32 Core version for build consistency | 锁定 ESP32 Core 版本以确保构建一致性
# Library versions (locked for build stability) | 库版本(锁定以确保构建稳定性)
ARDUINOJSON_VERSION: "7.4.2"
WEBSOCKETS_VERSION: "2.7.1"
NEOPIXEL_VERSION: "1.15.2"
jobs:
# Detect which firmware needs to be built | 检测需要构建的固件
detect-changes:
runs-on: ubuntu-latest
outputs:
build_iot_button: ${{ steps.check.outputs.build_iot_button }}
build_wifi_provisioning: ${{ steps.check.outputs.build_wifi_provisioning }}
library_changed: ${{ steps.check.outputs.library_changed }}
any_firmware_changed: ${{ steps.check.outputs.any_firmware_changed }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 2 # Need previous commit to detect changes | 需要上一个提交来检测更改
- name: Detect changed files
id: check
run: |
echo "Detecting changed files..."
# For manual trigger with build_all, build everything
# 手动触发且 build_all 为 true 时,构建所有
if [ "${{ github.event.inputs.build_all }}" == "true" ]; then
echo "Manual trigger: building all firmware"
echo "build_iot_button=true" >> $GITHUB_OUTPUT
echo "build_wifi_provisioning=true" >> $GITHUB_OUTPUT
echo "library_changed=true" >> $GITHUB_OUTPUT
echo "any_firmware_changed=true" >> $GITHUB_OUTPUT
exit 0
fi
# For manual trigger with specific firmware
# 手动触发指定特定固件
if [ -n "${{ github.event.inputs.firmware }}" ]; then
echo "Manual trigger: building specific firmware: ${{ github.event.inputs.firmware }}"
if [ "${{ github.event.inputs.firmware }}" == "IoTButtonV2_DeepSleep" ]; then
echo "build_iot_button=true" >> $GITHUB_OUTPUT
echo "build_wifi_provisioning=false" >> $GITHUB_OUTPUT
elif [ "${{ github.event.inputs.firmware }}" == "WiFiProvisioning" ]; then
echo "build_iot_button=false" >> $GITHUB_OUTPUT
echo "build_wifi_provisioning=true" >> $GITHUB_OUTPUT
fi
echo "library_changed=false" >> $GITHUB_OUTPUT
echo "any_firmware_changed=true" >> $GITHUB_OUTPUT
exit 0
fi
# Get changed files | 获取更改的文件
if [ "${{ github.event_name }}" == "pull_request" ]; then
CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }})
else
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || git diff --name-only HEAD)
fi
echo "Changed files:"
echo "$CHANGED_FILES"
echo ""
# Initialize flags | 初始化标志
BUILD_IOT_BUTTON=false
BUILD_WIFI_PROVISIONING=false
LIBRARY_CHANGED=false
# Check if library source changed | 检查库源码是否更改
if echo "$CHANGED_FILES" | grep -q "arduino/SeeedHADiscovery/src/"; then
echo "Library source changed - will rebuild ALL firmware"
LIBRARY_CHANGED=true
BUILD_IOT_BUTTON=true
BUILD_WIFI_PROVISIONING=true
fi
# Check if workflow file changed | 检查工作流文件是否更改
if echo "$CHANGED_FILES" | grep -q ".github/workflows/build-firmware.yml"; then
echo "Workflow file changed - will rebuild ALL firmware"
BUILD_IOT_BUTTON=true
BUILD_WIFI_PROVISIONING=true
fi
# Check specific firmware changes | 检查特定固件更改
if echo "$CHANGED_FILES" | grep -q "arduino/SeeedHADiscovery/examples/IoTButtonV2_DeepSleep/"; then
echo "IoTButtonV2_DeepSleep changed"
BUILD_IOT_BUTTON=true
fi
if echo "$CHANGED_FILES" | grep -q "arduino/SeeedHADiscovery/examples/WiFiProvisioning/"; then
echo "WiFiProvisioning changed"
BUILD_WIFI_PROVISIONING=true
fi
# Check if any firmware needs building | 检查是否有固件需要构建
ANY_CHANGED=false
if [ "$BUILD_IOT_BUTTON" == "true" ] || [ "$BUILD_WIFI_PROVISIONING" == "true" ]; then
ANY_CHANGED=true
fi
# Output results | 输出结果
echo ""
echo "Build decisions:"
echo " - IoTButtonV2_DeepSleep: $BUILD_IOT_BUTTON"
echo " - WiFiProvisioning: $BUILD_WIFI_PROVISIONING"
echo " - Library changed: $LIBRARY_CHANGED"
echo " - Any firmware to build: $ANY_CHANGED"
echo "build_iot_button=$BUILD_IOT_BUTTON" >> $GITHUB_OUTPUT
echo "build_wifi_provisioning=$BUILD_WIFI_PROVISIONING" >> $GITHUB_OUTPUT
echo "library_changed=$LIBRARY_CHANGED" >> $GITHUB_OUTPUT
echo "any_firmware_changed=$ANY_CHANGED" >> $GITHUB_OUTPUT
# Build IoTButtonV2_DeepSleep firmware | 构建 IoTButtonV2_DeepSleep 固件
build-iot-button:
needs: detect-changes
if: needs.detect-changes.outputs.build_iot_button == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Arduino CLI
run: |
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=/usr/local/bin sh
arduino-cli version
- name: Install platform and libraries
run: |
arduino-cli config init
arduino-cli config add board_manager.additional_urls "https://espressif.github.io/arduino-esp32/package_esp32_index.json"
arduino-cli core update-index
arduino-cli core install esp32:esp32@${{ env.ESP32_CORE_VERSION }}
# Install libraries with locked versions | 安装锁定版本的库
arduino-cli lib install "ArduinoJson@${{ env.ARDUINOJSON_VERSION }}"
arduino-cli lib install "WebSockets@${{ env.WEBSOCKETS_VERSION }}"
arduino-cli lib install "Adafruit NeoPixel@${{ env.NEOPIXEL_VERSION }}"
echo "Installed library versions:"
arduino-cli lib list
mkdir -p ~/Arduino/libraries
cp -r arduino/SeeedHADiscovery ~/Arduino/libraries/
- name: Compile IoTButtonV2_DeepSleep
run: |
mkdir -p build/IoTButtonV2_DeepSleep
arduino-cli compile \
--fqbn "esp32:esp32:esp32c6:CDCOnBoot=cdc,PartitionScheme=huge_app,CPUFreq=80,FlashMode=qio,FlashSize=4M,UploadSpeed=921600" \
--output-dir "build/IoTButtonV2_DeepSleep" \
--export-binaries \
"arduino/SeeedHADiscovery/examples/IoTButtonV2_DeepSleep/IoTButtonV2_DeepSleep.ino"
echo "Compiled files:"
ls -la build/IoTButtonV2_DeepSleep/
- name: Prepare firmware files
run: |
cd build/IoTButtonV2_DeepSleep
for f in *.bin; do
if [[ "$f" == *".ino.bin" ]]; then
mv "$f" "firmware.bin"
elif [[ "$f" == *".bootloader.bin" ]]; then
mv "$f" "bootloader.bin"
elif [[ "$f" == *".partitions.bin" ]]; then
mv "$f" "partitions.bin"
fi
done
# Copy boot_app0.bin
ESP32_CORE_PATH=$(find ~/.arduino15/packages/esp32/hardware/esp32 -maxdepth 1 -type d -name "${{ env.ESP32_CORE_VERSION }}" | head -1)
if [ -n "$ESP32_CORE_PATH" ] && [ -f "$ESP32_CORE_PATH/tools/partitions/boot_app0.bin" ]; then
cp "$ESP32_CORE_PATH/tools/partitions/boot_app0.bin" ./boot_app0.bin
else
BOOT_APP0=$(find ~/.arduino15/packages/esp32 -name "boot_app0.bin" -type f | head -1)
cp "$BOOT_APP0" ./boot_app0.bin
fi
# Create manifest.json
cat > manifest.json << 'EOF'
{
"name": "IoTButtonV2_DeepSleep",
"version": "1.0.0",
"home_assistant_domain": "seeed_ha_discovery",
"funding_url": "https://www.seeedstudio.com/",
"new_install_prompt_erase": true,
"new_install_improv_wait_time": 0,
"builds": [
{
"chipFamily": "ESP32-C6",
"parts": [
{ "path": "bootloader.bin", "offset": 0 },
{ "path": "partitions.bin", "offset": 32768 },
{ "path": "boot_app0.bin", "offset": 57344 },
{ "path": "firmware.bin", "offset": 65536 }
]
}
]
}
EOF
echo "Final files:"
ls -la
- name: Upload firmware artifact
uses: actions/upload-artifact@v4
with:
name: firmware-IoTButtonV2_DeepSleep
path: build/IoTButtonV2_DeepSleep/
retention-days: 30
# Build WiFiProvisioning firmware for multiple ESP32 chips | 为多种 ESP32 芯片构建 WiFiProvisioning 固件
# This is a generic example that works on all ESP32 variants | 这是一个适用于所有 ESP32 系列的通用示例
build-wifi-provisioning:
needs: detect-changes
if: needs.detect-changes.outputs.build_wifi_provisioning == 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
# ESP32-C3 (XIAO ESP32C3) | ESP32-C3(XIAO ESP32C3)
- chip: "C3"
fqbn: "esp32:esp32:esp32c3:CDCOnBoot=cdc,PartitionScheme=huge_app,CPUFreq=80,FlashMode=qio,FlashSize=4M,UploadSpeed=921600"
chip_family: "ESP32-C3"
bootloader_offset: 0
# ESP32-C6 (XIAO ESP32C6) | ESP32-C6(XIAO ESP32C6)
- chip: "C6"
fqbn: "esp32:esp32:esp32c6:CDCOnBoot=cdc,PartitionScheme=huge_app,CPUFreq=80,FlashMode=qio,FlashSize=4M,UploadSpeed=921600"
chip_family: "ESP32-C6"
bootloader_offset: 0
# ESP32-S3 (XIAO ESP32S3) | ESP32-S3(XIAO ESP32S3)
- chip: "S3"
fqbn: "esp32:esp32:esp32s3:CDCOnBoot=cdc,PartitionScheme=huge_app,USBMode=hwcdc,FlashMode=qio,FlashSize=8M,UploadSpeed=921600,PSRAM=opi"
chip_family: "ESP32-S3"
bootloader_offset: 0
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Arduino CLI
run: |
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=/usr/local/bin sh
arduino-cli version
- name: Install platform and libraries
run: |
arduino-cli config init
arduino-cli config add board_manager.additional_urls "https://espressif.github.io/arduino-esp32/package_esp32_index.json"
arduino-cli core update-index
arduino-cli core install esp32:esp32@${{ env.ESP32_CORE_VERSION }}
# Install libraries with locked versions | 安装锁定版本的库
arduino-cli lib install "ArduinoJson@${{ env.ARDUINOJSON_VERSION }}"
arduino-cli lib install "WebSockets@${{ env.WEBSOCKETS_VERSION }}"
arduino-cli lib install "Adafruit NeoPixel@${{ env.NEOPIXEL_VERSION }}"
echo "Installed library versions:"
arduino-cli lib list
mkdir -p ~/Arduino/libraries
cp -r arduino/SeeedHADiscovery ~/Arduino/libraries/
- name: Compile WiFiProvisioning for ${{ matrix.chip }}
run: |
FIRMWARE_NAME="WiFiProvisioning-${{ matrix.chip }}"
mkdir -p build/${FIRMWARE_NAME}
echo "Compiling for ${{ matrix.chip_family }}..."
arduino-cli compile \
--fqbn "${{ matrix.fqbn }}" \
--output-dir "build/${FIRMWARE_NAME}" \
--export-binaries \
"arduino/SeeedHADiscovery/examples/WiFiProvisioning/WiFiProvisioning.ino"
echo "Compiled files:"
ls -la build/${FIRMWARE_NAME}/
- name: Prepare firmware files for ${{ matrix.chip }}
run: |
# Create chip-specific subfolder | 创建芯片特定的子文件夹
# Structure: WiFiProvisioning/C3/, WiFiProvisioning/C6/, WiFiProvisioning/S3/
# ESP Web Tools will auto-detect chip and use correct subfolder
# ESP Web Tools 会自动检测芯片并使用正确的子文件夹
CHIP_DIR="build/WiFiProvisioning/${{ matrix.chip }}"
mkdir -p ${CHIP_DIR}
# Move and rename binaries to chip subfolder | 移动并重命名二进制文件到芯片子文件夹
cd build/WiFiProvisioning-${{ matrix.chip }}
for f in *.bin; do
if [[ "$f" == *".ino.bin" ]]; then
cp "$f" "../WiFiProvisioning/${{ matrix.chip }}/firmware.bin"
elif [[ "$f" == *".bootloader.bin" ]]; then
cp "$f" "../WiFiProvisioning/${{ matrix.chip }}/bootloader.bin"
elif [[ "$f" == *".partitions.bin" ]]; then
cp "$f" "../WiFiProvisioning/${{ matrix.chip }}/partitions.bin"
fi
done
# Copy boot_app0.bin to chip subfolder
ESP32_CORE_PATH=$(find ~/.arduino15/packages/esp32/hardware/esp32 -maxdepth 1 -type d -name "${{ env.ESP32_CORE_VERSION }}" | head -1)
if [ -n "$ESP32_CORE_PATH" ] && [ -f "$ESP32_CORE_PATH/tools/partitions/boot_app0.bin" ]; then
cp "$ESP32_CORE_PATH/tools/partitions/boot_app0.bin" "../WiFiProvisioning/${{ matrix.chip }}/boot_app0.bin"
else
BOOT_APP0=$(find ~/.arduino15/packages/esp32 -name "boot_app0.bin" -type f | head -1)
cp "$BOOT_APP0" "../WiFiProvisioning/${{ matrix.chip }}/boot_app0.bin"
fi
echo "Files for ${{ matrix.chip_family }}:"
ls -la ../WiFiProvisioning/${{ matrix.chip }}/
- name: Upload firmware artifact for ${{ matrix.chip }}
uses: actions/upload-artifact@v4
with:
name: firmware-WiFiProvisioning-${{ matrix.chip }}
path: build/WiFiProvisioning/${{ matrix.chip }}/
retention-days: 30
# Combine all built firmware | 合并所有构建的固件
combine:
needs: [detect-changes, build-iot-button, build-wifi-provisioning]
if: always() && needs.detect-changes.outputs.any_firmware_changed == 'true'
runs-on: ubuntu-latest
steps:
- name: Download all firmware artifacts
uses: actions/download-artifact@v4
with:
path: all-firmware/
pattern: firmware-*
continue-on-error: true # Some artifacts may not exist | 某些 artifact 可能不存在
- name: Check downloaded artifacts
run: |
echo "Downloaded artifacts:"
ls -la all-firmware/ 2>/dev/null || echo "No artifacts directory"
find all-firmware -type f 2>/dev/null || echo "No files found"
- name: Reorganize firmware files
run: |
mkdir -p combined-firmware
if [ -d "all-firmware" ]; then
# Handle IoTButtonV2_DeepSleep (single chip) | 处理 IoTButtonV2_DeepSleep(单芯片)
if [ -d "all-firmware/firmware-IoTButtonV2_DeepSleep" ]; then
echo "Adding IoTButtonV2_DeepSleep..."
cp -r "all-firmware/firmware-IoTButtonV2_DeepSleep" "combined-firmware/IoTButtonV2_DeepSleep"
fi
# Handle WiFiProvisioning (multi-chip) | 处理 WiFiProvisioning(多芯片)
# Merge all chip variants into one folder with subfolders
# 将所有芯片变体合并到一个带有子文件夹的目录中
mkdir -p combined-firmware/WiFiProvisioning
for chip in C3 C6 S3; do
if [ -d "all-firmware/firmware-WiFiProvisioning-${chip}" ]; then
echo "Adding WiFiProvisioning/${chip}..."
mkdir -p "combined-firmware/WiFiProvisioning/${chip}"
cp -r "all-firmware/firmware-WiFiProvisioning-${chip}/"* "combined-firmware/WiFiProvisioning/${chip}/"
fi
done
# Create multi-build manifest.json for WiFiProvisioning
# 为 WiFiProvisioning 创建多芯片 manifest.json
# ESP Web Tools will auto-detect connected chip and use correct build
# ESP Web Tools 会自动检测连接的芯片并使用正确的构建
if [ -d "combined-firmware/WiFiProvisioning" ] && [ "$(ls -A combined-firmware/WiFiProvisioning 2>/dev/null)" ]; then
echo "Creating multi-build manifest.json for WiFiProvisioning..."
# Start manifest | 开始 manifest
cat > combined-firmware/WiFiProvisioning/manifest.json << 'MANIFEST_START'
{

Check failure on line 416 in .github/workflows/build-firmware.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/build-firmware.yml

Invalid workflow file

You have an error in your yaml syntax on line 416
"name": "WiFiProvisioning",
"version": "1.0.0",
"home_assistant_domain": "seeed_ha_discovery",
"funding_url": "https://www.seeedstudio.com/",
"new_install_prompt_erase": true,
"new_install_improv_wait_time": 0,
"builds": [
MANIFEST_START
# Add builds for each available chip | 为每个可用芯片添加构建
FIRST_BUILD=true
if [ -d "combined-firmware/WiFiProvisioning/C3" ]; then
if [ "$FIRST_BUILD" = false ]; then echo "," >> combined-firmware/WiFiProvisioning/manifest.json; fi
FIRST_BUILD=false
cat >> combined-firmware/WiFiProvisioning/manifest.json << 'BUILD_C3'
{
"chipFamily": "ESP32-C3",
"parts": [
{ "path": "C3/bootloader.bin", "offset": 0 },
{ "path": "C3/partitions.bin", "offset": 32768 },
{ "path": "C3/boot_app0.bin", "offset": 57344 },
{ "path": "C3/firmware.bin", "offset": 65536 }
]
}
BUILD_C3
fi
if [ -d "combined-firmware/WiFiProvisioning/C6" ]; then
if [ "$FIRST_BUILD" = false ]; then echo "," >> combined-firmware/WiFiProvisioning/manifest.json; fi
FIRST_BUILD=false
cat >> combined-firmware/WiFiProvisioning/manifest.json << 'BUILD_C6'
{
"chipFamily": "ESP32-C6",
"parts": [
{ "path": "C6/bootloader.bin", "offset": 0 },
{ "path": "C6/partitions.bin", "offset": 32768 },
{ "path": "C6/boot_app0.bin", "offset": 57344 },
{ "path": "C6/firmware.bin", "offset": 65536 }
]
}
BUILD_C6
fi
if [ -d "combined-firmware/WiFiProvisioning/S3" ]; then
if [ "$FIRST_BUILD" = false ]; then echo "," >> combined-firmware/WiFiProvisioning/manifest.json; fi
FIRST_BUILD=false
cat >> combined-firmware/WiFiProvisioning/manifest.json << 'BUILD_S3'
{
"chipFamily": "ESP32-S3",
"parts": [
{ "path": "S3/bootloader.bin", "offset": 0 },
{ "path": "S3/partitions.bin", "offset": 32768 },
{ "path": "S3/boot_app0.bin", "offset": 57344 },
{ "path": "S3/firmware.bin", "offset": 65536 }
]
}
BUILD_S3
fi
# Close manifest | 关闭 manifest
cat >> combined-firmware/WiFiProvisioning/manifest.json << 'MANIFEST_END'
]
}
MANIFEST_END
echo "Generated manifest.json:"
cat combined-firmware/WiFiProvisioning/manifest.json
fi
fi
echo ""
echo "=========================="
echo "Combined firmware structure:"
echo "=========================="
find combined-firmware -type f 2>/dev/null || echo "No firmware files"
- name: Upload combined firmware
uses: actions/upload-artifact@v4
with:
name: all-firmware
path: combined-firmware/
retention-days: 90
if: hashFiles('combined-firmware/**') != ''
# Create release | 创建发布版本
release:
needs: [detect-changes, combine]
if: always() && needs.detect-changes.outputs.any_firmware_changed == 'true' && github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for changelog | 完整历史用于更新日志
- name: Download combined firmware
uses: actions/download-artifact@v4
with:
name: all-firmware
path: firmware/
continue-on-error: true
- name: Check firmware exists
id: check_firmware
run: |
if [ -d "firmware" ] && [ "$(ls -A firmware 2>/dev/null)" ]; then
echo "has_firmware=true" >> $GITHUB_OUTPUT
echo "Firmware directory contents:"
find firmware -type f
else
echo "has_firmware=false" >> $GITHUB_OUTPUT
echo "No firmware to release"
fi
- name: Get version and changelog
id: version
if: steps.check_firmware.outputs.has_firmware == 'true'
run: |
VERSION=$(date +'%Y.%m.%d')-$(git rev-parse --short HEAD)
echo "version=$VERSION" >> $GITHUB_OUTPUT
# Get the last release tag
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
echo "Generating changelog..."
if [ -n "$LAST_TAG" ]; then
echo "Changes since $LAST_TAG:"
CHANGELOG=$(git log ${LAST_TAG}..HEAD --pretty=format:"- %s (%h)" --no-merges | head -30)
else
echo "No previous tag found, using last 20 commits"
CHANGELOG=$(git log --pretty=format:"- %s (%h)" --no-merges -20)
fi
echo "$CHANGELOG" > changelog.txt
cat changelog.txt
- name: Package firmware
if: steps.check_firmware.outputs.has_firmware == 'true'
run: |
cd firmware
for dir in */; do
firmware_name="${dir%/}"
echo "Packaging $firmware_name..."
zip -r "${firmware_name}.zip" "$dir"
done
cd ..
zip -r "all-firmware.zip" firmware/
mv all-firmware.zip firmware/
echo "Created packages:"
ls -la firmware/*.zip
- name: Generate release body
if: steps.check_firmware.outputs.has_firmware == 'true'
run: |
CHANGELOG=$(cat changelog.txt)
# Generate firmware table | 生成固件表格
# Categorize firmware by type | 按类型分类固件
echo "| Firmware | Chip | Description |" > firmware_table.md
echo "|----------|------|-------------|" >> firmware_table.md
for dir in firmware/*/; do
firmware_name=$(basename "$dir")
if [ "$firmware_name" != "*.zip" ]; then
# Determine chip and description based on firmware name
# 根据固件名称确定芯片和描述
case "$firmware_name" in
"IoTButtonV2_DeepSleep")
echo "| $firmware_name | ESP32-C6 | IoT Button with deep sleep (XIAO ESP32C6 only) |" >> firmware_table.md
;;
"WiFiProvisioning-C3")
echo "| $firmware_name | ESP32-C3 | WiFi provisioning demo (XIAO ESP32C3) |" >> firmware_table.md
;;
"WiFiProvisioning-C6")
echo "| $firmware_name | ESP32-C6 | WiFi provisioning demo (XIAO ESP32C6) |" >> firmware_table.md
;;
"WiFiProvisioning-S3")
echo "| $firmware_name | ESP32-S3 | WiFi provisioning demo (XIAO ESP32S3) |" >> firmware_table.md
;;
*)
echo "| $firmware_name | - | - |" >> firmware_table.md
;;
esac
fi
done
FIRMWARE_TABLE=$(cat firmware_table.md)
cat > release_body.md << ENDOFHEADER
## 🚀 Firmware Release
Pre-compiled firmware for Seeed HA Discovery devices.
为 Seeed HA Discovery 设备预编译的固件。
### 📥 How to Flash | 如何烧录
**Web Flasher (Recommended | 推荐):**
Visit [Web Flasher](https://limengdu.github.io/Seeed-Homeassistant-Discovery/flasher/) to flash directly from browser.
访问 [网页烧录器](https://limengdu.github.io/Seeed-Homeassistant-Discovery/flasher/) 直接从浏览器烧录。
### 📦 Firmware in this release | 本次发布的固件
$FIRMWARE_TABLE
> **Note:** WiFiProvisioning is available for multiple ESP32 chips. Choose the variant matching your hardware.
> **注意:** WiFiProvisioning 提供多种 ESP32 芯片版本,请选择与您硬件匹配的版本。
### 📝 Changelog | 更新日志
$CHANGELOG
---
**Build Info | 构建信息:**
- ESP32 Core: ${{ env.ESP32_CORE_VERSION }}
- ArduinoJson: ${{ env.ARDUINOJSON_VERSION }}
- WebSockets: ${{ env.WEBSOCKETS_VERSION }}
- Adafruit NeoPixel: ${{ env.NEOPIXEL_VERSION }}
- Build Date: $(date -u '+%Y-%m-%d %H:%M:%S UTC')
- Commit: ${{ github.sha }}
ENDOFHEADER
cat release_body.md
- name: Create Release
if: steps.check_firmware.outputs.has_firmware == 'true'
uses: softprops/action-gh-release@v1
with:
tag_name: firmware-${{ steps.version.outputs.version }}
name: Firmware Release ${{ steps.version.outputs.version }}
body_path: release_body.md
files: |
firmware/*.zip