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

mindersec / minder / 14376078638

10 Apr 2025 08:39AM UTC coverage: 56.857%. First build
14376078638

Pull #5515

github

web-flow
Merge ea220ae51 into 0f5ecd80e
Pull Request #5515: Don't return errors when getting properties

27 of 49 new or added lines in 22 files covered. (55.1%)

18305 of 32195 relevant lines covered (56.86%)

37.04 hits per line

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

0.0
/internal/providers/gitlab/pull_request_properties.go
1
// SPDX-FileCopyrightText: Copyright 2024 The Minder Authors
2
// SPDX-License-Identifier: Apache-2.0
3

4
package gitlab
5

6
import (
7
        "context"
8
        "encoding/json"
9
        "fmt"
10
        "net/http"
11
        "net/url"
12
        "strconv"
13

14
        gitlab "gitlab.com/gitlab-org/api/client-go"
15

16
        pbinternal "github.com/mindersec/minder/internal/proto"
17
        "github.com/mindersec/minder/pkg/entities/properties"
18
        provifv1 "github.com/mindersec/minder/pkg/providers/v1"
19
)
20

21
// FormatPullRequestUpstreamID returns the upstream ID for a gitlab merge request
22
// This is done so we don't have to deal with conversions in the provider
23
// when dealing with entities
24
func FormatPullRequestUpstreamID(id int) string {
×
25
        return fmt.Sprintf("%d", id)
×
26
}
×
27

28
//nolint:gocyclo // TODO: Refactor to reduce complexity
29
func (c *gitlabClient) getPropertiesForPullRequest(
30
        ctx context.Context, getByProps *properties.Properties,
31
) (*properties.Properties, error) {
×
32
        uid, err := getByProps.GetProperty(properties.PropertyUpstreamID).AsString()
×
33
        if err != nil {
×
34
                return nil, fmt.Errorf("upstream ID not found or invalid: %w", err)
×
35
        }
×
36

37
        iid, err := getByProps.GetProperty(PullRequestNumber).AsString()
×
38
        if err != nil {
×
39
                return nil, fmt.Errorf("merge request number not found or invalid: %w", err)
×
40
        }
×
41

42
        pid, err := getByProps.GetProperty(PullRequestProjectID).AsString()
×
43
        if err != nil {
×
44
                return nil, fmt.Errorf("project ID not found or invalid: %w", err)
×
45
        }
×
46

47
        mrURLPath, err := url.JoinPath("projects", pid, "merge_requests", iid)
×
48
        if err != nil {
×
49
                return nil, fmt.Errorf("failed to join URL path for merge request using upstream ID: %w", err)
×
50
        }
×
51

52
        // NOTE: We're not using github.com/xanzy/go-gitlab to do the actual
53
        // request here because of the way they form authentication for requests.
54
        // It would be ideal to use it, so we should consider contributing and making
55
        // that part more pluggable.
56
        req, err := c.NewRequest("GET", mrURLPath, nil)
×
57
        if err != nil {
×
58
                return nil, fmt.Errorf("failed to create request: %w", err)
×
59
        }
×
60

61
        resp, err := c.Do(ctx, req)
×
62
        if err != nil {
×
63
                return nil, fmt.Errorf("failed to get merge request: %w", err)
×
64
        }
×
65

66
        defer resp.Body.Close()
×
67

×
68
        if resp.StatusCode != http.StatusOK {
×
69
                if resp.StatusCode == http.StatusNotFound {
×
70
                        return nil, provifv1.ErrEntityNotFound
×
71
                }
×
72

73
                return nil, fmt.Errorf("failed to get merge request: %s", resp.Status)
×
74
        }
75

76
        mr := &gitlab.MergeRequest{}
×
77
        if err := json.NewDecoder(resp.Body).Decode(mr); err != nil {
×
78
                return nil, fmt.Errorf("failed to decode response: %w", err)
×
79
        }
×
80

81
        // Validate - merge request upstream ID must match the one we requested
82
        if res := FormatPullRequestUpstreamID(mr.ID); res != uid {
×
83
                return nil, fmt.Errorf("merge request ID mismatch: %s != %s", res, uid)
×
84
        }
×
85

86
        proj, err := c.getGitLabProject(ctx, pid)
×
87
        if err != nil {
×
88
                return nil, fmt.Errorf("failed to get project: %w", err)
×
89
        }
×
90

91
        targetproj := proj
×
92
        if mr.SourceProjectID != 0 && mr.SourceProjectID != proj.ID {
×
93
                targetproj, err = c.getGitLabProject(ctx, FormatRepositoryUpstreamID(mr.SourceProjectID))
×
94
                if err != nil {
×
95
                        return nil, fmt.Errorf("failed to get target project: %w", err)
×
96
                }
×
97
        }
98

99
        outProps, err := gitlabMergeRequestToProperties(mr, proj, targetproj)
×
100
        if err != nil {
×
101
                return nil, fmt.Errorf("failed to convert merge request to properties: %w", err)
×
102
        }
×
103

104
        return outProps, nil
×
105
}
106

