Hide the repo Checks tab when no checks exist (reappear on first report) #505
Labels
No labels
actions
bug
cli
duplicate
enhancement
fork
forum
git storage
help wanted
insights
invalid
issues
moderation
oidc
ownership transfer
packages
pr/merge protection rules
projects
pull requests
question
releases
sponsorships
tags
webhooks
wiki
wontfix
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
crueber/walhub#505
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What's requested
Hide the Checks tab on the repo page when the repository has no checks reported, and make the tab reappear automatically with the first reported check. Static diagnosis from code reading — no local reproduction.
tabBadgediscipline, issue #319)./:owner/:name/checks(bookmarks,target_urllinks from statuses on other instances, old links) must remain sane when the tab is hidden.web/src/pages/Checks.jsx, toolbar, href/api#checks-ci) is currently the discoverable pointer for external CI authors; hiding the tab on check-less repos removes it exactly where CI hasn't been wired yet.Evidence
web/src/pages/Repo.jsxTABSarray includes{ id: "checks", … }unconditionally; the<For each={TABS}>renderer (navrepo-tabs) has no per-tab visibility filter (badges render only when count > 0, but tabs themselves always render).web/src/pages/Checks.jsx—Emptyfallback "No checks reported yet" whengetPage().checksis empty; toolbar carries thereporting APIlink.internal/api/summary.gosummaryBodyhas no checks field. The projection precedents to copy are right there in the same handler:CollabCounts(issue #319, open_issues/open_pulls) andForkSummary(issue #424) — both one exact-key probe behind anEnvhook, nil/absent → zero, +0 round trips for non-consumers (law 4: 404s are free).repos/<o>/<r>/checks/index.json(internal/checks/checks.go,IndexKey, created on first report). One exact-key conditional GET on it = "has any checks" (the index is written by every report; the per-sha objects are the backfill truth but the index is the cheap flag).checkframes already ride the one repo collaboration stream (web/src/pages/Checks.jsxuseCollabStream(… ["check"])) and the summary is fetched by the shell — but note the summary is servedno-cachewith an ETag (ccMutable, #381), so a new field must be covered by the ETag or a revalidating client 304s and the tab never reappears (the~d/~m/~c/~v/~fsuffix discipline, lines 164–207).Architecture notes
CollabCounts/ForkInfoininternal/api/env.go): aChecksSummary-style Env hook probingIndexKeyexistence; wire the concrete probe frominternal/checks(the package already owns the key) intocmd/walhub/serve.go, exactly as the other feature packages feed their hooks.summaryBody, e.g.has_checks(bool, orchecks_total intif a count is trivially available from the index projection — flag-only is enough; pick one and note it). Old clients ignore it (14 §14.12).omitemptyvs always-present: follow the #319 discipline (always present, 0/false = none).~k+ version or presence byte) covered by whatever the probe reads. The index is CAS'd, so a version/ETag from the index object is a natural suffix input.TABSrender whensummary.has_checksis false. Consider keeping it a pure helper inweb/src/lib/alongsidetabs.js(headless-testable per the settingsNav convention) so the visibility rule is unit-testable without DOM.internal/checksexposed_test.gopins the discovery list — a new summary field is server-side only and shouldn't touch it, but any route change would; don't add routes.Summary(ctx, id)view is git-only). The tab badge machinery (tabBadge, #319) is client-only and consumes summary fields — this ticket supplies the field it would need.Acceptance criteria
/:owner/:name/checkson a check-less repo still renders (the empty state is a fine landing — tab hiding must not 404 or redirect-bounce), and the active-tab matcher (web/src/lib/tabs.js) keeps handlingchecks/checkpath segments even when the tab is hidden./api#checks-cieven when the tab is hidden; implementer picks the surface and notes it.~-suffix discipline has per-field precedent tests ininternal/api).web/src/lib/).Context pairing: #504 documents that the checks subsystem is fully wired but unused (nothing external reports yet) — this ticket hides the tab until the first check arrives, per the owner ruling. The summary has_checks flag prescribed here must invalidate when the first status is POSTed via the #504 write path so the tab reappears without a reload.
Fix ready for review: #510 (branch fix/issue-505). Summary has_checks + ~k ETag suffix; tab hides when false, reappears live via hidden-state shell stream + check→repo frame mapping; deep-link /checks still renders; header keeps the /api#checks-ci link while hidden.
REVIEW of PR #510 (fix/issue-505, commit
1779177) — verified in scratch worktree /tmp/pr510 (removed afterward); main worktree left clean (only pre-existing untracked .opencode/). No browser used — tests + reasoning only, per instructions. No docker/compose/system-package changes. Live 127.0.0.1:8080 instance untouched (only the smoke test's own GETs ran against it).All 8 acceptance criteria PASS. No fixes needed — nothing pushed.
(1) Probe (+0 trips, exact-key, nil→false): PASS. internal/checks/service.go:539 HasChecks does one exact-key GET on IndexKey, nil→(false,0,false,nil); corrupt/store-error→err and cmd/walhub/collab.go:202-211 fails open to absent (nil/absent→has_checks:false, byte-identical ETag). Budget pinned in internal/checks/summary_test.go (1 GET/0 LIST). +1 GET per summary when wired is off the law-6 budgeted paths (push/sync/checkpoint never call summary) — documented in docs/go/07_api.md §9.1. Law 8 holds: internal/api never imports internal/checks (Env.ChecksSummary hook, CollabCounts shape).
(2) ETag ~k suffix: PASS. internal/api/summary.go:226-232 appends ~k only when checksOK; no collision with ~d/~m/~c/~v/~f/~degraded. Flip 200-not-304 proven in internal/api/summary505_test.go TestSummaryChecksRevalidate (bare→200 with ~k1 on first report, version bump→200 again, current→304).
(3) Helper fail-open: PASS. web/src/lib/tabs.js:80-83 showChecksTab returns true for null/undefined/missing-field (loading, deleted, pre-505 servers); false only on explicit has_checks:false. Matrix unit-tested in web/test/unit/checks-tab-505.test.js.
(4) Deep link: PASS. web/src/index.jsx:115-116 /checks and /checks/:sha routes render unconditionally (empty state is the landing); activeTab in tabs.js untouched — checks/check segments still map while hidden (pinned by test).
(5) Live reappear, no reconnect storm: PASS. web/src/lib/collab.js:70 adds repo:{full} to check frames (#319 invalidate-at-minimum precedent); web/src/pages/Repo.jsx:642-643 hidden-state-only shell stream via boolean createMemo (effect deps flip only on hidden↔shown transitions; full() stable across summary refreshes) with null-full early-out, so check-ful/loading/deleted/pre-505 hold no extra stream. Unmount on flip = single cycle, no storm.
(6) Discoverability: PASS. Checks toolbar /api#checks-ci link untouched (Checks.jsx:162-168); repo-header meta line keeps the same href/spelling exactly while hidden, Show when={!showChecksTab(s())} (Repo.jsx:731-733), retiring on first report. Surface noted in 07 Decisions + 12_web_ui Decisions.
(7) exposed_test untouched: PASS — git diff on internal/checks/exposed_test.go is empty; no new routes.
(8) Stale #396 pin update legitimate: PASS — web/test/unit/fetch-rate-guard.test.js repo:{full} 0→1 is the necessary consequence of the new check→repo frame mapping (stale summary refetches once, like every other mapped key).
Checks: internal/api 95.3% + internal/checks 96.3% (≥95% gate holds); go test -race green on both; gofmt clean; go vet clean; node --test 1131 total / 1130 pass / 1 fail = pre-existing smoke.test.js live-server subtest, confirmed failing identically on pristine main (env: something answers /healthz on 127.0.0.1:8080 but 403s /setup); vite build green (chunk-size warning only, pre-existing); go build ./... green; internal/e2e green (56.8s). No new deps (go.mod/package.json untouched). Docs accurate: 07_api §9.1 + suffix lists + Decisions, 06 route table, 12_web_ui Decisions (law 12 satisfied).
Edge noted, not blocking: repos whose index compacted past every sha read has_checks:false (len(SHAs)==0) — consistent with the table page, which reads the same index projection; staleness envelope is stated in the HasChecks doc comment.
MERGE RECOMMENDATION: ready to merge (squash per repo convention; do NOT merge without a second human glance at nothing — no open items).
Fixed by PR #510 (review clean — all 8 criteria pass, flip economics proven, live reappear sound), merged. Closing.
crueber referenced this issue2026-09-14 13:43:44 +00:00