diff --git a/.github/workflows/beta.yml b/.github/workflows/beta.yml index 3cf64ab50..39bc721f4 100644 --- a/.github/workflows/beta.yml +++ b/.github/workflows/beta.yml @@ -611,3 +611,31 @@ jobs: --tag "${compatibility}:beta" "${canonical_version}@${expected}" test "$(scripts/inspect-image-digest.sh "${compatibility}:beta")" = "${expected}" done + + addon: + name: notify the Home Assistant app repository + runs-on: ubuntu-latest + needs: [tag, release] + # srcfl/home-assistant-addons follows every release on its own hourly + # sync; this dispatch only makes its next check immediate. It reads the + # GitHub release and the registry rather than this payload, and a missing + # secret is a notice, never a failed release. + if: ${{ github.repository == 'srcfl/ftw' }} + steps: + - name: Dispatch ftw-release to srcfl/home-assistant-addons + env: + GH_TOKEN: ${{ secrets.HA_ADDON_DISPATCH_TOKEN }} + TAG: ${{ needs.tag.outputs.version }} + run: | + set -euo pipefail + if [ -z "${GH_TOKEN:-}" ]; then + echo "::notice::HA_ADDON_DISPATCH_TOKEN is not set; srcfl/home-assistant-addons picks up ${TAG} on its hourly sync." + exit 0 + fi + gh api repos/srcfl/home-assistant-addons/dispatches \ + --method POST \ + -f event_type=ftw-release \ + -f "client_payload[channel]=beta" \ + -f "client_payload[tag]=${TAG}" \ + -f "client_payload[commit]=${GITHUB_SHA}" + echo "Dispatched ftw-release for ${TAG} (beta)." diff --git a/.github/workflows/release-assets.yml b/.github/workflows/release-assets.yml index 15daa91d5..4d132e924 100644 --- a/.github/workflows/release-assets.yml +++ b/.github/workflows/release-assets.yml @@ -897,3 +897,32 @@ jobs: -H "Content-Type: application/json" \ -d "${PAYLOAD}" \ "${DISCORD_WEBHOOK}" + + addon: + name: notify the Home Assistant app repository + runs-on: ubuntu-latest + needs: [meta, publish] + # Same contract as the beta workflow: srcfl/home-assistant-addons verifies + # the stable release against ftw-promotion-receipt.json and the registry; + # this event only shortens the wait for its hourly sync. + if: ${{ github.repository == 'srcfl/ftw' }} + steps: + - name: Dispatch ftw-release to srcfl/home-assistant-addons + env: + GH_TOKEN: ${{ secrets.HA_ADDON_DISPATCH_TOKEN }} + TAG: ${{ needs.meta.outputs.tag }} + SOURCE_BETA: ${{ needs.meta.outputs.source_beta }} + run: | + set -euo pipefail + if [ -z "${GH_TOKEN:-}" ]; then + echo "::notice::HA_ADDON_DISPATCH_TOKEN is not set; srcfl/home-assistant-addons picks up ${TAG} on its hourly sync." + exit 0 + fi + gh api repos/srcfl/home-assistant-addons/dispatches \ + --method POST \ + -f event_type=ftw-release \ + -f "client_payload[channel]=stable" \ + -f "client_payload[tag]=${TAG}" \ + -f "client_payload[source_beta]=${SOURCE_BETA}" \ + -f "client_payload[commit]=${GITHUB_SHA}" + echo "Dispatched ftw-release for ${TAG} (stable, from ${SOURCE_BETA})." diff --git a/AGENTS.md b/AGENTS.md index d6846fb78..1a5132763 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -248,6 +248,15 @@ cleanup, which is accepted; any other unexpected cleanup result fails the check. If the write check fails, stop, repair package access or rotate the one dedicated secret, then rerun the same immutable version. Do not mint another beta tag to work around an access failure. +The Home Assistant app repository, `srcfl/home-assistant-addons`, follows +every release on its own. `beta.yml` and `release-assets.yml` end by sending +it a `repository_dispatch` of type `ftw-release`, authenticated with the +secret `HA_ADDON_DISPATCH_TOKEN`: a fine-grained token with *Contents: read +and write* on that repository only. Without the secret the step logs a notice +and the app repository picks the release up on its hourly sync. The dispatch +never blocks a release, and the app repository verifies the release against +its digest receipt and the registry rather than trusting the payload. + `CLAUDE.md` imports this file, so these rules apply to Claude and Codex alike. ## Cursor Cloud specific instructions