107
func gitlabMergeRequestToProperties(
108
        mr *gitlab.MergeRequest, proj *gitlab.Project, targetproj *gitlab.Project) (*properties.Properties, error) {
×
109
        ns, err := getGitlabProjectNamespace(proj)
×
110
        if err != nil {
×
111
                return nil, fmt.Errorf("failed to get namespace: %w", err)
×
112
        }
×
113

114
        projName := proj.Name
×
115

×
NEW
116
        outProps := properties.NewProperties(map[string]any{
×
117
                // Unique upstream ID for the merge request
×
118
                properties.PropertyUpstreamID:           FormatPullRequestUpstreamID(mr.ID),
×
119
                properties.PropertyName:                 formatPullRequestName(ns, projName, FormatPullRequestUpstreamID(mr.IID)),
×
120
                properties.PullRequestCommitSHA:         mr.SHA,
×
121
                properties.PullRequestBaseCloneURL:      proj.HTTPURLToRepo,
×
122
                properties.PullRequestBaseDefaultBranch: mr.TargetBranch,
×
123
                properties.PullRequestTargetCloneURL:    targetproj.HTTPURLToRepo,
×
124
                properties.PullRequestTargetBranch:      mr.SourceBranch,
×
125
                properties.PullRequestUpstreamURL:       mr.WebURL,
×
126
                RepoPropertyNamespace:                   ns,
×
127
                RepoPropertyProjectName:                 projName,
×
128
                // internal ID of the merge request
×
129
                PullRequestNumber:    FormatPullRequestUpstreamID(mr.IID),
×
130
                PullRequestProjectID: FormatRepositoryUpstreamID(proj.ID),
×
131
                PullRequestAuthor:    int64(mr.Author.ID),
×
132
        })
×
133

×
134
        return outProps, nil
×
135
}
136

137
func pullRequestV1FromProperties(prProps *properties.Properties) (*pbinternal.PullRequest, error) {
×
138
        _, err := prProps.GetProperty(properties.PropertyUpstreamID).AsString()
×
139
        if err != nil {
×
140
                return nil, fmt.Errorf("failed to get upstream ID: %w", err)
×
141
        }
×
142

143
        iid, err := getStringProp(prProps, PullRequestNumber)
×
144
        if err != nil {
×
145
                return nil, fmt.Errorf("failed to get merge request number: %w", err)
×
146
        }
×
147

148
        ns, err := getStringProp(prProps, RepoPropertyNamespace)
×
149
        if err != nil {
×
150
                return nil, fmt.Errorf("failed to get namespace: %w", err)
×
151
        }
×
152

153
        projName, err := getStringProp(prProps, RepoPropertyProjectName)
×
154
        if err != nil {
×
155
                return nil, fmt.Errorf("failed to get project name: %w", err)
×
156
        }
×
157

158
        commitSha, err := getStringProp(prProps, properties.PullRequestCommitSHA)
×
159
        if err != nil {
×
160
                return nil, fmt.Errorf("failed to get commit SHA: %w", err)
×
161
        }
×
162

163
        mrURL, err := getStringProp(prProps, properties.PullRequestUpstreamURL)
×
164
        if err != nil {
×
165
                return nil, fmt.Errorf("failed to get merge request URL: %w", err)
×
166
        }
×
167

168
        authorID, err := prProps.GetProperty(PullRequestAuthor).AsInt64()
×
169
        if err != nil {
×
170
                return nil, fmt.Errorf("failed to get author ID: %w", err)
×
171
        }
×
172

173
        basecloneurl := prProps.GetProperty(properties.PullRequestBaseCloneURL).GetString()
×
174
        targetcloneurl := prProps.GetProperty(properties.PullRequestTargetCloneURL).GetString()
×
175
        basebranch := prProps.GetProperty(properties.PullRequestBaseDefaultBranch).GetString()
×
176
        targetbranch := prProps.GetProperty(properties.PullRequestTargetBranch).GetString()
×
177

×
178
        // parse UpstreamID to int64
×
179
        id, err := strconv.ParseInt(iid, 10, 64)
×
180
        if err != nil {
×
181
                return nil, fmt.Errorf("failed to parse upstream ID: %w", err)
×
182
        }
×
183

184
        pbPR := &pbinternal.PullRequest{
×
185
                Number:         id,
×
186
                RepoOwner:      ns,
×
187
                RepoName:       projName,
×
188
                CommitSha:      commitSha,
×
189
                AuthorId:       authorID,
×
190
                Url:            mrURL,
×
191
                BaseCloneUrl:   basecloneurl,
×
192
                TargetCloneUrl: targetcloneurl,
×
193
                BaseRef:        basebranch,
×
194
                TargetRef:      targetbranch,
×
195
                Properties:     prProps.ToProtoStruct(),
×
196
        }
×
197

×
198
        return pbPR, nil
×
199
}
200

201
func getPullRequestNameFromProperties(props *properties.Properties) (string, error) {
×
202
        groupName, err := getStringProp(props, RepoPropertyNamespace)
×
203
        if err != nil {
×
204
                return "", err
×
205
        }
×
206

207
        projectName, err := getStringProp(props, RepoPropertyProjectName)
×
208
        if err != nil {
×
209
                return "", err
×
210
        }
×
211

212
        iid, err := getStringProp(props, PullRequestNumber)
×
213
        if err != nil {
×
214
                return "", err
×
215
        }
×
216

217
        return formatPullRequestName(groupName, projectName, iid), nil
×
218
}
219

220
func formatPullRequestName(groupName, projectName, iid string) string {
×
221
        return fmt.Sprintf("%s/%s/%s", groupName, projectName, iid)
×
222
}
×
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

© 2025 Coveralls, Inc