Skip to content

Track custom integrations from the HACS default list - #1128

Open
clintongormley wants to merge 1 commit into
home-assistant:devfrom
clintongormley:track-hacs-default-custom-integrations
Open

Track custom integrations from the HACS default list#1128
clintongormley wants to merge 1 commit into
home-assistant:devfrom
clintongormley:track-hacs-default-custom-integrations

Conversation

@clintongormley

@clintongormley clintongormley commented Aug 4, 2026

Copy link
Copy Markdown

Proposed change

processQueue only counts a reported custom integration if its domain is in brands' domains.json, and since HA 2026.3.0 brands no longer accepts new custom_integrations/ entries (Brands Proxy API announcement). A custom integration created after the freeze can therefore never appear in the public stats, however many installations report it.

This adds the HACS default repository list as a second source of known domains — 901 domains that brands does not have today — and keeps working for anything added to HACS from now on.

The list comes from https://data-v2.hacs.xyz/integration/data.json (the same host HACS itself uses), is reduced to a plain list of domains, and is cached in KV. It refreshes at most once a day; a failed refresh reuses the cached list and raises a Sentry warning, so an outage of a third-party source can't stall queue processing. With nothing cached it falls back to brands alone.

Matching against a curated list rather than accepting any reported domain keeps the property the brands filter was there for: only domains from a publicly reviewable list are counted, so custom_integrations.json can't be filled with arbitrary keys.

Notes for reviewers

  • worker/src/utils/fetch-json.ts is new — three sources now share the fetch/check/parse shape, so it is extracted. That also surfaced the !versionResponse.ok branch throwing "Could not get domain list from brands", now corrected.
  • This does not help integrations distributed outside the HACS default list, including the one in How can custom integrations registered after the brands freeze get tracked? #1094. It fixes the large, tractable slice; anything further needs a decision on what the source of truth should be post-freeze.

Type of change

  • Bugfix (non-breaking change which fixes an issue)

Additional information

Checklist

  • The code change is tested and works locally (script/worker_test, script/worker_build).
  • There is no commented out code in this PR.

🤖 Generated with Claude Code

@clintongormley
clintongormley marked this pull request as draft August 4, 2026 13:43
brands no longer accepts new custom_integrations entries since HA 2026.3.0,
so any custom integration created after the freeze can never appear in the
public stats: reported domains that are not in brands' domains.json are
dropped when the queue is processed.

Use the HACS default repository list as an additional source of known
domains, so integrations distributed through HACS are counted even when
they have no brands entry.

The list is reduced to the domains we need and cached in KV, refreshed at
most once a day. A failed refresh falls back to the cached list, so an
outage of a third-party source can never stall queue processing.

Fixes home-assistant#1094

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@mholzi

mholzi commented Aug 18, 2026

Copy link
Copy Markdown

Another data point in favour of this: quizify (mholzi/quizify) is a custom integration that is invisible today and would be counted by this PR.

  • Not in brands at all — absent from both core and custom in domains.json (1504 / 4245 entries today), because it was created after the freeze and used the Brands Proxy API (custom_components/quizify/brand/) instead.
  • Already in the source this PR reads — https://data-v2.hacs.xyz/integration/data.json lists it as mholzi/quizify with domain: quizify (accepted into the HACS default list on 2026-08-01).

I verified the drop happens exactly where you describe, on an instance that does report: analytics preferences are {"base": true, "diagnostics": true, "usage": true, "statistics": true}, the Quizify config entry is loaded with source: user and disabled_by: null, so it passes _async_should_report_integration() and is sent in custom_integrations — and it still never appears in the public JSON.

A cross-check on the current custom_integrations.json matches the theory precisely: all 4210 listed domains are present in brands' domains.json, and 0 are not. The brands set is the whole gate.

Happy to test against a preview deployment if that is useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants