fix: handle repository filtering on Overview scores IN-1253 - #2127
Conversation
…kdown (IN-1253) Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
Comments explaining the repo-filtering behavior repeated inline ticket references and narrated project history instead of just the invariant a maintainer needs. Kept the WHY, dropped the IN-1253/IN-1212 tags and git-history callouts. Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
…ingle-repo/group routes IN-1253 Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
…ject IN-1253 Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
There was a problem hiding this comment.
Pull request overview
Adds repository-scoped Overview health data and empty states.
Changes:
- Threads selected repositories through Overview queries.
- Adds filtered Lifecycle and breakdown API paths.
- Introduces archived/excluded selection states.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
health-score-v2.get.ts |
Fetches repository-scoped Lifecycle data. |
health-score-breakdown.get.ts |
Fetches repository-scoped breakdown signals. |
trust-score.ts |
Defines filter empty-state copy. |
overview.vue |
Connects repository scope to Overview sections. |
project.store.ts |
Derives archival and exclusion states. |
overview.api.service.ts |
Adds repositories to requests and cache keys. |
trust-score-v2.vue |
Renders filtered Health Score states. |
health-breakdown-section.vue |
Handles unavailable filtered breakdowns. |
Suppressed comments (1)
frontend/server/api/project/[slug]/overview/health-score-v2.get.ts:34
- These three values feed the Health breakdown category cards, so every filtered selection now shows “No data” and unavailable-category copy even when
repo_health_score_v2_breakdownreturned valid recomputed signals. The upstream pipe only returns signal columns, not these category totals. Please derive/populate the three scoped category scores or update the response/component contract so the recomputed breakdown is displayed accurately.
maintainerHealthScoreV2: null,
securitySupplyChainScoreV2: null,
developmentActivityScoreV2: null,
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| { slug, repos }, | ||
| ); | ||
| return { | ||
| healthScoreV2: null, |
Selecting a single repo from the search list navigated to the repo route but never emitted close, so the picker stayed open over the transitioning page — the modal only closed for the repository-group and all-repositories paths, which do call close/set isModalOpen. Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
frontend/app/components/modules/project/views/overview.vue:102
reposis populated on the dedicated/repository/[name]and/repository-group/[groupSlug]routes too. Any non-empty value makeshealth-score-v2.get.tsreturnnullfor the total, whileisRepoFilterActiveis false on those routes, so the normal score UI renders an unavailable score instead of the route's scoped total. Please distinguish the top-level repo-filter mode from dedicated route scope and fetch the scoped total for dedicated routes.
repos: selectedRepositories.value.length ? selectedReposValues.value : undefined,
frontend/server/api/project/[slug]/overview/health-score-v2.get.ts:34
- For every filtered selection these category totals are forced to
null.health-breakdown-section.vueuses them for its three category cards, while the new breakdown pipe returns only per-signal fields, so each card displays “No data” and a zero progress bar even when its filtered signal rows contain data. Return or derive the filtered category totals before rendering the breakdown.
maintainerHealthScoreV2: null,
securitySupplyChainScoreV2: null,
developmentActivityScoreV2: null,
Reading useRoute() inside the Pinia project store's setup captured a disconnected route object that stopped tracking client-side navigation, so selectedRepositories never updated after the first render. Fixed by reading router.currentRoute (the ref vue-router mutates directly). The overview page component was also never remounted when navigating between /project/[slug] and /project/[slug]/repository/[name], since NuxtPage has no key by default and both routes render the same nested component. Keying NuxtPage on the full route path forces a fresh instance per repo selection, so the health score queries refetch immediately instead of lagging one selection behind. Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
frontend/server/api/project/[slug]/overview/health-score-v2.get.ts:27
- The
reposbranch also runs on dedicated/repository/[name]and/repository-group/[groupSlug]pages:overview.vuesendsselectedReposValueswhenever that scope is nonempty. Returning a null total makes those pages render Health Score as unavailable (and can trigger the low-signal warning), rather than showing the scoped total promised in the PR description. Please distinguish top-level filter requests from dedicated-route requests and return the scoped aggregate for the latter.
healthScoreV2: null,
| maintainerHealthScoreV2: null, | ||
| securitySupplyChainScoreV2: null, | ||
| developmentActivityScoreV2: null, |
…ests IN-1253 Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
…ing IN-1253 Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
| developmentActivityScoreV2: number | null; | ||
| signals: HealthBreakdownResults | null; | ||
| selectedReposAllArchivedOrExcluded: boolean; | ||
| isRepoSelected: boolean; |
| impactScore: null, | ||
| impactLabel: null, |
| :development-activity-score-v2="healthScoreV2Data?.developmentActivityScoreV2 ?? null" | ||
| :status="healthScoreV2Status" | ||
| :is-repo-selected="selectedRepositories.length > 0" | ||
| :is-repo-selected="isRepoFilterActive" |
…cted IN-1253 Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.
Suppressed comments (6)
Previously missed (3) — in code that hasn't changed since the last review.
frontend/server/api/project/[slug]/overview/health-score-v2.get.ts:40
- This same live aggregation pipe is requested again by
fetchHealthScoreBreakdownwhenever the Overview starts its two queries. That duplicates the repository-scoped breakdown work on every filter change. Return the total/category fields and signal breakdown from one shared request, or otherwise share/cache the result between these endpoints.
fetchFromTinybird<RepoHealthScoreV2CategoryTotals[]>(
'/v0/pipes/repo_health_score_v2_breakdown.json',
{ slug, repos },
),
frontend/server/api/project/[slug]/overview/health-score-v2.get.ts:35
- The selector has no selection limit, so this unbounded repository-URL array can make both Nuxt and Tinybird GET URLs exceed request-line limits for large projects. The repository already provides
postToTinybirdspecifically for large array parameters (server/data/tinybird/tinybird.ts:238-247). Use a POST/body contract end-to-end, or enforce a safe maximum selection size.
fetchFromTinybird<{ lifecycleLabel: string | null }[]>('/v0/pipes/repo_lifecycle_v2.json', {
slug,
repos,
frontend/server/api/project/[slug]/overview/health-score-breakdown.get.ts:24
- This endpoint also forwards an unbounded list of repository URLs through GET query strings. Large valid selections can exceed URL/request-line limits before reaching Tinybird; use a POST body through both application and Tinybird hops, or validate a bounded list size.
const res = await fetchFromTinybird<HealthBreakdownResults[]>(
'/v0/pipes/repo_health_score_v2_breakdown.json',
{ slug, repos },
frontend/server/api/project/[slug]/overview/health-score-v2.get.ts:48
- The PR says repository filtering is threaded through Impact, but scoped requests explicitly discard both Impact values. When the currently hidden Impact UI is re-enabled, repository and group routes will show it as unavailable rather than scoped. Either implement the scoped Impact data path or update the PR scope and track Impact as follow-up work.
impactScore: null,
impactLabel: null,
frontend/app/components/modules/project/components/overview/health-breakdown-section.vue:16
- This condition still exposes a scoped Health Score total for a one-repository
?repos=...filter, becauseisMultipleReposSelectedis false. The subset state requires the total to be hidden for every top-level filter selection; useisRepoSelectedinstead. Dedicated repository and group routes keep the chip because that prop is false there.
v-if="props.healthScoreV2 !== null && !props.isMultipleReposSelected"
frontend/app/components/modules/project/views/overview.vue:21
isRepoFilterActiveis false on dedicated single-repository routes, but this prop also controls whether the child renders the repository active-contributors badge. Those routes now render the project Health Score badge instead. Pass a separate “repository selected” signal to the share badge while retaining this filter-only signal for hiding the total.
:is-repo-selected="isRepoFilterActive"
Summary
The Overview page's repo filter didn't affect Health Score, Health Score breakdown, Lifecycle, or Impact — they were always project-wide. This threads the selected repos through to those sections with three states:
Select "All repositories" in order to get the aggregated Health Score; breakdown and Lifecycle recomputed live for just the selection via the newrepo_health_score_v2_breakdown/repo_lifecycle_v2pipes.Health Score Unavailableempty state (not the "select all" copy, since selecting all wouldn't fix this); Lifecycle still computed for the selection./repository/[name]) and repo-group (/repository-group/[slug]) routes always show their own scoped total — they never hit the "select all" empty state, since there's no "select all" control on those routes.Depends on linuxfoundation/crowd.dev#4528 (already deployed to production) for the two new pipes.
Test plan
pnpm lint/pnpm tsc-check/pnpm testall green/project/k8spagecomponents/modules/project/components/shared/header.vue, last touched by IN-1001, untouched by this PR) causes unreliable client-side navigation — including stale data shown after navigating to the single-repo/group routes via the dropdown, and a mobile-viewport state desync. Confirmed viagit diffthat this PR never touches that file, and via code review that this PR's own reactive data-fetching wiring is correct end-to-end. Recommend filing as a separate, standalone bug — see PR discussion for full repro details.