Repository navigation
feat(update): optional GitHub token for firmware update checks - #152
Open
mrdarrengriffin wants to merge 1 commit into
Open
mrdarrengriffin wants to merge 1 commit into
mrdarrengriffin wants to merge 1 commit into
Conversation
Firmware update checks call the GitHub REST API anonymously, which allows 60 requests per hour per public IP. That budget is shared by every OpenDisplay device and every other tool on the same network, so a household with many displays runs out and update.install fails with "Could not fetch release metadata: 403, rate limit exceeded". - Options flow: optional "GitHub token" (password field, stored in entry options, never logged, redacted from diagnostics). A token set on any OpenDisplay entry is used for all of them, since the limit is per network. When set, api.github.com requests send "Authorization: Bearer <token>" (5,000 requests per hour). Behaviour without a token is unchanged. - Release metadata responses are cached per URL for an hour and shared by all entries, so N devices on the same firmware repo cost one request per scan instead of N (also at startup). - A 403/429 with x-ratelimit-remaining: 0 now raises a translated HomeAssistantError that names the limit, the reset time (from x-ratelimit-reset) and suggests adding a token; the periodic check logs the same hint instead of a bare "rate limited".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
The firmware update entity talks to the GitHub REST API anonymously (
releases/latestevery 6 h per device,releases/tags/<tag>on install). Anonymous calls are limited to 60 requests per hour per public IP, and that budget is shared by every OpenDisplay device in the house and every other tool on the same network that touches the GitHub API (HACS, other integrations, scripts, browsers on the same NAT).With many displays this runs out. With 18 displays here, every device scans at startup and every 6 h, and
update.installregularly fails with:The error gives no hint about why or what to do, and nothing in the integration lets you use an authenticated request (5,000 per hour).
What changed
entry.options, notdata). It is never logged and is added to the diagnostics redaction list. The rate limit is per network rather than per device, so a token set on any OpenDisplay entry is used for all of them. You don't have to paste it into every device.api.github.comsendAuthorization: Bearer <token>. The asset download (browser_download_url, served from github.com/CDN rather than the API) is unchanged and sends no token. With no token set, behaviour is the same as before.hass.data, with a per-URL lock, and shared by all entries. N devices on the same firmware repo now cost one request per scan (and one at startup) instead of N. Errors are not cached.x-ratelimit-remaining: 0raises a translatedHomeAssistantError(github_rate_limited). It states the limit, the local reset time (fromx-ratelimit-reset) and suggests adding a token. The periodic check logs the same hint as a warning. Other 403s keep the existing handling.strings.jsonandtranslations/en.jsonby hand (option label, description and the new exception). Other languages are left to the translate workflow, andscripts/verify_translations.pypasses.tests/test_update.py,tests/test_options_flow.py):AuthorizationheaderBearerheader and the latest version is still reportedgithub_rate_limitedwith the limit placeholder, never starts the flash and clears progressHow to test
scripts/test(andscripts/test --min-ha) runs the new tests with the rest of the suite.x-ratelimit-limitshould be 5000, or turn on debug logging and watch the update checks succeed.for i in $(seq 61); do curl -s -o /dev/null https://api.github.com/repos/OpenDisplay/Firmware_Silabs/releases/latest; done). Then press Install on an update entity. The error should name the reset time and suggest a token.Notes
ruff checkandruff format --checkare clean.uv.lock. CI should cover it.Screenshots
N/A (one extra field in the existing options form).