Skip to content

fix: handle repository filtering on Overview scores IN-1253 - #2127

Merged
gaspergrom merged 11 commits into
mainfrom
feat/IN-1253
Aug 31, 2026
Merged

fix: handle repository filtering on Overview scores IN-1253#2127
gaspergrom merged 11 commits into
mainfrom
feat/IN-1253

Conversation

@gaspergrom

Copy link
Copy Markdown
Collaborator

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:

  • All repos (default): Health Score total, breakdown, Lifecycle, and Impact all aggregated project-wide (unchanged).
  • Subset selected (mixed archived+active allowed): Health Score total hidden with Select "All repositories" in order to get the aggregated Health Score; breakdown and Lifecycle recomputed live for just the selection via the new repo_health_score_v2_breakdown/repo_lifecycle_v2 pipes.
  • Selection is entirely archived/excluded repos: distinct Health Score Unavailable empty state (not the "select all" copy, since selecting all wouldn't fix this); Lifecycle still computed for the selection.
  • Dedicated single-repo (/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 test all green
  • QA loop (crowd-insights-qa): all 5 acceptance criteria PASS against the live /project/k8s page
  • Multi-persona QA pass: confirmed all 3 states, mixed-selection behavior, and cross-project pipe scoping (foreign-repo leak test) correct on fresh page loads
  • Known follow-up, not fixed in this PR: a pre-existing bug in the repo-filter dropdown/header component (components/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 via git diff that 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.

…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>
Copilot AI balanced review requested due to automatic review settings August 28, 2026 12:47

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

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_breakdown returned 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>
Copilot AI review requested due to automatic review settings August 28, 2026 13:06

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

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

  • repos is populated on the dedicated /repository/[name] and /repository-group/[groupSlug] routes too. Any non-empty value makes health-score-v2.get.ts return null for the total, while isRepoFilterActive is 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.vue uses 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,

@gaspergrom
gaspergrom requested a review from joanagmaia August 28, 2026 13:12
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>
Copilot AI review requested due to automatic review settings August 28, 2026 14:51

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

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 repos branch also runs on dedicated /repository/[name] and /repository-group/[groupSlug] pages: overview.vue sends selectedReposValues whenever 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,

Comment on lines +32 to +34
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>
Copilot AI review requested due to automatic review settings August 28, 2026 17:46

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

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

developmentActivityScoreV2: number | null;
signals: HealthBreakdownResults | null;
selectedReposAllArchivedOrExcluded: boolean;
isRepoSelected: boolean;
Comment on lines +47 to +48
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>
Copilot AI review requested due to automatic review settings August 28, 2026 17:55

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

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 fetchHealthScoreBreakdown whenever 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 postToTinybird specifically 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, because isMultipleReposSelected is false. The subset state requires the total to be hidden for every top-level filter selection; use isRepoSelected instead. 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

  • isRepoFilterActive is 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"

@gaspergrom
gaspergrom merged commit 5df43ce into main Aug 31, 2026
11 checks passed
@gaspergrom
gaspergrom deleted the feat/IN-1253 branch August 31, 2026 10:03
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.

3 participants