this repo has no description
1package models 2 3import ( 4 "fmt" 5 "slices" 6 "strings" 7 "time" 8 9 "github.com/bluesky-social/indigo/atproto/syntax" 10 "github.com/go-git/go-git/v5/plumbing" 11 spindle "tangled.org/core/spindle/models" 12 "tangled.org/core/workflow" 13) 14 15type Pipeline struct { 16 Id int 17 Rkey string 18 Knot string 19 RepoOwner syntax.DID 20 RepoName string 21 TriggerId int 22 Sha string 23 Created time.Time 24 25 // populate when querying for reverse mappings 26 Trigger *Trigger 27 Statuses map[string]WorkflowStatus 28} 29 30type WorkflowStatus struct { 31 Data []PipelineStatus 32} 33 34func (w WorkflowStatus) Latest() PipelineStatus { 35 return w.Data[len(w.Data)-1] 36} 37 38// time taken by this workflow to reach an "end state" 39func (w WorkflowStatus) TimeTaken() time.Duration { 40 var start, end *time.Time 41 for _, s := range w.Data { 42 if s.Status.IsStart() { 43 start = &s.Created 44 } 45 if s.Status.IsFinish() { 46 end = &s.Created 47 } 48 } 49 50 if start != nil && end != nil && end.After(*start) { 51 return end.Sub(*start) 52 } 53 54 return 0 55} 56 57// produces short summary of successes: 58// - "0/4" when zero successes of 4 workflows 59// - "4/4" when all successes of 4 workflows 60// - "0/0" when no workflows run in this pipeline 61func (p Pipeline) ShortStatusSummary() string { 62 counts := make(map[spindle.StatusKind]int) 63 for _, w := range p.Statuses { 64 counts[w.Latest().Status] += 1 65 } 66 67 total := len(p.Statuses) 68 successes := counts[spindle.StatusKindSuccess] 69 70 return fmt.Sprintf("%d/%d", successes, total) 71} 72 73// produces a string of the form "3/4 success, 2/4 failed, 1/4 pending" 74func (p Pipeline) LongStatusSummary() string { 75 counts := make(map[spindle.StatusKind]int) 76 for _, w := range p.Statuses { 77 counts[w.Latest().Status] += 1 78 } 79 80 total := len(p.Statuses) 81 82 var result []string 83 // finish states first, followed by start states 84 states := append(spindle.FinishStates[:], spindle.StartStates[:]...) 85 for _, state := range states { 86 if count, ok := counts[state]; ok { 87 result = append(result, fmt.Sprintf("%d/%d %s", count, total, state.String())) 88 } 89 } 90 91 return strings.Join(result, ", ") 92} 93 94func (p Pipeline) Counts() map[string]int { 95 m := make(map[string]int) 96 for _, w := range p.Statuses { 97 m[w.Latest().Status.String()] += 1 98 } 99 return m 100} 101 102func (p Pipeline) TimeTaken() time.Duration { 103 var s time.Duration 104 for _, w := range p.Statuses { 105 s += w.TimeTaken() 106 } 107 return s 108} 109 110func (p Pipeline) Workflows() []string { 111 var ws []string 112 for v := range p.Statuses { 113 ws = append(ws, v) 114 } 115 slices.Sort(ws) 116 return ws 117} 118 119// if we know that a spindle has picked up this pipeline, then it is Responding 120func (p Pipeline) IsResponding() bool { 121 return len(p.Statuses) != 0 122} 123 124type Trigger struct { 125 Id int 126 Kind workflow.TriggerKind 127 128 // push trigger fields 129 PushRef *string 130 PushNewSha *string 131 PushOldSha *string 132 133 // pull request trigger fields 134 PRSourceBranch *string 135 PRTargetBranch *string 136 PRSourceSha *string 137 PRAction *string 138} 139 140func (t *Trigger) IsPush() bool { 141 return t != nil && t.Kind == workflow.TriggerKindPush 142} 143 144func (t *Trigger) IsPullRequest() bool { 145 return t != nil && t.Kind == workflow.TriggerKindPullRequest 146} 147 148func (t *Trigger) TargetRef() string { 149 if t.IsPush() { 150 return plumbing.ReferenceName(*t.PushRef).Short() 151 } else if t.IsPullRequest() { 152 return *t.PRTargetBranch 153 } 154 155 return "" 156} 157 158type PipelineStatus struct { 159 ID int 160 Spindle string 161 Rkey string 162 PipelineKnot string 163 PipelineRkey string 164 Created time.Time 165 Workflow string 166 Status spindle.StatusKind 167 Error *string 168 ExitCode int 169}