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

mvisonneau / gitlab-ci-pipelines-exporter / 29748522538

20 Jul 2026 01:57PM UTC coverage: 60.0% (-1.8%) from 61.785%
29748522538

Pull #728

github

mathstuf
examples/quickstart: update grafana dashboards to consider source projects
Pull Request #728: Mr pipelines from fork

82 of 271 new or added lines in 7 files covered. (30.26%)

3 existing lines in 1 file now uncovered.

3642 of 6070 relevant lines covered (60.0%)

3.84 hits per line

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

87.97
/pkg/gitlab/projects.go
1
package gitlab
2

3
import (
4
        "context"
5
        "fmt"
6
        "regexp"
7

8
        log "github.com/sirupsen/logrus"
9
        goGitlab "gitlab.com/gitlab-org/api/client-go"
10
        "go.openly.dev/pointy"
11
        "go.opentelemetry.io/otel"
12
        "go.opentelemetry.io/otel/attribute"
13

14
        "github.com/mvisonneau/gitlab-ci-pipelines-exporter/pkg/config"
15
        "github.com/mvisonneau/gitlab-ci-pipelines-exporter/pkg/schemas"
16
)
17

18
// GetProject ..
19
func (c *Client) GetProject(ctx context.Context, name string) (*goGitlab.Project, error) {
1✔
20
        ctx, span := otel.Tracer(tracerName).Start(ctx, "gitlab:GetProject")
1✔
21
        defer span.End()
1✔
22
        span.SetAttributes(attribute.String("project_name", name))
1✔
23

1✔
24
        log.WithFields(log.Fields{
1✔
25
                "project-name": name,
1✔
26
        }).Debug("reading project")
1✔
27

1✔
28
        c.rateLimit(ctx)
1✔
29
        p, resp, err := c.Projects.GetProject(name, &goGitlab.GetProjectOptions{}, goGitlab.WithContext(ctx))
1✔
30
        c.requestsRemaining(resp)
1✔
31

1✔
32
        return p, err
1✔
33
}
1✔
34

35
// GetProjectByID ..
NEW
36
func (c *Client) GetProjectByID(ctx context.Context, id int64) (*goGitlab.Project, error) {
×
NEW
37
        ctx, span := otel.Tracer(tracerName).Start(ctx, "gitlab:GetProjectByID")
×
NEW
38
        defer span.End()
×
NEW
39
        span.SetAttributes(attribute.Int64("project_id", id))
×
NEW
40

×
NEW
41
        log.WithFields(log.Fields{
×
NEW
42
                "project-id": id,
×
NEW
43
        }).Debug("reading project")
×
NEW
44

×
NEW
45
        c.rateLimit(ctx)
×
NEW
46
        p, resp, err := c.Projects.GetProject(id, &goGitlab.GetProjectOptions{}, goGitlab.WithContext(ctx))
×
NEW
47
        c.requestsRemaining(resp)
×
NEW
48

×
NEW
49
        return p, err
×
NEW
50
}
×
51

