• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mvisonneau / gitlab-ci-pipelines-exporter / 20995478763

14 Jan 2026 01:16PM UTC coverage: 62.984% (+0.007%) from 62.977%
20995478763

push

github

mvisonneau
ci: made a bunch of config changes

3694 of 5865 relevant lines covered (62.98%)

3.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.0
/pkg/gitlab/client.go
1
package gitlab
2

3
import (
4
        "context"
5
        "crypto/tls"
6
        "fmt"
7
        "net/http"
8
        "strconv"
9
        "sync"
10
        "sync/atomic"
11
        "time"
12

13
        "github.com/heptiolabs/healthcheck"
14
        "github.com/paulbellamy/ratecounter"
15
        goGitlab "gitlab.com/gitlab-org/api/client-go"
16
        "go.opentelemetry.io/otel"
17
        "golang.org/x/oauth2"
18

19
        "github.com/mvisonneau/gitlab-ci-pipelines-exporter/pkg/ratelimit"
20
)
21

22
const (
23
        userAgent  = "gitlab-ci-pipelines-exporter"
24
        tracerName = "gitlab-ci-pipelines-exporter"
25
)
26

27
// Client ..
28
type Client struct {
29
        *goGitlab.Client
30

31
        Readiness struct {
32
                URL        string
33
                HTTPClient *http.Client
34
        }
35

36
        RateLimiter       ratelimit.Limiter
37
        RateCounter       *ratecounter.RateCounter
38
        RequestsCounter   atomic.Uint64
39
        RequestsLimit     int
40
        RequestsRemaining int
41

42
        version GitLabVersion
43
        mutex   sync.RWMutex
44
}
45

46
// ClientConfig ..
47
type ClientConfig struct {
48
        URL              string
49
        Token            string
50
        UserAgentVersion string
51
        DisableTLSVerify bool
52
        ReadinessURL     string
53

54
        RateLimiter ratelimit.Limiter
55
}
56

57
// NewHTTPClient ..
58
func NewHTTPClient(disableTLSVerify bool) *http.Client {
4✔
59
        // http.DefaultTransport contains useful settings such as the correct values for the picking
4✔
60
        // up proxy information from env variables
4✔
61
        transport := http.DefaultTransport.(*http.Transport).Clone()
4✔
62

4✔
63
        // nolint:gosec
4✔
64
        transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: disableTLSVerify}
4✔
65

4✔
66
        return &http.Client{
4✔
67
                Transport: transport,
4✔
68
        }
4✔
69
}
4✔
70

71
// NewClient ..
72
func NewClient(cfg ClientConfig) (*Client, error) {
1✔
73
        opts := []goGitlab.ClientOptionFunc{
1✔
74
                goGitlab.WithHTTPClient(NewHTTPClient(cfg.DisableTLSVerify)),
1✔
75
                goGitlab.WithBaseURL(cfg.URL),
1✔
76
                goGitlab.WithoutRetries(),
1✔
77
        }
1✔
78

1✔
79
        ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: cfg.Token})
1✔
80
        gc, err := goGitlab.NewAuthSourceClient(goGitlab.OAuthTokenSource{TokenSource: ts}, opts...)
1✔
81
        if err != nil {
1✔
82
                return nil, err
×
83
        }
×
84

85
        gc.UserAgent = fmt.Sprintf("%s-%s", userAgent, cfg.UserAgentVersion)
1✔
86

1✔
87
        readinessCheckHTTPClient := NewHTTPClient(cfg.DisableTLSVerify)
1✔
88
        readinessCheckHTTPClient.Timeout = 5 * time.Second
1✔
89

1✔
90
        return &Client{
1✔
91
                Client:      gc,
1✔
92
                RateLimiter: cfg.RateLimiter,
1✔
93
                Readiness: struct {
1✔
94
                        URL        string
1✔
95
                        HTTPClient *http.Client
1✔
96
                }{
1✔
97
                        URL:        cfg.ReadinessURL,
1✔
98
                        HTTPClient: readinessCheckHTTPClient,
1✔
99
                },
1✔
100
                RateCounter: ratecounter.NewRateCounter(time.Second),
1✔
101
        }, nil
1✔
102
}
103

104
// ReadinessCheck ..
105
func (c *Client) ReadinessCheck(ctx context.Context) healthcheck.Check {
1✔
106
        ctx, span := otel.Tracer(tracerName).Start(ctx, "gitlab:ReadinessCheck")
1✔
107
        defer span.End()
1✔
108

1✔
109
        return func() error {
4✔
110
                if c.Readiness.HTTPClient == nil {
4✔
111
                        return fmt.Errorf("readiness http client not configured")
1✔
112
                }
1✔
113

114
                req, err := http.NewRequestWithContext(
2✔
115
                        ctx,
2✔
116
                        http.MethodGet,
2✔
117
                        c.Readiness.URL,
2✔
118
                        nil,
2✔
119
                )
2✔
120
                if err != nil {
2✔
121
                        return err
×
122
                }
×
123

124
                resp, err := c.Readiness.HTTPClient.Do(req)
2✔
125
                if err != nil {
2✔
126
                        return err
×
127
                }
×
128

129
                if resp == nil {
2✔
130
                        return fmt.Errorf("HTTP error: empty response")
×
131
                }
×
132
                defer func() { _ = resp.Body.Close() }()
4✔
133

134
                if err == nil && resp.StatusCode != http.StatusOK {
3✔
135
                        return fmt.Errorf("HTTP error: %d", resp.StatusCode)
1✔
136
                }
1✔
137

138
                return nil
1✔
139
        }
140
}
141

142
func (c *Client) rateLimit(ctx context.Context) {
56✔
143
        ctx, span := otel.Tracer(tracerName).Start(ctx, "gitlab:rateLimit")
56✔
144
        defer span.End()
56✔
145

56✔
146
        ratelimit.Take(ctx, c.RateLimiter)
56✔
147
        // Used for monitoring purposes
56✔
148
        c.RateCounter.Incr(1)
56✔
149
        c.RequestsCounter.Add(1)
56✔
150
}
56✔
151

152
func (c *Client) UpdateVersion(version GitLabVersion) {
2✔
153
        c.mutex.Lock()
2✔
154
        defer c.mutex.Unlock()
2✔
155
        c.version = version
2✔
156
}
2✔
157

158
func (c *Client) Version() GitLabVersion {
6✔
159
        c.mutex.RLock()
6✔
160
        defer c.mutex.RUnlock()
6✔
161

6✔
162
        return c.version
6✔
163
}
6✔
164

165
func (c *Client) requestsRemaining(response *goGitlab.Response) {
47✔
166
        if response == nil {
47✔
167
                return
×
168
        }
×
169

170
        if remaining := response.Header.Get("ratelimit-remaining"); remaining != "" {
47✔
171
                c.RequestsRemaining, _ = strconv.Atoi(remaining)
×
172
        }
×
173

174
        if limit := response.Header.Get("ratelimit-limit"); limit != "" {
47✔
175
                c.RequestsLimit, _ = strconv.Atoi(limit)
×
176
        }
×
177
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc