Never show a fabricated GitHub star count - #277
Draft
evnchn wants to merge 1 commit into
Draft
Conversation
Seed the count as an empty string instead of '0' and hide the tile while the count is unknown, so a failed fetch renders nothing rather than a confident but wrong number. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NYtshdRxziWhERLt5AupKv
evnchn
force-pushed
the
fix/github-stars-no-false-zero
branch
from
August 1, 2026 02:54
02ca2fa to
065d9e9
Compare
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.
Verdict: nicegui.io stops rendering a fabricated
0 GitHub Stars. An unknown count now hides the stat tile instead of showing a plausible-looking wrong number, and a failed fetch retries in a minute (backing off) rather than waiting out the full hour. Fixes zauberzeug#6211. Draft — the maintainers picked no fix direction yet, so this implements directions 1 + 2 from the issue and leaves direction 3 (auth token / shared cache) alone.Motivation
website/github_stars.pyhad three compounding properties, reported in zauberzeug#6211 with 58/58 region-correlated samples against production:'0';app.storage.general) is per-machine, so a healthy Fly machine's value never reaches a failing one;0.Result: everyone routed to the Tokyo machine saw a confident
0, while San Jose served16k+.Implementation
GitHubStars.stringseeds to''; the sponsors stat tile binds its visibility to the value being non-empty, so an unknown count hides the tile rather than showing a wrong number. The nav badge's label simply renders empty next to the GitHub icon.Empirical before/after — the real component, fetch forced to fail
A throwaway script served the real
sponsors_sectionwithgithub_stars.httpxswapped for a client that raisesConnectError, with no.nicegui/cache present (a cold machine whose fetch fails — the production condition). The served payload was curled and inspected.Before (upstream
main): the tile is visible and renders a bare0.After (this branch): the tile carries
hiddenand the label is empty.Server log confirms the failure path ran:
failed to fetch GitHub star count.Note: an earlier run of the same probe accidentally proved the happy path too — the real hourly timer fired at startup, fetched successfully, and rendered
16k+with the tile visible.Regression tests — confirmed to fail without the fix
tests/test_website_github_stars.py, 3 tests. With the source reverted to upstream behaviour but the new symbols kept (so the tests can still be collected), all three fail for the right reasons:With the fix applied:
Wider slice, checking the new module-level import does not leak into neighbours (
145 passedcoverstest_user_simulation,test_user_simulation_context,test_binding,test_storage,test_timer; the74 passedrun adds this file alongsidetest_user_simulationand is clean, where importing thewebsitepackage instead produced an ERROR — see the next fold):Linters on the touched files:
ruffclean,mypyclean,pylint10.00/10. Pre-commit hooks passed on commit.Why the test loads the module by path instead of importing it
import website.github_starsrunswebsite/__init__.py, which eagerly imports the documentation tree;doc.auto_executepre-renders each page inside adummy_client(), and each of those constructs anOutboxwhoseloop()coroutine is deferred viaapp.on_startup.client.delete()does not close it, so when the test plugin'snicegui_reset_globalscallsapp.reset()those ~26 coroutines are dropped unawaited. Underfilterwarnings = ['error']pytest surfaces them as anExceptionGroupat the setup of whichever test runs next — measured: importing the package from a test madetests/test_user_simulation.py::test_module_import_isolation_first_testERROR with 27 sub-exceptions, in a run that is otherwise green.Rather than widen this PR into the library, the test loads
website/github_stars.pydirectly withimportlib(the module has no relative imports) and temporarily swapsbackground_tasks.create_or_deferso its own hourly timer is closed instead of deferred — otherwise the suite would fire a real request atapi.github.com.Flagging the underlying leak as a separate finding, not fixed here: any future test that imports anything under
website/will hit it. The fix belongs inapp.reset()/ the deferred-task path (close pending coroutines instead of dropping them), with its own test.Second-opinion review (Codex, gpt-5.2-codex — different lineage)
Prompted adversarially ("assume this diff is broken and try to refute it"), pointed at the specific risks: timer-interval mutation from inside the timer's own callback, retry rate vs. GitHub's limit, the unbound nav-badge label, the dataclass default change, the test preamble, and CI portability.
Verdict: no BLOCKER findings, one SHOULD-FIX, 8/10 shippable.
Acted on — the flat 60 s retry became the doubling ladder described above, with a test asserting the ladder and the resulting request rate.
Its other conclusions, verified against the source:
Caveat on this evidence: Codex reviewed by reading, not running — its environment lacked the project dependencies.
Deliberately not done
NICEGUI_REDIS_URL, or bake the count in at deploy time) — that is a deployment/infrastructure decision for the maintainers, not a code change, and directions 1 + 2 fix the user-visible symptom regardless of why the fetch fails.fly logson thenrtmachine grepped forfailed to fetch GitHub star count. This PR is deliberately agnostic to the cause.website/header.py:151) — an empty label beside the GitHub icon already degrades acceptably, and hiding it would change the header's layout.website-package import leak described above — real, but a library-level change that does not belong in a website bugfix.Progress