diff --git a/src/components/GitHubActionsFetcher.tsx b/src/components/GitHubActionsFetcher.tsx
index 824a31422..64980aab7 100644
--- a/src/components/GitHubActionsFetcher.tsx
+++ b/src/components/GitHubActionsFetcher.tsx
@@ -1,9 +1,10 @@
-import { useState, useEffect } from 'react'
+import { useState, useEffect, useMemo } from 'react'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
import { Skeleton } from '@/components/ui/skeleton'
-import { CheckCircle, XCircle, ArrowClockwise, ArrowSquareOut, Info } from '@phosphor-icons/react'
+import { Badge } from '@/components/ui/badge'
+import { CheckCircle, XCircle, ArrowClockwise, ArrowSquareOut, Info, Warning, TrendUp, TrendDown } from '@phosphor-icons/react'
import { toast } from 'sonner'
import { Octokit } from 'octokit'
@@ -79,6 +80,39 @@ export function GitHubActionsFetcher() {
return
}
+ const conclusion = useMemo(() => {
+ if (!data || data.length === 0) return null
+
+ const total = data.length
+ const completed = data.filter(r => r.status === 'completed').length
+ const successful = data.filter(r => r.conclusion === 'success').length
+ const failed = data.filter(r => r.conclusion === 'failure').length
+ const cancelled = data.filter(r => r.conclusion === 'cancelled').length
+ const inProgress = data.filter(r => r.status !== 'completed').length
+
+ const successRate = completed > 0 ? Math.round((successful / completed) * 100) : 0
+ const recentRuns = data.slice(0, 5)
+ const recentSuccessful = recentRuns.filter(r => r.conclusion === 'success').length
+ const recentFailed = recentRuns.filter(r => r.conclusion === 'failure').length
+
+ const health = successRate >= 80 ? 'healthy' : successRate >= 60 ? 'warning' : 'critical'
+ const trend = recentSuccessful >= recentFailed ? 'up' : 'down'
+
+ return {
+ total,
+ completed,
+ successful,
+ failed,
+ cancelled,
+ inProgress,
+ successRate,
+ health,
+ trend,
+ recentSuccessful,
+ recentFailed
+ }
+ }, [data])
+
return (
@@ -98,6 +132,92 @@ export function GitHubActionsFetcher() {
+ {conclusion && (
+
+
+
+ {conclusion.health === 'healthy' && }
+ {conclusion.health === 'warning' && }
+ {conclusion.health === 'critical' && }
+ Pipeline Health Summary
+
+
+ Analysis of recent workflow runs
+
+
+
+
+
+
+ {conclusion.successRate}% Success Rate
+
+
+
+
+ {conclusion.successful} Passed
+
+
+ {conclusion.failed > 0 && (
+
+
+ {conclusion.failed} Failed
+
+ )}
+
+ {conclusion.inProgress > 0 && (
+
+
+ {conclusion.inProgress} Running
+
+ )}
+
+ {conclusion.cancelled > 0 && (
+
+ {conclusion.cancelled} Cancelled
+
+ )}
+
+
+ {conclusion.trend === 'up' ? (
+
+ ) : (
+
+ )}
+ Recent: {conclusion.recentSuccessful}/{conclusion.recentSuccessful + conclusion.recentFailed}
+
+
+
+
+ {conclusion.health === 'healthy' && (
+
+
+ Pipeline is healthy. Most recent runs are passing consistently.
+
+ )}
+ {conclusion.health === 'warning' && (
+
+
+ Pipeline health is moderate. Some failures detected in recent runs.
+
+ )}
+ {conclusion.health === 'critical' && (
+
+
+ Pipeline health is critical. High failure rate detected.
+
+ )}
+
+
+
+
+ )}
+
{needsAuth && (