-
Notifications
You must be signed in to change notification settings - Fork 239
/
pipelines.go
140 lines (119 loc) · 3.49 KB
/
pipelines.go
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
package controller
import (
"fmt"
"reflect"
"github.com/mvisonneau/gitlab-ci-pipelines-exporter/pkg/schemas"
log "github.com/sirupsen/logrus"
goGitlab "github.com/xanzy/go-gitlab"
)
// PullRefMetrics ..
func (c *Controller) PullRefMetrics(ref schemas.Ref) error {
// At scale, the scheduled ref may be behind the actual state being stored
// to avoid issues, we refresh it from the store before manipulating it
if err := c.Store.GetRef(&ref); err != nil {
return err
}
logFields := log.Fields{
"project-name": ref.Project.Name,
"ref": ref.Name,
"ref-kind": ref.Kind,
}
// We need a different syntax if the ref is a merge-request
var refName string
if ref.Kind == schemas.RefKindMergeRequest {
refName = fmt.Sprintf("refs/merge-requests/%s/head", ref.Name)
} else {
refName = ref.Name
}
pipelines, _, err := c.Gitlab.GetProjectPipelines(ref.Project.Name, &goGitlab.ListProjectPipelinesOptions{
// We only need the most recent pipeline
ListOptions: goGitlab.ListOptions{
PerPage: 1,
Page: 1,
},
Ref: &refName,
})
if err != nil {
return fmt.Errorf("error fetching project pipelines for %s: %v", ref.Project.Name, err)
}
if len(pipelines) == 0 {
log.WithFields(logFields).Debug("could not find any pipeline for the ref")
return nil
}
pipeline, err := c.Gitlab.GetRefPipeline(ref, pipelines[0].ID)
if err != nil {
return err
}
if ref.LatestPipeline.ID == 0 || !reflect.DeepEqual(pipeline, ref.LatestPipeline) {
formerPipeline := ref.LatestPipeline
ref.LatestPipeline = pipeline
// fetch pipeline variables
if ref.Project.Pull.Pipeline.Variables.Enabled {
ref.LatestPipeline.Variables, err = c.Gitlab.GetRefPipelineVariablesAsConcatenatedString(ref)
if err != nil {
return err
}
}
// Update the ref in the store
if err = c.Store.SetRef(ref); err != nil {
return err
}
// If the metric does not exist yet, start with 0 instead of 1
// this could cause some false positives in prometheus
// when restarting the exporter otherwise
runCount := schemas.Metric{
Kind: schemas.MetricKindRunCount,
Labels: ref.DefaultLabelsValues(),
}
storeGetMetric(c.Store, &runCount)
if formerPipeline.ID != 0 {
runCount.Value++
}
storeSetMetric(c.Store, runCount)
storeSetMetric(c.Store, schemas.Metric{
Kind: schemas.MetricKindCoverage,
Labels: ref.DefaultLabelsValues(),
Value: pipeline.Coverage,
})
storeSetMetric(c.Store, schemas.Metric{
Kind: schemas.MetricKindID,
Labels: ref.DefaultLabelsValues(),
Value: float64(pipeline.ID),
})
emitStatusMetric(
c.Store,
schemas.MetricKindStatus,
ref.DefaultLabelsValues(),
statusesList[:],
pipeline.Status,
ref.Project.OutputSparseStatusMetrics,
)
storeSetMetric(c.Store, schemas.Metric{
Kind: schemas.MetricKindDurationSeconds,
Labels: ref.DefaultLabelsValues(),
Value: pipeline.DurationSeconds,
})
storeSetMetric(c.Store, schemas.Metric{
Kind: schemas.MetricKindQueuedDurationSeconds,
Labels: ref.DefaultLabelsValues(),
Value: pipeline.QueuedDurationSeconds,
})
storeSetMetric(c.Store, schemas.Metric{
Kind: schemas.MetricKindTimestamp,
Labels: ref.DefaultLabelsValues(),
Value: pipeline.Timestamp,
})
if ref.Project.Pull.Pipeline.Jobs.Enabled {
if err := c.PullRefPipelineJobsMetrics(ref); err != nil {
return err
}
}
return nil
}
if ref.Project.Pull.Pipeline.Jobs.Enabled {
if err := c.PullRefMostRecentJobsMetrics(ref); err != nil {
return err
}
}
return nil
}