mirror of
https://github.com/athom-tech/esp32-configs.git
synced 2026-07-27 19:56:13 +00:00
Update ci.yml
This commit is contained in:
+29
-19
@@ -9,34 +9,43 @@ on:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
discover:
|
||||
name: Discover ESPHome YAML files
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.files.outputs.matrix }}
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Discover root-level YAML files
|
||||
id: files
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
mapfile -t files < <(find . -maxdepth 1 -type f -name '*.yaml' -exec basename {} .yaml \; | sort)
|
||||
if [ "${#files[@]}" -eq 0 ]; then
|
||||
echo "No root-level ESPHome YAML files found." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf '%s\n' "${files[@]}"
|
||||
printf 'matrix=%s\n' "$(printf '%s\n' "${files[@]}" | jq -R -s -c 'split("\n")[:-1]')" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
ci:
|
||||
name: Building ${{ matrix.file }} / ${{ matrix.esphome-version }}
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- discover
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 3
|
||||
matrix:
|
||||
#### Modify below here to match your project ####
|
||||
file:
|
||||
- athom-2ch-relay-board
|
||||
- athom-4ch-relay-board
|
||||
- athom-8ch-relay-board
|
||||
- athom-energy-monitor-x2
|
||||
- athom-energy-monitor-x6
|
||||
- athom-garage-door
|
||||
- athom-mini-relay-v2
|
||||
- athom-smart-plug
|
||||
- athom-zigbee-gateway
|
||||
- athom-presence-sensor-v3
|
||||
- athom-scd40-sensor
|
||||
- athom-sht40-sensor
|
||||
- athom-ld2450-sensor
|
||||
#### Modify above here to match your project ####
|
||||
|
||||
file: ${{ fromJson(needs.discover.outputs.matrix) }}
|
||||
esphome-version:
|
||||
- stable
|
||||
- beta
|
||||
@@ -44,8 +53,9 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: ESPHome ${{ matrix.esphome-version }}
|
||||
uses: esphome/build-action@v7
|
||||
with:
|
||||
yaml-file: ${{ matrix.file }}.yaml
|
||||
version: ${{ matrix.esphome-version }}
|
||||
version: ${{ matrix.esphome-version }}
|
||||
|
||||
@@ -1,44 +1,338 @@
|
||||
name: Publish Firmware
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
schedule:
|
||||
- cron: '27 */6 * * *'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
esphome_version:
|
||||
description: 'ESPHome version to build. Leave empty to use the latest stable release.'
|
||||
required: false
|
||||
type: string
|
||||
force:
|
||||
description: 'Recreate the GitHub release if it already exists.'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.inputs.esphome_version || 'latest-stable' }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
name: Prepare Release
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
esphome-version: ${{ steps.release.outputs.esphome-version }}
|
||||
release-tag: ${{ steps.release.outputs.release-tag }}
|
||||
release-url: ${{ steps.release.outputs.release-url }}
|
||||
release-notes: ${{ steps.release.outputs.release-notes }}
|
||||
should-build: ${{ steps.release.outputs.should-build }}
|
||||
matrix: ${{ steps.files.outputs.matrix }}
|
||||
files: ${{ steps.files.outputs.files }}
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Resolve ESPHome release
|
||||
id: release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
INPUT_VERSION: ${{ inputs.esphome_version }}
|
||||
FORCE: ${{ inputs.force }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ -n "${INPUT_VERSION}" ]; then
|
||||
esphome_version="${INPUT_VERSION#v}"
|
||||
else
|
||||
esphome_version="$(
|
||||
gh api repos/esphome/esphome/releases/latest --jq .tag_name
|
||||
)"
|
||||
esphome_version="${esphome_version#v}"
|
||||
fi
|
||||
|
||||
if [ -z "${esphome_version}" ] || [ "${esphome_version}" = "null" ]; then
|
||||
echo "Unable to resolve an ESPHome release version." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
release_tag="esphome-${esphome_version}"
|
||||
release_url="https://github.com/${GH_REPO}/releases/tag/${release_tag}"
|
||||
release_notes="Firmware built automatically from ESPHome ${esphome_version} stable release."
|
||||
should_build="true"
|
||||
|
||||
if gh release view "${release_tag}" >/dev/null 2>&1; then
|
||||
if [ "${FORCE}" = "true" ]; then
|
||||
echo "Release ${release_tag} already exists and will be replaced after a successful build."
|
||||
else
|
||||
should_build="false"
|
||||
fi
|
||||
fi
|
||||
|
||||
{
|
||||
echo "esphome-version=${esphome_version}"
|
||||
echo "release-tag=${release_tag}"
|
||||
echo "release-url=${release_url}"
|
||||
echo "release-notes=${release_notes}"
|
||||
echo "should-build=${should_build}"
|
||||
} >> "${GITHUB_OUTPUT}"
|
||||
|
||||
if [ "${should_build}" = "true" ]; then
|
||||
echo "Building firmware with ESPHome ${esphome_version}."
|
||||
else
|
||||
echo "Release ${release_tag} already exists. Nothing to build."
|
||||
fi
|
||||
|
||||
- name: Discover ESPHome YAML files
|
||||
id: files
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
mapfile -t files < <(find . -maxdepth 1 -type f -name '*.yaml' -exec basename {} \; | sort)
|
||||
if [ "${#files[@]}" -eq 0 ]; then
|
||||
echo "No root-level ESPHome YAML files found." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
json="$(printf '%s\n' "${files[@]}" | jq -R -s -c 'split("\n")[:-1]')"
|
||||
names="$(printf '%s\n' "${files[@]}" | sed 's/\.yaml$//' | jq -R -s -c 'split("\n")[:-1]')"
|
||||
|
||||
{
|
||||
echo "matrix=${json}"
|
||||
echo "files=${names}"
|
||||
} >> "${GITHUB_OUTPUT}"
|
||||
|
||||
build-firmware:
|
||||
name: Build Firmware
|
||||
uses: esphome/workflows/.github/workflows/build.yml@2025.7.0
|
||||
with:
|
||||
#### Modify below here to match your project ####
|
||||
files: |
|
||||
athom-2ch-relay-board.yaml
|
||||
athom-4ch-relay-board.yaml
|
||||
athom-8ch-relay-board.yaml
|
||||
athom-energy-monitor-x2.yaml
|
||||
athom-energy-monitor-x6.yaml
|
||||
athom-garage-door.yaml
|
||||
athom-mini-relay-v2.yaml
|
||||
athom-smart-plug.yaml
|
||||
athom-zigbee-gateway.yaml
|
||||
athom-presence-sensor-v3.yaml
|
||||
athom-scd40-sensor.yaml
|
||||
athom-sht40-sensor.yaml
|
||||
athom-ld2450-sensor.yaml
|
||||
esphome-version: 2025.7.0
|
||||
combined-name: Athom-ESP32-Device
|
||||
#### Modify above here to match your project ####
|
||||
|
||||
release-summary: ${{ github.event.release.body }}
|
||||
release-url: ${{ github.event.release.html_url }}
|
||||
release-version: ${{ github.event.release.tag_name }}
|
||||
|
||||
upload-to-release:
|
||||
name: Upload to Release
|
||||
uses: esphome/workflows/.github/workflows/upload-to-gh-release.yml@2025.7.0
|
||||
name: Build ${{ matrix.file }}
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- prepare
|
||||
if: needs.prepare.outputs.should-build == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 3
|
||||
matrix:
|
||||
file: ${{ fromJson(needs.prepare.outputs.matrix) }}
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: ESPHome ${{ needs.prepare.outputs.esphome-version }}
|
||||
id: build
|
||||
continue-on-error: true
|
||||
uses: esphome/build-action@v7
|
||||
with:
|
||||
yaml-file: ${{ matrix.file }}
|
||||
version: ${{ needs.prepare.outputs.esphome-version }}
|
||||
complete-manifest: true
|
||||
release-summary: ${{ needs.prepare.outputs.release-notes }}
|
||||
release-url: ${{ needs.prepare.outputs.release-url }}
|
||||
|
||||
- name: Collect firmware files
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
name="${{ matrix.file }}"
|
||||
name="${name%.yaml}"
|
||||
mkdir -p "firmware/${name}"
|
||||
|
||||
build_name="${{ steps.build.outputs.name }}"
|
||||
build_dir=""
|
||||
|
||||
if [ -n "${build_name}" ] && [ -d "${build_name}" ]; then
|
||||
build_dir="${build_name}"
|
||||
else
|
||||
mapfile -t candidates < <(find . -mindepth 2 -maxdepth 2 -name '*.factory.bin' -exec dirname {} \; | sed 's#^\./##' | sort -u)
|
||||
if [ "${#candidates[@]}" -eq 1 ]; then
|
||||
build_dir="${candidates[0]}"
|
||||
build_name="$(basename "${build_dir}")"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "${build_dir}" ] || [ ! -d "${build_dir}" ]; then
|
||||
echo "Expected ESPHome build output directory was not found." >&2
|
||||
find . -maxdepth 3 -type f \( -name '*.bin' -o -name 'manifest.json' \) -print >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cp "${build_dir}/"*.bin "firmware/${name}/"
|
||||
|
||||
factory_bin="$(find "firmware/${name}" -maxdepth 1 -name '*.factory.bin' -print -quit)"
|
||||
ota_bin="$(find "firmware/${name}" -maxdepth 1 -name '*.ota.bin' -print -quit)"
|
||||
|
||||
if [ -z "${factory_bin}" ] || [ -z "${ota_bin}" ]; then
|
||||
echo "Expected factory and OTA binaries in '${build_dir}'." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "${build_dir}/manifest.json" ]; then
|
||||
case "${build_name}" in
|
||||
*-esp32) chip_family="ESP32" ;;
|
||||
*-esp32s2) chip_family="ESP32-S2" ;;
|
||||
*-esp32s3) chip_family="ESP32-S3" ;;
|
||||
*-esp32c3) chip_family="ESP32-C3" ;;
|
||||
*-esp32c5) chip_family="ESP32-C5" ;;
|
||||
*-esp32c6) chip_family="ESP32-C6" ;;
|
||||
*-esp8266) chip_family="ESP8266" ;;
|
||||
*) echo "Cannot infer chip family from build name '${build_name}'." >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
jq -n --arg chipFamily "${chip_family}" \
|
||||
--arg name "${name}" \
|
||||
--arg version "${{ needs.prepare.outputs.esphome-version }}" \
|
||||
--arg otaPath "$(basename "${ota_bin}")" \
|
||||
--arg otaMd5 "$(md5sum "${ota_bin}" | awk '{print $1}')" \
|
||||
--arg otaSha256 "$(sha256sum "${ota_bin}" | awk '{print $1}')" \
|
||||
--arg factoryPath "$(basename "${factory_bin}")" \
|
||||
--arg factoryMd5 "$(md5sum "${factory_bin}" | awk '{print $1}')" \
|
||||
--arg factorySha256 "$(sha256sum "${factory_bin}" | awk '{print $1}')" \
|
||||
'{
|
||||
name: $name,
|
||||
version: $version,
|
||||
home_assistant_domain: "esphome",
|
||||
new_install_prompt_erase: false,
|
||||
builds: [
|
||||
{
|
||||
chipFamily: $chipFamily,
|
||||
ota: {
|
||||
path: $otaPath,
|
||||
md5: $otaMd5,
|
||||
sha256: $otaSha256
|
||||
},
|
||||
parts: [
|
||||
{
|
||||
path: $factoryPath,
|
||||
offset: 0,
|
||||
md5: $factoryMd5,
|
||||
sha256: $factorySha256
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}' > "firmware/${name}/manifest.json"
|
||||
else
|
||||
cp "${build_dir}/manifest.json" "firmware/${name}/manifest.json"
|
||||
fi
|
||||
|
||||
find "firmware/${name}" -maxdepth 1 -type f -print | sort
|
||||
test -f "firmware/${name}/manifest.json"
|
||||
|
||||
- name: Upload firmware artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware-${{ matrix.file }}
|
||||
path: firmware/
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
publish-release:
|
||||
name: Publish Release
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- prepare
|
||||
- build-firmware
|
||||
with:
|
||||
version: ${{ github.event.release.tag_name }}
|
||||
if: needs.prepare.outputs.should-build == 'true'
|
||||
steps:
|
||||
- name: Download firmware artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: downloaded-artifacts
|
||||
pattern: firmware-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Prepare release assets
|
||||
env:
|
||||
RELEASE_TAG: ${{ needs.prepare.outputs.release-tag }}
|
||||
ESPHOME_VERSION: ${{ needs.prepare.outputs.esphome-version }}
|
||||
RELEASE_NOTES: ${{ needs.prepare.outputs.release-notes }}
|
||||
FILES_JSON: ${{ needs.prepare.outputs.files }}
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
mkdir -p release-assets firmware
|
||||
if [ -d downloaded-artifacts/firmware ]; then
|
||||
cp -R downloaded-artifacts/firmware/. firmware/
|
||||
else
|
||||
cp -R downloaded-artifacts/. firmware/
|
||||
fi
|
||||
|
||||
jq -n --arg name "Athom ESP32 Device" \
|
||||
--arg version "${ESPHOME_VERSION}" \
|
||||
--arg homeAssistantDomain "esphome" \
|
||||
'{name: $name, version: $version, home_assistant_domain: $homeAssistantDomain, new_install_prompt_erase: false, builds: []}' \
|
||||
> release-assets/Athom-ESP32-Device.manifest.json
|
||||
|
||||
for device_dir in firmware/*; do
|
||||
[ -d "${device_dir}" ] || continue
|
||||
device="$(basename "${device_dir}")"
|
||||
|
||||
if [ -f "${device_dir}/manifest.json" ]; then
|
||||
cp "${device_dir}/manifest.json" "release-assets/${device}.manifest.json"
|
||||
|
||||
tmp_manifest="$(mktemp)"
|
||||
jq --slurpfile manifest "${device_dir}/manifest.json" \
|
||||
'.builds += ($manifest[0].builds // [$manifest[0]])' \
|
||||
release-assets/Athom-ESP32-Device.manifest.json > "${tmp_manifest}"
|
||||
mv "${tmp_manifest}" release-assets/Athom-ESP32-Device.manifest.json
|
||||
fi
|
||||
|
||||
cp "${device_dir}/"*.bin release-assets/
|
||||
done
|
||||
|
||||
cd release-assets
|
||||
shopt -s nullglob
|
||||
for binary in *.bin; do
|
||||
md5sum "${binary}" > "${binary}.md5"
|
||||
sha256sum "${binary}" > "${binary}.sha256"
|
||||
done
|
||||
|
||||
expected_count="$(jq 'length' <<< "${FILES_JSON}")"
|
||||
manifest_count="$(find . -maxdepth 1 -name '*.manifest.json' ! -name 'Athom-ESP32-Device.manifest.json' | wc -l)"
|
||||
factory_count="$(find . -maxdepth 1 -name '*.factory.bin' | wc -l)"
|
||||
ota_count="$(find . -maxdepth 1 -name '*.ota.bin' | wc -l)"
|
||||
|
||||
if [ "${manifest_count}" -ne "${expected_count}" ]; then
|
||||
echo "Expected ${expected_count} device manifests, found ${manifest_count}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${factory_count}" -ne "${expected_count}" ]; then
|
||||
echo "Expected ${expected_count} factory binaries, found ${factory_count}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${ota_count}" -ne "${expected_count}" ]; then
|
||||
echo "Expected ${expected_count} OTA binaries, found ${ota_count}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Create GitHub release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
FORCE: ${{ inputs.force }}
|
||||
RELEASE_TAG: ${{ needs.prepare.outputs.release-tag }}
|
||||
ESPHOME_VERSION: ${{ needs.prepare.outputs.esphome-version }}
|
||||
RELEASE_NOTES: ${{ needs.prepare.outputs.release-notes }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if gh release view "${RELEASE_TAG}" >/dev/null 2>&1; then
|
||||
if [ "${FORCE}" = "true" ]; then
|
||||
gh release delete "${RELEASE_TAG}" --yes --cleanup-tag
|
||||
else
|
||||
echo "Release ${RELEASE_TAG} already exists." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
gh release create "${RELEASE_TAG}" release-assets/* \
|
||||
--title "ESPHome ${ESPHOME_VERSION} firmware" \
|
||||
--notes "${RELEASE_NOTES}"
|
||||
|
||||
@@ -122,7 +122,7 @@ mdns:
|
||||
|
||||
web_server:
|
||||
port: 80
|
||||
# version: 3
|
||||
version: 3
|
||||
|
||||
network:
|
||||
enable_ipv6: ${ipv6_enable}
|
||||
|
||||
Reference in New Issue
Block a user