-
Notifications
You must be signed in to change notification settings - Fork 95
Expand file tree
/
Copy pathget_workflow_runs_from_github.go
More file actions
152 lines (135 loc) · 4.25 KB
/
get_workflow_runs_from_github.go
File metadata and controls
152 lines (135 loc) · 4.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package metrics
import (
"context"
"log"
"strconv"
"strings"
"time"
"github.com/spendesk/github-actions-exporter/pkg/config"
"github.com/google/go-github/v45/github"
)
// getFieldValue return value from run element which corresponds to field
func getFieldValue(repo string, run github.WorkflowRun, field string) string {
switch field {
case "repo":
return repo
case "id":
return strconv.FormatInt(*run.ID, 10)
case "node_id":
return *run.NodeID
case "head_branch":
return *run.HeadBranch
case "head_sha":
return *run.HeadSHA
case "run_number":
return strconv.Itoa(*run.RunNumber)
case "workflow_id":
return strconv.FormatInt(*run.WorkflowID, 10)
case "actor":
return getActorLogin(&run)
case "workflow":
r, exist := workflows[repo]
if !exist {
log.Printf("Couldn't fetch repo '%s' from workflow cache.", repo)
return "unknown"
}
w, exist := r[*run.WorkflowID]
if !exist {
log.Printf("Couldn't fetch repo '%s', workflow '%d' from workflow cache.", repo, *run.WorkflowID)
return "unknown"
}
return *w.Name
case "event":
return *run.Event
case "status":
return *run.Status
}
log.Printf("Tried to fetch invalid field '%s'", field)
return ""
}
func getActorLogin(run *github.WorkflowRun) string {
return run.Actor.GetLogin()
}
func getRelevantFields(repo string, run *github.WorkflowRun) []string {
relevantFields := strings.Split(config.WorkflowFields, ",")
result := make([]string, len(relevantFields))
for i, field := range relevantFields {
result[i] = getFieldValue(repo, *run, field)
}
return result
}
func getRecentWorkflowRuns(owner string, repo string) []*github.WorkflowRun {
window_start := time.Now().Add(time.Duration(-12) * time.Hour).Format(time.RFC3339)
opt := &github.ListWorkflowRunsOptions{
ListOptions: github.ListOptions{PerPage: 200},
Created: ">=" + window_start,
}
var runs []*github.WorkflowRun
for {
resp, rr, err := client.Actions.ListRepositoryWorkflowRuns(context.Background(), owner, repo, opt)
if rl_err, ok := err.(*github.RateLimitError); ok {
log.Printf("ListRepositoryWorkflowRuns ratelimited. Pausing until %s", rl_err.Rate.Reset.Time.String())
time.Sleep(time.Until(rl_err.Rate.Reset.Time))
continue
} else if err != nil {
log.Printf("ListRepositoryWorkflowRuns error for repo %s/%s: %s", owner, repo, err.Error())
return runs
}
runs = append(runs, resp.WorkflowRuns...)
if rr.NextPage == 0 {
break
}
opt.Page = rr.NextPage
}
return runs
}
func getRunUsage(owner string, repo string, runId int64) *github.WorkflowRunUsage {
for {
resp, _, err := client.Actions.GetWorkflowRunUsageByID(context.Background(), owner, repo, runId)
if rl_err, ok := err.(*github.RateLimitError); ok {
log.Printf("GetWorkflowRunUsageByID ratelimited. Pausing until %s", rl_err.Rate.Reset.Time.String())
time.Sleep(time.Until(rl_err.Rate.Reset.Time))
continue
} else if err != nil {
log.Printf("GetWorkflowRunUsageByID error for repo %s/%s and runId %d: %s", owner, repo, runId, err.Error())
return nil
}
return resp
}
}
// getWorkflowRunsFromGithub - return informations and status about a workflow
func getWorkflowRunsFromGithub() {
for {
for _, repo := range repositories {
r := strings.Split(repo, "/")
runs := getRecentWorkflowRuns(r[0], r[1])
for _, run := range runs {
var s float64 = 0
if run.GetConclusion() == "success" {
s = 1
} else if run.GetConclusion() == "skipped" {
s = 2
} else if run.GetConclusion() == "in_progress" {
s = 3
} else if run.GetConclusion() == "queued" {
s = 4
}
fields := getRelevantFields(repo, run)
workflowRunStatusGauge.WithLabelValues(fields...).Set(s)
var run_usage *github.WorkflowRunUsage = nil
if config.Metrics.FetchWorkflowRunUsage {
run_usage = getRunUsage(r[0], r[1], *run.ID)
}
if run_usage == nil { // Fallback for Github Enterprise
created := run.CreatedAt.Time.Unix()
updated := run.UpdatedAt.Time.Unix()
elapsed := updated - created
workflowRunDurationGauge.WithLabelValues(fields...).Set(float64(elapsed * 1000))
} else {
workflowRunDurationGauge.WithLabelValues(fields...).Set(float64(run_usage.GetRunDurationMS()))
}
}
}
time.Sleep(time.Duration(config.Github.Refresh) * time.Second)
}
}