Skip to content

Use local brand icons for update entities#5249

Closed
gielk wants to merge 1 commit into
hacs:mainfrom
gielk:use-brands-proxy-for-update-icons
Closed

Use local brand icons for update entities#5249
gielk wants to merge 1 commit into
hacs:mainfrom
gielk:use-brands-proxy-for-update-icons

Conversation

@gielk

@gielk gielk commented Apr 30, 2026

Copy link
Copy Markdown

Summary

  • Add a small HACS brand icon endpoint for installed integration repositories.
  • Point integration update entity pictures at that endpoint instead of the legacy Brands CDN URL.
  • Serve local brand/icon.png when present and redirect to the existing Brands CDN fallback when it is not.

Motivation

Home Assistant Brands no longer accepts new brand icons for custom integrations since the 2026.3 local branding changes. HACS validation already accepts local custom_components/<domain>/brand/icon.png assets, but update entities still hardcode https://brands.home-assistant.io/_/{domain}/icon.png. That means HACS update cards can show the placeholder icon for valid custom integrations that ship local brand assets.

I first considered the Home Assistant Brands Proxy API, but this keeps HACS compatible with older supported Home Assistant versions while still allowing installed local brand assets to show in the update entity.

Tests

  • .venv313/bin/python -m ruff check custom_components/hacs/brands.py custom_components/hacs/const.py custom_components/hacs/frontend.py custom_components/hacs/update.py tests/test_brands.py
  • .venv313/bin/python -m pytest tests/test_brands.py tests/test_update.py tests/test_switch.py -q

Copilot AI review requested due to automatic review settings April 30, 2026 14:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a local HACS HTTP endpoint for serving installed integration brand icons and updates HACS update entities to use that local endpoint (with a redirect fallback to the legacy Home Assistant Brands CDN), so update cards can display local custom_components/<domain>/brand/icon.png assets.

Changes:

  • Add HacsBrandIconView at /api/hacs/brands/{domain}/icon.png to serve local brand/icon.png for installed integration repositories, otherwise redirect to the Brands CDN.
  • Update update-entity entity_picture to point to the new local endpoint.
  • Add unit tests for the view and update snapshot expectations for entity_picture.

Reviewed changes

Copilot reviewed 44 out of 44 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
custom_components/hacs/brands.py New HTTP view that serves local brand icons with a CDN redirect fallback.
custom_components/hacs/const.py Adds constants for the local brand icon URL and CDN fallback URL.
custom_components/hacs/frontend.py Registers the new brand icon HTTP view during frontend setup.
custom_components/hacs/update.py Switches update entity entity_picture from CDN URL to the local endpoint.
tests/test_brands.py Adds unit tests covering local serving, CDN fallback redirect, and invalid-domain handling.
tests/snapshots/test_integration_setup.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/theme-basic/test_update_repository_websocket.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/theme-basic/test_update_repository_entity.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/theme-basic/test_remove_repository_pre.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/theme-basic/test_remove_repository_post.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/theme-basic/test_download_repository.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/theme-basic/test_discard_invalid_repo_data.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/template-basic/test_update_repository_websocket.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/template-basic/test_update_repository_entity.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/template-basic/test_remove_repository_pre.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/template-basic/test_remove_repository_post.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/template-basic/test_download_repository.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/template-basic/test_discard_invalid_repo_data.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/python_script-basic/test_update_repository_websocket.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/python_script-basic/test_update_repository_entity.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/python_script-basic/test_remove_repository_pre.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/python_script-basic/test_remove_repository_post.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/python_script-basic/test_download_repository.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/python_script-basic/test_discard_invalid_repo_data.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/plugin-basic/test_update_repository_websocket.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/plugin-basic/test_update_repository_entity.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/plugin-basic/test_remove_repository_pre.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/plugin-basic/test_remove_repository_post.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/plugin-basic/test_download_repository.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/plugin-basic/test_discard_invalid_repo_data.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/integration-basic/test_update_repository_websocket.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/integration-basic/test_update_repository_entity.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/integration-basic/test_update_entity_state.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/integration-basic/test_switch/entity_states.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/integration-basic/test_remove_repository_pre.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/integration-basic/test_remove_repository_post.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/integration-basic/test_download_repository.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/integration-basic/test_discard_invalid_repo_data.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/appdaemon-basic/test_update_repository_websocket.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/appdaemon-basic/test_update_repository_entity.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/appdaemon-basic/test_remove_repository_pre.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/appdaemon-basic/test_remove_repository_post.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/appdaemon-basic/test_download_repository.json Updates snapshot entity_picture to the new local endpoint.
tests/snapshots/hacs-test-org/appdaemon-basic/test_discard_invalid_repo_data.json Updates snapshot entity_picture to the new local endpoint.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


name = "api:hacs:brand_icon"
url = BRAND_ICON_URL
requires_auth = False
Comment on lines +22 to +26
if not path.is_file():
return None
return path.read_bytes()


@gielk

gielk commented Apr 30, 2026

Copy link
Copy Markdown
Author

Closing this as a duplicate after finding the existing issue/PR chain for the same HA 2026.3 brands-proxy migration: #5223 and #5228. The Asmoke Cloud case is the same symptom: local custom integration brand assets are present, but the HACS-created update entity still points at the legacy Brands CDN placeholder.

@gielk gielk closed this Apr 30, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators May 1, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants