Skip to content

Add repository brand icon endpoint#5388

Open
Niek wants to merge 3 commits into
hacs:mainfrom
Niek:repository-brand-icons
Open

Add repository brand icon endpoint#5388
Niek wants to merge 3 commits into
hacs:mainfrom
Niek:repository-brand-icons

Conversation

@Niek

@Niek Niek commented Jul 15, 2026

Copy link
Copy Markdown

Proposed change

Adds an authenticated endpoint that serves brand icons for repositories HACS knows about:

GET /api/hacs/repository/{repository_id}/icon.png
GET /api/hacs/repository/{repository_id}/dark_icon.png

Since Home Assistant 2026.3, custom integrations ship brand images in custom_components/<domain>/brand/, and home-assistant/brands no longer accepts images for custom integrations (announcement). The HACS dashboard still builds icon URLs against the brands CDN, so custom integrations that are not grandfathered into the CDN show a placeholder (#5171, #5223, #5179).

The core brands proxy only covers installed integrations, which was the main concern raised against switching the frontend to it in hacs/frontend#937. This implements the HACS repository endpoint design discussed there:

  • Requests require either normal Home Assistant authentication or the rotating brands access token exposed by brands/access_token.
  • Downloaded integrations are served from their local brand folder, so the icon matches the downloaded version.
  • Integrations that are not downloaded are fetched from repository content on raw.githubusercontent.com. Both standard repository layouts and content_in_root are supported.
  • Release-based caches are keyed by version. Repositories without releases use last_commit as their cache identity, so a new commit refreshes the icon.
  • Confirmed 404s, invalid PNGs, and oversized icons receive a seven-day negative cache marker. Network failures and other transient GitHub responses are not negatively cached and return a non-cacheable fallback, so the next request retries.
  • Remote responses are read in chunks and stopped once they exceed 1 MiB. Local, cached, and remote content all receive the same PNG magic-byte and size validation.
  • dark_icon.png falls back to icon.png while preserving the access token.
  • The registered view resolves the current HACS instance per request, so config-entry reloads do not leave it attached to stale state.

Repositories without a usable icon ultimately redirect to the brands CDN, preserving grandfathered images and its placeholder behavior. The update entity picture is intentionally unchanged; #5228 / #5339 cover that separately.

Frontend companion PR: hacs/frontend#945.

Release follow-up

The integration currently pins frontend release 20250128065759 in scripts/install/frontend. To ship this end to end:

  1. Merge both PRs.
  2. Publish a new hacs/frontend release containing Use the HACS repository icon endpoint for dashboard icons frontend#945.
  3. Bump FRONTEND_VERSION in hacs/integration to that release.
  4. Publish the integration release.

The pin cannot be updated in this PR until that frontend release exists.

Related issues and PRs: fixes #5171, #5179, and #5223 together with the frontend PR; alternative to hacs/frontend#937 and hacs/frontend#929, which only cover installed integrations.

Checklist

  • Regression tests cover authentication, local and remote icons, content_in_root, branch cache refresh, transient failures, streamed size limits, dark fallback, and config-entry reloads.
  • Full test suite passes: 443 tests.
  • Ruff checks pass.

Serve brand icons for integrations from HACS itself, now that custom
integrations ship brand images in the repository and
home-assistant/brands no longer accepts them:

- Downloaded integrations are served from the local brand folder.
- Other integrations are fetched from the repository content on GitHub
  and cached on disk, keyed by the version they were fetched for.
- Repositories without a brand icon are redirected to the brands CDN.

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 new unauthenticated HTTP view in the HACS integration that serves repository brand icons (icon.png / dark_icon.png) to address missing icons for custom integrations since the HA 2026.3 brands changes. It serves icons from the local custom_components/<domain>/brand/ folder for downloaded integrations, otherwise fetches from raw.githubusercontent.com and caches results (including negative caching), with CDN/placeholder fallback behavior.

Changes:

  • Introduces HacsRepositoryIconView with local/remote icon serving, on-disk caching, and redirect fallbacks.
  • Registers the new view during HACS startup.
  • Adds a new test suite for the view plus API-usage snapshots.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

File Description
custom_components/hacs/brands.py New icon-serving endpoint with local/remote fetch logic and caching.
custom_components/hacs/__init__.py Registers the new icon view at startup.
tests/test_brands.py Adds tests covering local serve, remote fetch/cache, redirects, and validation cases.
tests/snapshots/api-usage/tests/test_brandstest-*.json Adds API usage snapshots for the new tests.

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

Comment thread custom_components/hacs/brands.py Outdated
Comment thread custom_components/hacs/brands.py
Comment thread custom_components/hacs/brands.py Outdated
Niek added 2 commits July 15, 2026 13:30
…ling

Address review feedback:
- Local and cached icons go through the same PNG magic-byte and size
  validation as downloaded ones.
- The cache filename now percent-encodes the ref so distinct refs can
  not collide.
- async_download_file already returns None on failure, so the
  try/except around it was dead code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HACS dashboard doesn't show local brand icons (HA 2026.3+)

2 participants