{{ define "main" }} {{/* Load metrics - supports multi-repo with dynamic switching. Renders content for all repos, JavaScript handles showing the selected one. */}} {{ $reposIndex := site.Data.repos }} {{ if and $reposIndex $reposIndex.repositories }} {{/* ===== All-Repositories Summary View ===== */}} {{ $chartColors := slice "rgb(0, 102, 204)" "rgb(40, 167, 69)" "rgb(255, 193, 7)" "rgb(220, 53, 69)" "rgb(108, 117, 125)" "rgb(153, 102, 255)" "rgb(255, 159, 64)" }} {{/* Gather per-repo data once for totals, table rows, and chart series */}} {{ $totalStars := 0 }} {{ $totalForks := 0 }} {{ $totalOpenIssues := 0 }} {{ $totalOpenPRs := 0 }} {{ $totalActive := 0 }} {{ $totalAwaitingIssues := 0 }} {{ $totalAwaitingPRs := 0 }} {{ $rows := slice }} {{ $issuesSeries := slice }} {{ $pullsSeries := slice }} {{ $starsSeries := slice }} {{ $downloadsSeries := slice }} {{ $dlWeeklySeries := slice }} {{ $dlMonthlySeries := slice }} {{ $dlTotalSeries := slice }} {{ $allDates := slice }} {{ $allWeeks := slice }} {{ $allMonths := slice }} {{/* Global latest snapshot date — used as the trailing-week anchor so all repos bin to the same x-axis even if one lags. */}} {{ $latestDate := "" }} {{ range $rc := $reposIndex.repositories }} {{ with index site.Data.repos $rc.owner }}{{ with index . $rc.repo }}{{ range .snapshots }} {{ if gt .date $latestDate }}{{ $latestDate = .date }}{{ end }} {{ end }}{{ end }}{{ end }} {{ end }} {{ $latest := time.AsTime (cond (ne $latestDate "") $latestDate (now.Format "2006-01-02")) }} {{ $anyInbound := false }} {{ $anyDownloads := false }} {{ range $i, $rc := $reposIndex.repositories }} {{ $rm := false }} {{ $rsnaps := false }} {{ $ra := false }} {{ $ri := false }} {{ with index site.Data.repos $rc.owner }}{{ with index . $rc.repo }} {{ $rm = .metrics }} {{ $rsnaps = .snapshots }} {{ $ra = .actionability }} {{ $ri = .issues }} {{ end }}{{ end }} {{ if $rm }} {{ $totalStars = add $totalStars ($rm.repository.stars | default 0) }} {{ $totalForks = add $totalForks ($rm.repository.forks | default 0) }} {{ $totalOpenIssues = add $totalOpenIssues ($rm.issues.open_count | default 0) }} {{ $totalOpenPRs = add $totalOpenPRs ($rm.pulls.open_count | default 0) }} {{ $totalActive = add $totalActive ($rm.contributors.active_30d | default 0) }} {{ $totalAwaitingIssues = add $totalAwaitingIssues ($rm.issues.without_response_24h | default 0) }} {{ $totalAwaitingPRs = add $totalAwaitingPRs ($rm.pulls.without_review_24h | default 0) }} {{ $starsSpark := partial "get-sparkline.html" (dict "snapshots" $rsnaps "path" "repository.stars" "limit" 8) }} {{ $issuesSpark := partial "get-sparkline.html" (dict "snapshots" $rsnaps "path" "issues.open" "limit" 8) }} {{ $pullsSpark := partial "get-sparkline.html" (dict "snapshots" $rsnaps "path" "pulls.open" "limit" 8) }} {{ $hasAct := and $ra $ra.summary }} {{ $hasIss := and $ri $ri.summary }} {{ if or $hasAct $hasIss }}{{ $anyInbound = true }}{{ end }} {{ $dl := $rm.downloads }} {{ $dlDaily := 0 }} {{ $dlTrend := 0.0 }} {{ $dlWeekly := $dl.last_week | default 0 }} {{ $dlMonthly := $dl.last_month | default 0 }} {{ if $dl }} {{ $anyDownloads = true }} {{/* Daily from most-recent snapshot with a value — registry APIs lag 1-2 days so metrics.json's daily is often undefined. */}} {{ $spark := partial "get-sparkline.html" (dict "snapshots" $rsnaps "path" "downloads.daily" "limit" 2) }} {{ if $spark }}{{ $dlDaily = index $spark (sub (len $spark) 1) }}{{ end }} {{ $dlTrend = partial "calc-trend.html" (dict "sparkline" $spark) }} {{ if not $dlWeekly }} {{ $wk := partial "get-sparkline.html" (dict "snapshots" $rsnaps "path" "downloads.daily" "limit" 7) }} {{ range $wk }}{{ $dlWeekly = add $dlWeekly . }}{{ end }} {{ end }} {{ if not $dlMonthly }} {{ $mo := partial "get-sparkline.html" (dict "snapshots" $rsnaps "path" "downloads.daily" "limit" 30) }} {{ range $mo }}{{ $dlMonthly = add $dlMonthly . }}{{ end }} {{ end }} {{ end }} {{ $rows = $rows | append (dict "owner" $rc.owner "repo" $rc.repo "name" ($rc.name | default (printf "%s/%s" $rc.owner $rc.repo)) "stars" $rm.repository.stars "starsTrend" (partial "calc-trend.html" (dict "sparkline" $starsSpark)) "issues" $rm.issues.open_count "issuesTrend" (partial "calc-trend.html" (dict "sparkline" $issuesSpark)) "pulls" $rm.pulls.open_count "pullsTrend" (partial "calc-trend.html" (dict "sparkline" $pullsSpark)) "awaitingIssues" $rm.issues.without_response_24h "awaitingPRs" $rm.pulls.without_review_24h "active" $rm.contributors.active_30d "hasAct" $hasAct "actionablePRs" (cond (not (not $hasAct)) $ra.summary.actionable_count 0) "hasIss" $hasIss "bugsEnh" (cond (not (not $hasIss)) (add ($ri.summary.by_type.bug | default 0) ($ri.summary.by_type.enhancement | default 0)) 0) "triagePending" (cond (not (not $hasIss)) (add ($ri.summary.untriaged_count | default 0) ($ri.summary.partially_triaged_count | default 0)) 0) "p0Breach" (cond (not (not $hasIss)) $ri.summary.sla.p0_7d_breach 0) "p1Breach" (cond (not (not $hasIss)) $ri.summary.sla.p1_90d_breach 0) "hasDl" (not (not $dl)) "dlDaily" $dlDaily "dlWeekly" $dlWeekly "dlMonthly" $dlMonthly "dlTotal" ($dl.total | default 0) "dlTrend" $dlTrend "pkg" $rc.package ) }} {{/* Build chart series from snapshots - use {x,y} points so repos with fewer snapshots align correctly */}} {{ if $rsnaps }} {{ $entries := slice }} {{ range $fn, $d := $rsnaps }} {{ $entries = $entries | append (dict "date" $d.date "issues" (index $d "issues" "open") "pulls" (index $d "pulls" "open") "stars" (index $d "repository" "stars") "dlDaily" (index $d "downloads" "daily") "dlTotal" (index $d "downloads" "total")) }} {{ end }} {{ $sorted := sort $entries "date" "asc" }} {{ $dates := slice }}{{ $iv := slice }}{{ $pv := slice }}{{ $sv := slice }}{{ $dv := slice }}{{ $tv := slice }} {{ $weekBins := dict }} {{ $monthBins := dict }} {{ range $sorted }} {{ $dates = $dates | append .date }} {{ if ne .issues nil }}{{ $iv = $iv | append (dict "x" .date "y" .issues) }}{{ end }} {{ if ne .pulls nil }}{{ $pv = $pv | append (dict "x" .date "y" .pulls) }}{{ end }} {{ if ne .stars nil }}{{ $sv = $sv | append (dict "x" .date "y" .stars) }}{{ end }} {{ if ne .dlDaily nil }} {{ $dv = $dv | append (dict "x" .date "y" .dlDaily) }} {{ $ago := int (div ($latest.Sub (time.AsTime .date)).Hours 24) }} {{ $bin := div $ago 7 }} {{ $key := ($latest.Add (time.ParseDuration (printf "-%dh" (mul 168 $bin)))).Format "2006-01-02" }} {{ $weekBins = merge $weekBins (dict $key (add (index $weekBins $key | default 0) .dlDaily)) }} {{ $mkey := (time.AsTime .date).Format "2006-01" }} {{ $monthBins = merge $monthBins (dict $mkey (add (index $monthBins $mkey | default 0) .dlDaily)) }} {{ end }} {{ if ne .dlTotal nil }}{{ $tv = $tv | append (dict "x" .date "y" .dlTotal) }}{{ end }} {{ end }} {{ $wv := slice }} {{ range $k, $v := $weekBins }}{{ $wv = $wv | append (dict "x" $k "y" $v) }}{{ end }} {{ $wv = sort $wv "x" "asc" }} {{/* Drop oldest bin when snapshot count mod 7 != 0 — it's a partial week that looks like a cliff. */}} {{ if and (gt (len $wv) 1) (ne (mod (len $dv) 7) 0) }}{{ $wv = after 1 $wv }}{{ end }} {{ range $wv }}{{ $allWeeks = $allWeeks | union (slice .x) }}{{ end }} {{ $mv := slice }} {{ range $k, $v := $monthBins }}{{ $mv = $mv | append (dict "x" $k "y" $v) }}{{ end }} {{ $mv = sort $mv "x" "asc" }} {{ range $mv }}{{ $allMonths = $allMonths | union (slice .x) }}{{ end }} {{ $allDates = $allDates | union $dates }} {{ $color := index $chartColors (mod $i (len $chartColors)) }} {{ $label := $rc.name | default (printf "%s/%s" $rc.owner $rc.repo) }} {{ $issuesSeries = $issuesSeries | append (dict "label" $label "data" $iv "borderColor" $color "backgroundColor" "transparent" "tension" 0.3) }} {{ $pullsSeries = $pullsSeries | append (dict "label" $label "data" $pv "borderColor" $color "backgroundColor" "transparent" "tension" 0.3) }} {{ $starsSeries = $starsSeries | append (dict "label" $label "data" $sv "borderColor" $color "backgroundColor" "transparent" "tension" 0.3) }} {{ if $dv }}{{ $downloadsSeries = $downloadsSeries | append (dict "label" $label "data" $dv "borderColor" $color "backgroundColor" "transparent" "tension" 0.3) }}{{ end }} {{ if $wv }}{{ $dlWeeklySeries = $dlWeeklySeries | append (dict "label" $label "data" $wv "borderColor" $color "backgroundColor" "transparent" "tension" 0.3) }}{{ end }} {{ if $mv }}{{ $dlMonthlySeries = $dlMonthlySeries | append (dict "label" $label "data" $mv "borderColor" $color "backgroundColor" "transparent" "tension" 0.3) }}{{ end }} {{ if $tv }}{{ $dlTotalSeries = $dlTotalSeries | append (dict "label" $label "data" $tv "borderColor" $color "backgroundColor" "transparent" "tension" 0.3) }}{{ end }} {{ end }} {{ end }} {{ end }} {{ $allDates = sort $allDates }}
| Repository | StarsTotal GitHub stars. Delta shows change over the last 7 days. | Open IssuesCurrently open issues. Delta shows change over the last 7 days. | Open PRsCurrently open pull requests. Delta shows change over the last 7 days. | Awaiting ResponseOpen issues with no maintainer response after 24 hours | Awaiting ReviewOpen PRs with no review after 24 hours | Active (30d)Contributors with activity in the last 30 days |
|---|---|---|---|---|---|---|
|
{{ .name }}
{{ .owner }}/{{ .repo }}
|
{{ lang.FormatNumber 0 .stars }} {{ if ne .starsTrend 0.0 }}{{ $up := gt .starsTrend 0.0 }}{{ $abs := cond $up .starsTrend (mul .starsTrend -1) }} {{ cond $up "↑" "↓" }}{{ printf "%.1f" $abs }}% {{ end }} | {{ .issues }} {{ if ne .issuesTrend 0.0 }}{{ $up := gt .issuesTrend 0.0 }}{{ $abs := cond $up .issuesTrend (mul .issuesTrend -1) }} {{ cond $up "↑" "↓" }}{{ printf "%.1f" $abs }}% {{ end }} | {{ .pulls }} {{ if ne .pullsTrend 0.0 }}{{ $up := gt .pullsTrend 0.0 }}{{ $abs := cond $up .pullsTrend (mul .pullsTrend -1) }} {{ cond $up "↑" "↓" }}{{ printf "%.1f" $abs }}% {{ end }} | {{ .awaitingIssues }} | {{ .awaitingPRs }} | {{ .active }} |
| Repository |
Actionable PRsPRs where the ball is in our court. Green: ≤ 25 · Yellow: 26–50 · Red: > 50 |
Bugs + EnhOpen issues labeled bug or enhancement. |
Triage PendingIssues missing a type or priority label. Green: < 5 · Yellow: 5–9 · Red: ≥ 10 |
P0 > 7dP0 issues open past the 7-day SEP-1730 SLA. Green: 0 · Red: any |
P1 > 90dP1 issues open past 90 days — surfaces aspirational-P1 rot. Green: 0 · Yellow: 1–4 · Red: ≥ 5 |
|---|---|---|---|---|---|
|
{{ .name }}
{{ .owner }}/{{ .repo }}
|
{{- if .hasAct -}} {{- $c := cond (le .actionablePRs 25) "text-success" (cond (le .actionablePRs 50) "text-warning" "text-error") -}} {{ .actionablePRs }} {{- else }}{{ $dash }}{{ end -}} | {{- if .hasIss }}{{ .bugsEnh }}{{ else }}{{ $dash }}{{ end -}} | {{- if .hasIss -}} {{- $c := cond (lt .triagePending 5) "text-success" (cond (lt .triagePending 10) "text-warning" "text-error") -}} {{ .triagePending }} {{- else }}{{ $dash }}{{ end -}} | {{- if .hasIss -}} {{- $c := cond (gt .p0Breach 0) "text-error" "text-success" -}} {{ .p0Breach }} {{- else }}{{ $dash }}{{ end -}} | {{- if .hasIss -}} {{- $c := cond (eq .p1Breach 0) "text-success" (cond (lt .p1Breach 5) "text-warning" "text-error") -}} {{ .p1Breach }} {{- else }}{{ $dash }}{{ end -}} |
| SDK |
DailyDownloads on the most recent day with data. Delta compares to the day before. NuGet derives this from cumulative-total diffs, so C# needs two days of data before a value appears. |
WeeklyDownloads over the last 7 days. | MonthlyDownloads over the last 30 days. | TotalCumulative downloads. Native where the registry reports it; npm is a running sum we maintain from daily counts; PyPI comes from BigQuery's full download log history. |
|---|---|---|---|---|
|
{{ .name }}
{{ with .pkg }}{{ .registry }} · {{ .name }}{{ end }}
|
{{ if .dlDaily }} {{ lang.FormatNumber 0 .dlDaily }} {{ if ne .dlTrend 0.0 }}{{ $up := gt .dlTrend 0.0 }}{{ $abs := cond $up .dlTrend (mul .dlTrend -1) }} {{ cond $up "↑" "↓" }}{{ printf "%.1f" $abs }}% {{ end }} {{ else }}{{ $dash }}{{ end }} | {{ if .dlWeekly }}{{ lang.FormatNumber 0 .dlWeekly }}{{ else }}{{ $dash }}{{ end }} | {{ if .dlMonthly }}{{ lang.FormatNumber 0 .dlMonthly }}{{ else }}{{ $dash }}{{ end }} | {{ if .dlTotal }}{{ lang.FormatNumber 0 .dlTotal }}{{ else }}{{ $dash }}{{ end }} |