Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions services/libs/tinybird/pipes/repo_health_score_v2_breakdown.pipe
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
DESCRIPTION >
- `repo_health_score_v2_breakdown.pipe` is the live, request-time counterpart to
`project_insights_health_breakdown_copy.pipe`'s project-level Health Score v2 signal breakdown
rollup, scoped to a caller-supplied set of repo URLs instead of a project's full repo set. Powers
the Overview page's repo selector (IN-1253): when a subset of a project's repos is selected, the
Health breakdown box is recomputed live for just that subset's active repos.
- Per-column aggregation is copied 1:1 from `project_insights_health_breakdown_copy.pipe` — see
that pipe's DESCRIPTION for the full per-column methodology and rationale (coverage-filtered
`sumIf(score, available) / nullIf(countIf(available), 0)` for `*Available`-backed scores, `max()`
for counts/flags, `min()` for `daysSinceLatest`/`daysBetweenRecent`/`isGerrit`/`isExcluded`,
`avg()` for median-seconds columns and `commitActivityScore`).
- Join path: `repositories` (filtered by the `repos` param, `enabled = true AND excluded = false`)
-> `health_score_v2_signal_detail_ds` (matched on `repoUrl` = `rep.url`) — same population filter
as the project-level rollup, so archived/excluded repos in a mixed selection are dropped from the
aggregation. `HAVING count() > 0` ensures that when every repo in `repos` is archived/excluded,
this query returns zero rows rather than one row of NULL/NaN aggregates over an empty input.
- No `slug`/project grouping — this collapses to a single row for the given repo set, unlike the
project-level copy pipe which groups by project.
- Additionally joins `insightsProjects` (matched on `repositories.insightsProjectId` = `id`) and
requires `insightsProjects.slug` = the caller's `slug` param, so a `repos` value from a different
project can't leak that project's repo-level data into this response.
- Parameters: `slug` (required, the calling project's slug), `repos` (required array of repo URLs).

TOKEN "insights-app-token" READ

TAGS "Insights, Widget", "Project", "Health"

NODE repo_health_score_v2_breakdown_endpoint
SQL >
%
SELECT
sumIf(sd.busFactorScore, sd.busFactorAvailable)
/ nullIf(countIf(sd.busFactorAvailable), 0) AS busFactorScore,
max(sd.busFactorAvailable) AS busFactorAvailable,
max(sd.busFactorCount) AS busFactorCount,
sumIf(sd.orgDiversityScore, sd.orgDiversityAvailable)
/ nullIf(countIf(sd.orgDiversityAvailable), 0) AS orgDiversityScore,
max(sd.orgDiversityAvailable) AS orgDiversityAvailable,
max(sd.orgCount) AS orgCount,
sumIf(sd.responsivenessScore, sd.responsivenessAvailable)
/ nullIf(countIf(sd.responsivenessAvailable), 0) AS responsivenessScore,
max(sd.responsivenessAvailable) AS responsivenessAvailable,
avg(sd.medianPrResponseS) AS medianPrResponseS,
avg(sd.medianIssueResponseS) AS medianIssueResponseS,
min(sd.isGerrit) AS isGerrit,
min(sd.isExcluded) AS isExcluded,
sumIf(sd.openVulnScore, sd.openVulnAvailable)
/ nullIf(countIf(sd.openVulnAvailable), 0) AS openVulnScore,
max(sd.openVulnAvailable) AS openVulnAvailable,
max(sd.openCriticals) AS openCriticals,
max(sd.openHighs) AS openHighs,
max(sd.openModerates) AS openModerates,
sumIf(sd.scorecardScorePts, sd.scorecardAvailable)
/ nullIf(countIf(sd.scorecardAvailable), 0) AS scorecardScorePts,
max(sd.scorecardAvailable) AS scorecardAvailable,
sumIf(toFloat64OrNull(sd.scorecardScore), sd.scorecardAvailable)
/ nullIf(countIf(sd.scorecardAvailable), 0) AS scorecardScore,
sumIf(sd.securityPracticesScore, sd.securityPracticesAvailable)
/ nullIf(countIf(sd.securityPracticesAvailable), 0) AS securityPracticesScore,
max(sd.securityPracticesAvailable) AS securityPracticesAvailable,
max(sd.securityPolicyEnabled) AS securityPolicyEnabled,
max(sd.branchProtectionEnabled) AS branchProtectionEnabled,
max(sd.branchProtectionRequiredReviews) AS branchProtectionRequiredReviews,
max(sd.branchProtectionRequiresStatusChecks) AS branchProtectionRequiresStatusChecks,
max(sd.branchProtectionAllowsForcePush) AS branchProtectionAllowsForcePush,
sumIf(sd.dependencyHealthScore, sd.dependencyHealthAvailable)
/ nullIf(countIf(sd.dependencyHealthAvailable), 0) AS dependencyHealthScore,
max(sd.dependencyHealthAvailable) AS dependencyHealthAvailable,
max(sd.vulnerableDeps) AS vulnerableDeps,
sumIf(sd.releaseCadenceScore, sd.releaseCadenceAvailable)
/ nullIf(countIf(sd.releaseCadenceAvailable), 0) AS releaseCadenceScore,
max(sd.releaseCadenceAvailable) AS releaseCadenceAvailable,
min(sd.daysSinceLatest) AS daysSinceLatest,
min(sd.daysBetweenRecent) AS daysBetweenRecent,
avg(sd.commitActivityScore) AS commitActivityScore,
max(sd.commitsLast6m) AS commitsLast6m,
max(sd.lastCommitAt) AS lastCommitAt,
sumIf(sd.issueResolutionScore, sd.issueResolutionAvailable)
/ nullIf(countIf(sd.issueResolutionAvailable), 0) AS issueResolutionScore,
max(sd.issueResolutionAvailable) AS issueResolutionAvailable,
max(sd.closed12m) AS closed12m,
max(sd.opened12m) AS opened12m,
avg(sd.medianCloseS) AS medianCloseS,
sumIf(sd.prMergeScore, sd.prMergeAvailable)
/ nullIf(countIf(sd.prMergeAvailable), 0) AS prMergeScore,
max(sd.prMergeAvailable) AS prMergeAvailable,
max(sd.merged12m) AS merged12m,
max(sd.closedUnmerged12m) AS closedUnmerged12m,
avg(sd.medianMergeS) AS medianMergeS
FROM repositories rep FINAL
INNER JOIN health_score_v2_signal_detail_ds sd ON sd.repoUrl = rep.url
INNER JOIN insightsProjects ip FINAL ON ip.id = rep.insightsProjectId
WHERE
rep.url
IN {{ Array(repos, 'String', description="Selected repo URLs", required=True) }}
AND rep.enabled = true
AND rep.excluded = false
AND ip.slug = {{ String(slug, description="Calling project's slug", required=True) }}
Comment on lines +117 to +119
HAVING count() > 0
48 changes: 48 additions & 0 deletions services/libs/tinybird/pipes/repo_lifecycle_v2.pipe
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
DESCRIPTION >
- `repo_lifecycle_v2.pipe` is the live, request-time counterpart to `project_insights_copy.pipe`'s
`project_insights_copy_health_v2_project` lifecycle rollup, scoped to a caller-supplied set of repo
URLs instead of a project's full repo set. Powers the Overview page's repo selector (IN-1253):
when a subset of a project's repos is selected, Lifecycle is recomputed live for just that subset.
- Deliberately does NOT filter on `enabled`/`excluded` — `archived` is itself a valid
`lifecycleLabelV2` value (per the spec's decision tree: archived flag > abandoned > inert >
declining > stable > active, first match wins), so an all-archived/excluded selection must still
produce a real lifecycle label rather than being dropped from the rollup.
Comment on lines +6 to +9
- Reads `health_score_v2_repo_copy_ds` directly, no join with `repositories`.
- Same best-state-wins precedence and `if(empty(groupArray(...)), NULL, ...)` NULL-guard as
`project_insights_copy_health_v2_project` (see that node's DESCRIPTION for the `arrayElement` on
an empty array returning `''` instead of NULL rationale, IN-1196).
- Joins `repositories` (matched on `url` = `repoUrl`) to `insightsProjects` (matched on
`insightsProjectId` = `id`) and requires `insightsProjects.slug` = the caller's `slug` param, so a
`repos` value from a different project can't leak that project's repo-level data into this response.
- Parameters: `slug` (required, the calling project's slug), `repos` (required array of repo URLs).

TOKEN "insights-app-token" READ

TAGS "Insights, Widget", "Project", "Health"

NODE repo_lifecycle_v2_endpoint
SQL >
%
SELECT
if(
empty(groupArray(lifecycleLabelV2)),
NULL,
toNullable(
arrayElement(
arraySort(
x -> indexOf(
['active', 'stable', 'declining', 'inert', 'abandoned', 'archived'], x
),
groupArray(lifecycleLabelV2)
),
1
)
)
) AS lifecycleLabel
FROM health_score_v2_repo_copy_ds hs
INNER JOIN repositories rep FINAL ON rep.url = hs.repoUrl
INNER JOIN insightsProjects ip FINAL ON ip.id = rep.insightsProjectId
WHERE
hs.repoUrl
IN {{ Array(repos, 'String', description="Selected repo URLs", required=True) }}
AND ip.slug = {{ String(slug, description="Calling project's slug", required=True) }}
Loading