diff --git a/internal/atlas/runs.go b/internal/atlas/runs.go index a6bd134..88350f2 100644 --- a/internal/atlas/runs.go +++ b/internal/atlas/runs.go @@ -73,20 +73,20 @@ func RecentRuns(tasksJSON []byte, n int) ([]RunDot, error) { // aggregateState folds per-job outcomes into a run outcome. func aggregateState(jobs []Job) string { - allSucceeded := true + pending := false for _, j := range jobs { switch j.State() { case "failure", "cancelled", "error": return "failure" - case "success": + case "success", "skipped": // completed OK — skipped (e.g. deploy on a tag push) doesn't block default: - allSucceeded = false + pending = true // running / in_progress / waiting / queued / unknown } } - if allSucceeded { - return "success" + if pending { + return "running" } - return "running" + return "success" } // LatestRunJobs parses a Gitea `/actions/tasks` response (per-job entries, diff --git a/internal/atlas/runs_test.go b/internal/atlas/runs_test.go index ea24913..a583650 100644 --- a/internal/atlas/runs_test.go +++ b/internal/atlas/runs_test.go @@ -89,6 +89,16 @@ func TestRecentRuns_GroupsRunsNewestFirstWithAggregateState(t *testing.T) { } } +func TestRunState_SkippedJobsCountAsOK(t *testing.T) { + // A tag-push run skips the deploy job; the run still succeeded. + s := atlas.RunSummary{Jobs: []atlas.Job{ + {Status: "skipped"}, {Status: "success"}, {Status: "success"}, + }} + if s.State() != "success" { + t.Fatalf("skipped+success run state = %q, want success", s.State()) + } +} + func TestLatestRunJobs_ErrorsWhenEmpty(t *testing.T) { if _, err := atlas.LatestRunJobs([]byte(`{"workflow_runs":[]}`)); err == nil { t.Fatal("expected error on empty, got nil")