@@ -7,13 +7,16 @@ import (
77 "github.com/google/go-github/v61/github"
88 "github.com/prometheus/client_golang/prometheus"
99 "github.com/webdevops/go-common/prometheus/collector"
10+ "github.com/webdevops/go-common/utils/to"
1011)
1112
1213type (
1314 MetricsCollectorGithubWorkflows struct {
1415 collector.Processor
1516
1617 prometheus struct {
18+ repository * prometheus.GaugeVec
19+ workflow * prometheus.GaugeVec
1720 workflowLatestRun * prometheus.GaugeVec
1821 workflowLatestRunTimestamp * prometheus.GaugeVec
1922 workflowConsecutiveFailures * prometheus.GaugeVec
@@ -24,6 +27,34 @@ type (
2427func (m * MetricsCollectorGithubWorkflows ) Setup (collector * collector.Collector ) {
2528 m .Processor .Setup (collector )
2629
30+ m .prometheus .repository = prometheus .NewGaugeVec (
31+ prometheus.GaugeOpts {
32+ Name : "github_repository_info" ,
33+ Help : "GitHub repository info" ,
34+ },
35+ []string {
36+ "org" ,
37+ "repo" ,
38+ "defaultBranch" ,
39+ },
40+ )
41+ m .Collector .RegisterMetricList ("repository" , m .prometheus .repository , true )
42+
43+ m .prometheus .workflow = prometheus .NewGaugeVec (
44+ prometheus.GaugeOpts {
45+ Name : "github_workflow_info" ,
46+ Help : "GitHub workflow info" ,
47+ },
48+ []string {
49+ "org" ,
50+ "repo" ,
51+ "workflow" ,
52+ "state" ,
53+ "path" ,
54+ },
55+ )
56+ m .Collector .RegisterMetricList ("workflow" , m .prometheus .workflow , true )
57+
2758 m .prometheus .workflowLatestRun = prometheus .NewGaugeVec (
2859 prometheus.GaugeOpts {
2960 Name : "github_workflow_latest_run" ,
@@ -32,7 +63,7 @@ func (m *MetricsCollectorGithubWorkflows) Setup(collector *collector.Collector)
3263 []string {
3364 "org" ,
3465 "repo" ,
35- "workflowName " ,
66+ "workflow " ,
3667 "event" ,
3768 "branch" ,
3869 "conclusion" ,
@@ -48,7 +79,7 @@ func (m *MetricsCollectorGithubWorkflows) Setup(collector *collector.Collector)
4879 []string {
4980 "org" ,
5081 "repo" ,
51- "workflowName " ,
82+ "workflow " ,
5283 "event" ,
5384 "branch" ,
5485 "conclusion" ,
@@ -64,7 +95,7 @@ func (m *MetricsCollectorGithubWorkflows) Setup(collector *collector.Collector)
6495 []string {
6596 "org" ,
6697 "repo" ,
67- "workflowName " ,
98+ "workflow " ,
6899 "branch" ,
69100 },
70101 )
@@ -76,12 +107,12 @@ func (m *MetricsCollectorGithubWorkflows) Reset() {}
76107func (m * MetricsCollectorGithubWorkflows ) getRepoList (org string ) ([]* github.Repository , error ) {
77108 var repositories []* github.Repository
78109
79- repoOpts := & github.RepositoryListByOrgOptions {
110+ opts := github.RepositoryListByOrgOptions {
80111 ListOptions : github.ListOptions {PerPage : 100 , Page : 1 },
81112 }
82113
83114 for {
84- result , response , err := githubClient .Repositories .ListByOrg (m .Context (), org , repoOpts )
115+ result , response , err := githubClient .Repositories .ListByOrg (m .Context (), org , & opts )
85116 var ghRateLimitError * github.RateLimitError
86117 if ok := errors .As (err , & ghRateLimitError ); ok {
87118 m .Logger ().Debugf ("ListByOrg ratelimited. Pausing until %s" , ghRateLimitError .Rate .Reset .Time .String ())
@@ -97,26 +128,54 @@ func (m *MetricsCollectorGithubWorkflows) getRepoList(org string) ([]*github.Rep
97128 if response .NextPage == 0 {
98129 break
99130 }
100- repoOpts .Page = response .NextPage
131+ opts .Page = response .NextPage
101132 }
102133
103134 return repositories , nil
104135}
105136
106- func (m * MetricsCollectorGithubWorkflows ) getRepoWorkflows (repo * github.Repository ) ([]* github.WorkflowRun , error ) {
137+ func (m * MetricsCollectorGithubWorkflows ) getRepoWorkflows (org , repo string ) ([]* github.Workflow , error ) {
138+ var workflows []* github.Workflow
139+
140+ opts := github.ListOptions {PerPage : 100 , Page : 1 }
141+
142+ for {
143+ result , response , err := githubClient .Actions .ListWorkflows (m .Context (), org , repo , & opts )
144+ var ghRateLimitError * github.RateLimitError
145+ if ok := errors .As (err , & ghRateLimitError ); ok {
146+ m .Logger ().Debugf ("ListWorkflows ratelimited. Pausing until %s" , ghRateLimitError .Rate .Reset .Time .String ())
147+ time .Sleep (time .Until (ghRateLimitError .Rate .Reset .Time ))
148+ continue
149+ } else if err != nil {
150+ return workflows , err
151+ }
152+
153+ workflows = append (workflows , result .Workflows ... )
154+
155+ // calc next page
156+ if response .NextPage == 0 {
157+ break
158+ }
159+ opts .Page = response .NextPage
160+ }
161+
162+ return workflows , nil
163+ }
164+
165+ func (m * MetricsCollectorGithubWorkflows ) getRepoWorkflowRuns (repo * github.Repository ) ([]* github.WorkflowRun , error ) {
107166 var workflowRuns []* github.WorkflowRun
108167
109- workflowRunOpts := & github.ListWorkflowRunsOptions {
168+ opts := github.ListWorkflowRunsOptions {
110169 Branch : repo .GetDefaultBranch (),
111170 ExcludePullRequests : true ,
112171 ListOptions : github.ListOptions {PerPage : 100 , Page : 1 },
113172 Created : ">=" + time .Now ().Add (- Opts .GitHub .Workflows .Timeframe ).Format (time .RFC3339 ),
114173 }
115174
116175 for {
117- m .Logger ().Debugf (`fetching list of workflow runs for repo "%s" with page "%d"` , repo .GetName (), workflowRunOpts .Page )
176+ m .Logger ().Debugf (`fetching list of workflow runs for repo "%s" with page "%d"` , repo .GetName (), opts .Page )
118177
119- result , response , err := githubClient .Actions .ListRepositoryWorkflowRuns (m .Context (), Opts .GitHub .Organization , * repo .Name , workflowRunOpts )
178+ result , response , err := githubClient .Actions .ListRepositoryWorkflowRuns (m .Context (), Opts .GitHub .Organization , * repo .Name , & opts )
120179 var ghRateLimitError * github.RateLimitError
121180 if ok := errors .As (err , & ghRateLimitError ); ok {
122181 m .Logger ().Debugf ("ListRepositoryWorkflowRuns ratelimited. Pausing until %s" , ghRateLimitError .Rate .Reset .Time .String ())
@@ -132,34 +191,62 @@ func (m *MetricsCollectorGithubWorkflows) getRepoWorkflows(repo *github.Reposito
132191 if response .NextPage == 0 {
133192 break
134193 }
135- workflowRunOpts .Page = response .NextPage
194+ opts .Page = response .NextPage
136195 }
137196
138197 return workflowRuns , nil
139198}
140199
141200func (m * MetricsCollectorGithubWorkflows ) Collect (callback chan <- func ()) {
142- repositories , err := m .getRepoList (Opts .GitHub .Organization )
201+ repositoryMetric := m .Collector .GetMetricList ("repository" )
202+ workflowMetric := m .Collector .GetMetricList ("workflow" )
203+
204+ org := Opts .GitHub .Organization
205+
206+ repositories , err := m .getRepoList (org )
143207 if err != nil {
144208 panic (err )
145209 }
146210
147211 for _ , repo := range repositories {
148212 var workflowRuns []* github.WorkflowRun
149213
214+ repositoryMetric .AddInfo (prometheus.Labels {
215+ "org" : org ,
216+ "repo" : repo .GetName (),
217+ "defaultBranch" : to .String (repo .DefaultBranch ),
218+ })
219+
150220 if repo .GetDefaultBranch () == "" {
151221 // repo doesn't have default branch
152222 continue
153223 }
154224
155- workflowRuns , err := m .getRepoWorkflows (repo )
225+ workflows , err := m .getRepoWorkflows (org , repo . GetName () )
156226 if err != nil {
157227 panic (err )
158228 }
159229
230+ for _ , workflow := range workflows {
231+ workflowMetric .AddInfo (prometheus.Labels {
232+ "org" : org ,
233+ "repo" : repo .GetName (),
234+ "workflow" : workflow .GetName (),
235+ "state" : workflow .GetState (),
236+ "path" : workflow .GetPath (),
237+ })
238+ }
239+
160240 if len (workflowRuns ) >= 1 {
161- m .collectLatestRun (Opts .GitHub .Organization , repo , workflowRuns , callback )
162- m .collectConsecutiveFailures (Opts .GitHub .Organization , repo , workflowRuns , callback )
241+ workflowRuns , err := m .getRepoWorkflowRuns (repo )
242+ if err != nil {
243+ panic (err )
244+ }
245+
246+ if len (workflowRuns ) >= 1 {
247+ m .collectLatestRun (Opts .GitHub .Organization , repo , workflowRuns , callback )
248+ m .collectConsecutiveFailures (Opts .GitHub .Organization , repo , workflowRuns , callback )
249+ }
163250 }
164251 }
165252}
@@ -201,12 +288,12 @@ func (m *MetricsCollectorGithubWorkflows) collectLatestRun(org string, repo *git
201288
202289 for _ , workflowRun := range latestJobs {
203290 labels := prometheus.Labels {
204- "org" : org ,
205- "repo" : repo .GetName (),
206- "workflowName" : workflowRun .GetName (),
207- "event" : workflowRun .GetEvent (),
208- "branch" : workflowRun .GetHeadBranch (),
209- "conclusion" : workflowRun .GetConclusion (),
291+ "org" : org ,
292+ "repo" : repo .GetName (),
293+ "workflow" : workflowRun .GetName (),
294+ "event" : workflowRun .GetEvent (),
295+ "branch" : workflowRun .GetHeadBranch (),
296+ "conclusion" : workflowRun .GetConclusion (),
210297 }
211298
212299 runMetric .AddInfo (labels )
@@ -258,10 +345,10 @@ func (m *MetricsCollectorGithubWorkflows) collectConsecutiveFailures(org string,
258345 }
259346
260347 labels := prometheus.Labels {
261- "org" : org ,
262- "repo" : repo .GetName (),
263- "workflowName " : workflowRun .GetName (),
264- "branch" : workflowRun .GetHeadBranch (),
348+ "org" : org ,
349+ "repo" : repo .GetName (),
350+ "workflow " : workflowRun .GetName (),
351+ "branch" : workflowRun .GetHeadBranch (),
265352 }
266353 consecutiveFailuresMetric .Add (labels , float64 (consecutiveFailMap [workflowId ]))
267354 }
0 commit comments