52
// ListProjects ..
53
func (c *Client) ListProjects(ctx context.Context, w config.Wildcard) ([]schemas.Project, error) {
4✔
54
        ctx, span := otel.Tracer(tracerName).Start(ctx, "gitlab:ListProjects")
4✔
55
        defer span.End()
4✔
56
        span.SetAttributes(attribute.String("wildcard_search", w.Search))
4✔
57
        span.SetAttributes(attribute.String("wildcard_owner_kind", w.Owner.Kind))
4✔
58
        span.SetAttributes(attribute.String("wildcard_owner_name", w.Owner.Name))
4✔
59
        span.SetAttributes(attribute.Bool("wildcard_owner_include_subgroups", w.Owner.IncludeSubgroups))
4✔
60
        span.SetAttributes(attribute.Bool("wildcard_archived", w.Archived))
4✔
61

4✔
62
        logFields := log.Fields{
4✔
63
                "wildcard-search":                  w.Search,
4✔
64
                "wildcard-owner-kind":              w.Owner.Kind,
4✔
65
                "wildcard-owner-name":              w.Owner.Name,
4✔
66
                "wildcard-owner-include-subgroups": w.Owner.IncludeSubgroups,
4✔
67
                "wildcard-archived":                w.Archived,
4✔
68
        }
4✔
69
        log.WithFields(logFields).Debug("listing all projects from wildcard")
4✔
70

4✔
71
        var projects []schemas.Project
4✔
72

4✔
73
        listOptions := goGitlab.ListOptions{
4✔
74
                Page:    1,
4✔
75
                PerPage: 100,
4✔
76
        }
4✔
77

4✔
78
        // As a result, the API will return the projects that the owner has access onto.
4✔
79
        // This is not necessarily what we the end-user would intend when leveraging a
4✔
80
        // scoped wildcard. Therefore, if the wildcard owner name is set, we want to filter
4✔
81
        // out to project actually *belonging* to the owner.
4✔
82
        var ownerRegexp *regexp.Regexp
4✔
83

4✔
84
        if len(w.Owner.Name) > 0 {
7✔
85
                ownerRegexp = regexp.MustCompile(fmt.Sprintf(`^%s\/`, w.Owner.Name))
3✔
86
        } else {
4✔
87
                ownerRegexp = regexp.MustCompile(`.*`)
1✔
88
        }
1✔
89

90
        for {
8✔
91
                var (
4✔
92
                        gps  []*goGitlab.Project
4✔
93
                        resp *goGitlab.Response
4✔
94
                        err  error
4✔
95
                )
4✔
96

4✔
97
                c.rateLimit(ctx)
4✔
98

4✔
99
                switch w.Owner.Kind {
4✔
100
                case "user":
2✔
101
                        gps, resp, err = c.Projects.ListUserProjects(
2✔
102
                                w.Owner.Name,
2✔
103
                                &goGitlab.ListProjectsOptions{
2✔
104
                                        Archived:    &w.Archived,
2✔
105
                                        ListOptions: listOptions,
2✔
106
                                        Search:      &w.Search,
2✔
107
                                        Simple:      pointy.Bool(true),
2✔
108
                                },
2✔
109
                                goGitlab.WithContext(ctx),
2✔
110
                        )
2✔
111
                case "group":
1✔
112
                        gps, resp, err = c.Groups.ListGroupProjects(
1✔
113
                                w.Owner.Name,
1✔
114
                                &goGitlab.ListGroupProjectsOptions{
1✔
115
                                        Archived:         &w.Archived,
1✔
116
                                        WithShared:       pointy.Bool(false),
1✔
117
                                        IncludeSubGroups: &w.Owner.IncludeSubgroups,
1✔
118
                                        ListOptions:      listOptions,
1✔
119
                                        Search:           &w.Search,
1✔
120
                                        Simple:           pointy.Bool(true),
1✔
121
                                },
1✔
122
                                goGitlab.WithContext(ctx),
1✔
123
                        )
1✔
124
                default:
1✔
125
                        // List all visible projects
1✔
126
                        gps, resp, err = c.Projects.ListProjects(
1✔
127
                                &goGitlab.ListProjectsOptions{
1✔
128
                                        ListOptions: listOptions,
1✔
129
                                        Archived:    &w.Archived,
1✔
130
                                        Search:      &w.Search,
1✔
131
                                        Simple:      pointy.Bool(true),
1✔
132
                                },
1✔
133
                                goGitlab.WithContext(ctx),
1✔
134
                        )
1✔
135
                }
136

137
                if err != nil {
5✔
138
                        return projects, fmt.Errorf("unable to list projects with search pattern '%s' from the GitLab API : %v", w.Search, err.Error())
1✔
139
                }
1✔
140

141
                c.requestsRemaining(resp)
3✔
142

3✔
143
                // Copy relevant settings from wildcard into created project
3✔
144
                for _, gp := range gps {
8✔
145
                        if !ownerRegexp.MatchString(gp.PathWithNamespace) {
7✔
146
                                log.WithFields(logFields).WithFields(log.Fields{
2✔
147
                                        "project-id":   gp.ID,
2✔
148
                                        "project-name": gp.PathWithNamespace,
2✔
149
                                }).Debug("project path not matching owner's name, skipping")
2✔
150

2✔
151
                                continue
2✔
152
                        }
153

154
                        p := schemas.NewProject(gp.PathWithNamespace)
3✔
155
                        p.ProjectParameters = w.ProjectParameters
3✔
156
                        p.ID = gp.ID
3✔
157
                        projects = append(projects, p)
3✔
158
                }
159

160
                if resp.CurrentPage >= resp.NextPage {
6✔
161
                        break
3✔
162
                }
163

164
                listOptions.Page = resp.NextPage
×
165
        }
166

167
        return projects, nil
3✔
168
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc