1package models
2
3import (
4 "slices"
5 "time"
6
7 "github.com/bluesky-social/indigo/atproto/syntax"
8 "github.com/go-git/go-git/v5/plumbing"
9 spindle "tangled.org/core/spindle/models"
10 "tangled.org/core/workflow"
11)
12
13type Pipeline struct {
14 Id int
15 Rkey string
16 Knot string
17 RepoOwner syntax.DID
18 RepoName string
19 TriggerId int
20 Sha string
21 Created time.Time
22
23 // populate when querying for reverse mappings
24 Trigger *Trigger
25 Statuses map[string]WorkflowStatus
26}
27
28type WorkflowStatus struct {
29 Data []PipelineStatus
30}
31
32func (w WorkflowStatus) Latest() PipelineStatus {
33 return w.Data[len(w.Data)-1]
34}
35
36// time taken by this workflow to reach an "end state"
37func (w WorkflowStatus) TimeTaken() time.Duration {
38 var start, end *time.Time
39 for _, s := range w.Data {
40 if s.Status.IsStart() {
41 start = &s.Created
42 }
43 if s.Status.IsFinish() {
44 end = &s.Created
45 }
46 }
47
48 if start != nil && end != nil && end.After(*start) {
49 return end.Sub(*start)
50 }
51
52 return 0
53}
54
55func (p Pipeline) Counts() map[string]int {
56 m := make(map[string]int)
57 for _, w := range p.Statuses {
58 m[w.Latest().Status.String()] += 1
59 }
60 return m
61}
62
63func (p Pipeline) TimeTaken() time.Duration {
64 var s time.Duration
65 for _, w := range p.Statuses {
66 s += w.TimeTaken()
67 }
68 return s
69}
70
71func (p Pipeline) Workflows() []string {
72 var ws []string
73 for v := range p.Statuses {
74 ws = append(ws, v)
75 }
76 slices.Sort(ws)
77 return ws
78}
79
80// if we know that a spindle has picked up this pipeline, then it is Responding
81func (p Pipeline) IsResponding() bool {
82 return len(p.Statuses) != 0
83}
84
85type Trigger struct {
86 Id int
87 Kind workflow.TriggerKind
88
89 // push trigger fields
90 PushRef *string
91 PushNewSha *string
92 PushOldSha *string
93
94 // pull request trigger fields
95 PRSourceBranch *string
96 PRTargetBranch *string
97 PRSourceSha *string
98 PRAction *string
99}
100
101func (t *Trigger) IsPush() bool {
102 return t != nil && t.Kind == workflow.TriggerKindPush
103}
104
105func (t *Trigger) IsPullRequest() bool {
106 return t != nil && t.Kind == workflow.TriggerKindPullRequest
107}
108
109func (t *Trigger) TargetRef() string {
110 if t.IsPush() {
111 return plumbing.ReferenceName(*t.PushRef).Short()
112 } else if t.IsPullRequest() {
113 return *t.PRTargetBranch
114 }
115
116 return ""
117}
118
119type PipelineStatus struct {
120 ID int
121 Spindle string
122 Rkey string
123 PipelineKnot string
124 PipelineRkey string
125 Created time.Time
126 Workflow string
127 Status spindle.StatusKind
128 Error *string
129 ExitCode int
130}