-
Notifications
You must be signed in to change notification settings - Fork 117
/
gitlab.go
192 lines (170 loc) · 4.82 KB
/
gitlab.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
package gitlab
import (
"context"
"net/url"
"strings"
"github.com/xanzy/go-gitlab"
"github.com/akuity/kargo/internal/gitprovider"
)
const (
GitProviderServiceName = "gitlab"
)
var (
registration = gitprovider.ProviderRegistration{
Predicate: func(repoURL string) bool {
u, err := url.Parse(repoURL)
if err != nil {
return false
}
// We assume that any hostname with the word "gitlab" in the hostname,
// can use this provider. NOTE: we will miss cases where the host is
// Gitlab but doesn't incorporate the word "gitlab" in the hostname.
// e.g. 'git.mycompany.com'
return strings.Contains(u.Host, GitProviderServiceName)
},
NewService: func() (gitprovider.GitProviderService, error) {
return NewGitLabProvider()
},
}
)
func init() {
gitprovider.RegisterProvider(GitProviderServiceName, registration)
}
type MergeRequestClient interface {
CreateMergeRequest(
pid any,
opt *gitlab.CreateMergeRequestOptions,
options ...gitlab.RequestOptionFunc,
) (*gitlab.MergeRequest, *gitlab.Response, error)
ListProjectMergeRequests(
pid any,
opt *gitlab.ListProjectMergeRequestsOptions,
options ...gitlab.RequestOptionFunc,
) ([]*gitlab.MergeRequest, *gitlab.Response, error)
GetMergeRequest(
pid any,
mergeRequest int,
opt *gitlab.GetMergeRequestsOptions,
options ...gitlab.RequestOptionFunc,
) (*gitlab.MergeRequest, *gitlab.Response, error)
}
type GitLabClient struct { // nolint: revive
MergeRequests MergeRequestClient
}
type GitLabProvider struct { // nolint: revive
client *GitLabClient
}
func NewGitLabProvider() (gitprovider.GitProviderService, error) {
client, err := gitlab.NewClient("")
if err != nil {
return nil, err
}
return &GitLabProvider{
client: &GitLabClient{MergeRequests: client.MergeRequests},
}, nil
}
func (g *GitLabProvider) WithAuthToken(token string) (gitprovider.GitProviderService, error) {
client, err := gitlab.NewClient(token)
if err != nil {
return nil, err
}
g.client = &GitLabClient{MergeRequests: client.MergeRequests}
return g, nil
}
func (g *GitLabProvider) CreatePullRequest(
_ context.Context,
repoURL string,
opts gitprovider.CreatePullRequestOpts,
) (*gitprovider.PullRequest, error) {
projectName, err := getProjectNameFromUrl(repoURL)
if err != nil {
return nil, err
}
glMR, _, err := g.client.MergeRequests.CreateMergeRequest(projectName, &gitlab.CreateMergeRequestOptions{
Title: &opts.Title,
Description: &opts.Description,
SourceBranch: &opts.Head,
TargetBranch: &opts.Base,
RemoveSourceBranch: gitlab.Ptr(true),
})
if err != nil {
return nil, err
}
return convertGitlabMR(glMR), nil
}
func (g *GitLabProvider) GetPullRequest(
_ context.Context,
repoURL string,
id int64,
) (*gitprovider.PullRequest, error) {
glMR, err := g.getMergeRequest(repoURL, id)
if err != nil {
return nil, err
}
return convertGitlabMR(glMR), nil
}
func (g *GitLabProvider) ListPullRequests(
_ context.Context,
repoURL string,
opts gitprovider.ListPullRequestOpts,
) ([]*gitprovider.PullRequest, error) {
projectName, err := getProjectNameFromUrl(repoURL)
if err != nil {
return nil, err
}
listOpts := &gitlab.ListProjectMergeRequestsOptions{
SourceBranch: &opts.Head,
TargetBranch: &opts.Base,
}
glMRs, _, err := g.client.MergeRequests.ListProjectMergeRequests(projectName, listOpts)
if err != nil {
return nil, err
}
prs := make([]*gitprovider.PullRequest, 0, len(glMRs))
for _, glMR := range glMRs {
if (opts.State == gitprovider.PullRequestStateOpen) == isMROpen(glMR) {
prs = append(prs, convertGitlabMR(glMR))
}
}
return prs, nil
}
func (g *GitLabProvider) IsPullRequestMerged(_ context.Context, repoURL string, id int64) (bool, error) {
glMR, err := g.getMergeRequest(repoURL, id)
if err != nil {
return false, err
}
return glMR.State == "merged", nil
}
func convertGitlabMR(glMR *gitlab.MergeRequest) *gitprovider.PullRequest {
var prState gitprovider.PullRequestState
if isMROpen(glMR) {
prState = gitprovider.PullRequestStateOpen
} else {
prState = gitprovider.PullRequestStateClosed
}
return &gitprovider.PullRequest{
Number: int64(glMR.IID),
URL: glMR.WebURL,
State: prState,
MergeCommitSHA: glMR.MergeCommitSHA,
Object: glMR,
}
}
func isMROpen(glMR *gitlab.MergeRequest) bool {
return glMR.State == "opened" || glMR.State == "locked"
}
func getProjectNameFromUrl(u string) (string, error) {
gitlabUrl, err := url.Parse(u)
if err != nil {
return "", err
}
return strings.TrimSuffix(strings.TrimPrefix(gitlabUrl.Path, "/"), ".git"), nil
}
func (g *GitLabProvider) getMergeRequest(repoURL string, id int64) (*gitlab.MergeRequest, error) {
projectName, err := getProjectNameFromUrl(repoURL)
if err != nil {
return nil, err
}
glMR, _, err := g.client.MergeRequests.GetMergeRequest(projectName, int(id), nil)
return glMR, err
}