diff --git a/.github/workflows/beta.yml b/.github/workflows/beta.yml index 3cf64ab5..39bc721f 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 b4f824c2..2dc6ad7c 100644 --- a/.github/workflows/release-assets.yml +++ b/.github/workflows/release-assets.yml @@ -910,3 +910,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 d6846fb7..1a513276 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