Files
ghtracker/src/components/FleetStrip.vue
T
lukaszraczylo 5313b56774 feat: add GitHub repository dashboard with Prometheus metrics
ghtracker authenticates as a GitHub App and scans a configured list of repositories on a schedule. It serves a dashboard, a JSON state endpoint, a health probe and Prometheus metrics.

The dashboard lists only items that need attention: failing workflows, pull requests that wait too long or fail their checks, stale issues and projects that failed to scan. It has search, dynamic filters and a button that rescans on demand. The Vue app is embedded in the Go binary.

The client protects the GitHub rate limit with conditional requests, a request reserve and Retry-After handling.
2026-10-02 04:28:52 +01:00

53 lines
1.8 KiB
Vue

<script setup lang="ts">
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
import type { Repo } from '@/lib/types'
import type { RepoCounts } from '@/stores/tracker'
defineProps<{
repos: Repo[]
counts: Map<string, RepoCounts>
focused: string | null
matching: Set<string>
}>()
defineEmits<{ select: [fullName: string] }>()
const SEGMENT = { crit: 'bg-crit', warn: 'bg-warn', ok: 'bg-ok/30 hover:bg-ok/60' } as const
function summary(c: RepoCounts | undefined): string {
if (!c) return 'healthy'
const parts = []
if (c.crit) parts.push(`${c.crit} critical`)
if (c.warn) parts.push(`${c.warn} ${c.warn === 1 ? 'warning' : 'warnings'}`)
return parts.join(' · ')
}
</script>
<template>
<TooltipProvider :delay-duration="80">
<div class="flex gap-1" role="group" aria-label="Project health" data-test="strip">
<Tooltip v-for="repo in repos" :key="repo.fullName">
<TooltipTrigger as-child>
<button
type="button"
:aria-label="`${repo.fullName}: ${summary(counts.get(repo.fullName))}`"
:aria-pressed="focused === repo.fullName"
class="h-14 min-w-0 flex-1 rounded-[3px] transition-colors focus-visible:outline-offset-1"
:class="[
SEGMENT[repo.health],
focused === repo.fullName
? 'ring-foreground ring-2 ring-offset-2 ring-offset-background'
: '',
]"
data-test="segment"
@click="$emit('select', repo.fullName)"
/>
</TooltipTrigger>
<TooltipContent>
<p class="font-medium">{{ repo.fullName }}</p>
<p class="opacity-80">{{ summary(counts.get(repo.fullName)) }}</p>
</TooltipContent>
</Tooltip>
</div>
</TooltipProvider>
</template>