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