Skip to content

Sync component catalog on ESPHome release #109

Sync component catalog on ESPHome release

Sync component catalog on ESPHome release #109

name: Sync component catalog on ESPHome release
# Dispatched by esphome/version-notifier right after an ESPHome release. Waits
# for the new schema to publish, then dispatches the component catalog sync so
# it refreshes immediately instead of waiting for the nightly. The device/board
# catalog is sourced from devices.esphome.io plus curated manifests, so a
# release doesn't change it; it stays on its own schedule. Nightly dev builds
# are dispatched too but skipped: they publish no schema bundle.
on:
workflow_dispatch:
inputs:
version:
description: "ESPHome release version (e.g. 2026.6.0 or 2026.6.0b1)"
required: true
type: string
permissions:
actions: write # createWorkflowDispatch on this repo's component sync
concurrency:
group: sync-on-esphome-release-${{ inputs.version }}
cancel-in-progress: false
jobs:
dispatch:
# Expressions can't regex-match, so this job-level check is just the cheap
# denylist that spares a nightly runner allocation for dev builds; the gate
# step below is the strict allowlist for every other dispatch input.
if: ${{ !contains(inputs.version, 'dev') }}
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Check the version is a stable or beta release
id: gate
# Nightly dev builds (2026.8.0-dev20260712) publish no schema bundle,
# so waiting for one just burns 20 minutes and fails; the downstream
# sync rejects them with this same pattern anyway.
env:
VERSION: ${{ inputs.version }}
run: |
set -euo pipefail
if printf '%s' "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(b[0-9]+)?$'; then
echo "sync=true" >> "$GITHUB_OUTPUT"
else
echo "::notice::Skipping catalog sync for '$VERSION' - not a stable/beta release"
echo "sync=false" >> "$GITHUB_OUTPUT"
fi
- name: Wait for the schema bundle to publish
if: steps.gate.outputs.sync == 'true'
# The schema build (esphome-schema) and this run fan out from the same
# release event, so the bundle can lag the release by a few minutes. The
# component sync consumes it, so wait before kicking that off. ``version``
# comes through ``env`` rather than expression-interpolation into the
# shell so a crafted input can't inject command substitution. The esphome
# wheel the component sync installs isn't gated here; if it lags the
# schema the sync fails and the nightly retries.
env:
VERSION: ${{ inputs.version }}
run: |
set -euo pipefail
url="https://schema.esphome.io/${VERSION}/schema.zip"
for attempt in $(seq 1 40); do
if curl -fsSL --connect-timeout 10 --max-time 30 -A "device-builder-release-sync" --head -o /dev/null "$url"; then
echo "Schema ready: $url"
exit 0
fi
echo "Schema not published yet (attempt $attempt); waiting 30s"
sleep 30
done
echo "::error::Schema $url did not publish within 20 minutes"
exit 1
- name: Dispatch the component catalog sync
if: steps.gate.outputs.sync == 'true'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
VERSION: ${{ inputs.version }}
with:
script: |
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: "sync-component-catalog.yml",
ref: "main",
inputs: { version: process.env.VERSION },
});