mirror of
https://github.com/lukaszraczylo/ghtracker.git
synced 2026-10-14 00:58:36 +00:00
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.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||
import AgeMeter from '@/components/AgeMeter.vue'
|
||||
import { ageSince, isZeroTime, secondsSince, shorten } from '@/lib/format'
|
||||
import { iconFor } from '@/lib/kinds'
|
||||
import type { Row } from '@/lib/types'
|
||||
|
||||
const props = defineProps<{ row: Row; nowMs: number; critSeconds: number }>()
|
||||
|
||||
const ratio = computed(() => secondsSince(props.row.since, props.nowMs) / props.critSeconds)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<li class="grid grid-cols-[2rem_minmax(0,1fr)_auto] items-start gap-x-3 py-3" data-test="row">
|
||||
<span
|
||||
class="flex size-8 items-center justify-center rounded-md"
|
||||
:class="row.severity === 'crit' ? 'bg-crit/12 text-crit' : 'bg-warn/12 text-warn'"
|
||||
>
|
||||
<FontAwesomeIcon :icon="iconFor(row.kind)" aria-hidden="true" />
|
||||
<span class="sr-only">{{ row.severity === 'crit' ? 'Critical' : 'Warning' }}</span>
|
||||
</span>
|
||||
<div class="min-w-0">
|
||||
<a
|
||||
:href="row.url"
|
||||
class="hover:text-link leading-snug font-medium wrap-anywhere underline-offset-4 hover:underline"
|
||||
>
|
||||
{{ shorten(row.subject) }}
|
||||
</a>
|
||||
<p class="text-muted-foreground mt-0.5 text-sm wrap-anywhere">
|
||||
{{ shorten(row.detail, 120) }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-end gap-1.5 pt-0.5">
|
||||
<span class="text-muted-foreground font-mono text-xs whitespace-nowrap">
|
||||
{{ isZeroTime(row.since) ? '' : ageSince(row.since, nowMs) }}
|
||||
</span>
|
||||
<AgeMeter
|
||||
v-if="row.kind === 'pr_waiting' && !isZeroTime(row.since)"
|
||||
:ratio="ratio"
|
||||
:severity="row.severity"
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
Reference in New Issue
Block a user