Skip to content

Commit fdc0060

Browse files
author
chhsia0
committed
Supported RepositoryService.UpdatedHook in GitLab driver.
Note that the returned hook events are changed to reflect the actual parameter names used to create or update the webhook. Specifically, the original `convertEvents` in the GitLab driver sets the value of `Hook.Events` with the following mapping: ``` issues_events=true -> "issue" tag_push_events=true -> "tag" push_events=true -> "push" note_events=true -> "comment" merge_requests_events=true -> "merge" other options -> none ``` It seems the event name strings are arbitrary and not consistent across different drivers, so the mapping itself doesn't provide much abstraction (if any). More importantly, for all other drivers, `Hook.Events` contains native events unrecognized by go-scm, but GitLab driver completely discards them. This is important to implement logics to "reconcile" webhooks (i.e., update only if needed) to sync the list of watched events. Therefore, this patch proposes `Hook.Events` returned by the hook-related functions in the GitLab driver to store the option names if their values are true, e.g., `["issues_events", "push_events", "confidential_issues_events"]`. This is a breaking change.
1 parent 06c5ede commit fdc0060

File tree

5 files changed

+223
-92
lines changed

5 files changed

+223
-92
lines changed

scm/driver/gitlab/repo.go

Lines changed: 78 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"context"
99
"fmt"
1010
"net/url"
11+
"sort"
1112
"strconv"
1213
"strings"
1314
"time"
@@ -46,19 +47,22 @@ type access struct {
4647
}
4748

4849
type hook struct {
49-
ID int `json:"id"`
50-
URL string `json:"url"`
51-
ProjectID int `json:"project_id"`
52-
PushEvents bool `json:"push_events"`
53-
IssuesEvents bool `json:"issues_events"`
54-
MergeRequestsEvents bool `json:"merge_requests_events"`
55-
TagPushEvents bool `json:"tag_push_events"`
56-
NoteEvents bool `json:"note_events"`
57-
JobEvents bool `json:"job_events"`
58-
PipelineEvents bool `json:"pipeline_events"`
59-
WikiPageEvents bool `json:"wiki_page_events"`
60-
EnableSslVerification bool `json:"enable_ssl_verification"`
61-
CreatedAt time.Time `json:"created_at"`
50+
ID int `json:"id"`
51+
URL string `json:"url"`
52+
ProjectID int `json:"project_id"`
53+
PushEvents bool `json:"push_events"`
54+
IssuesEvents bool `json:"issues_events"`
55+
ConfidentialIssuesEvents bool `json:"confidential_issues_events"`
56+
MergeRequestsEvents bool `json:"merge_requests_events"`
57+
TagPushEvents bool `json:"tag_push_events"`
58+
NoteEvents bool `json:"note_events"`
59+
ConfidentialNoteEvents bool `json:"confidential_note_events"`
60+
JobEvents bool `json:"job_events"`
61+
PipelineEvents bool `json:"pipeline_events"`
62+
WikiPageEvents bool `json:"wiki_page_events"`
63+
DeploymentEvents bool `json:"deployment_events"`
64+
EnableSslVerification bool `json:"enable_ssl_verification"`
65+
CreatedAt time.Time `json:"created_at"`
6266
}
6367

6468
type repositoryService struct {
@@ -110,30 +114,13 @@ func (s *repositoryService) ListStatus(ctx context.Context, repo, ref string, op
110114
func (s *repositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) {
111115
params := url.Values{}
112116
params.Set("url", input.Target)
113-
if input.Secret != "" {
114-
params.Set("token", input.Secret)
117+
params.Set("token", input.Secret)
118+
params.Set("enable_ssl_verification", strconv.FormatBool(!input.SkipVerify))
119+
for k, v := range convertFromHookEvents(input.Events) {
120+
params.Set(k, strconv.FormatBool(v))
115121
}
116-
if input.SkipVerify {
117-
params.Set("enable_ssl_verification", "false")
118-
}
119-
if input.Events.Branch {
120-
// no-op
121-
}
122-
if input.Events.Issue {
123-
params.Set("issues_events", "true")
124-
}
125-
if input.Events.IssueComment ||
126-
input.Events.PullRequestComment {
127-
params.Set("note_events", "true")
128-
}
129-
if input.Events.PullRequest {
130-
params.Set("merge_requests_events", "true")
131-
}
132-
if input.Events.Push || input.Events.Branch {
133-
params.Set("push_events", "true")
134-
}
135-
if input.Events.Tag {
136-
params.Set("tag_push_events", "true")
122+
for _, k := range input.NativeEvents {
123+
params.Set(k, "true")
137124
}
138125

139126
path := fmt.Sprintf("api/v4/projects/%s/hooks?%s", encode(repo), params.Encode())
@@ -153,8 +140,22 @@ func (s *repositoryService) CreateStatus(ctx context.Context, repo, ref string,
153140
return convertStatus(out), res, err
154141
}
155142

156-
func (s *repositoryService) UpdateHook(ctx context.Context, repo string, id string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) {
157-
return nil, nil, scm.ErrNotSupported
143+
func (s *repositoryService) UpdateHook(ctx context.Context, repo, id string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) {
144+
params := url.Values{}
145+
params.Set("url", input.Target)
146+
params.Set("token", input.Secret)
147+
params.Set("enable_ssl_verification", strconv.FormatBool(!input.SkipVerify))
148+
for k, v := range convertFromHookEvents(input.Events) {
149+
params.Set(k, strconv.FormatBool(v))
150+
}
151+
for _, k := range input.NativeEvents {
152+
params.Set(k, "true")
153+
}
154+
155+
path := fmt.Sprintf("api/v4/projects/%s/hooks/%s?%s", encode(repo), id, params.Encode())
156+
out := new(hook)
157+
res, err := s.client.do(ctx, "PUT", path, nil, out)
158+
return convertHook(out), res, err
158159
}
159160

160161
func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id string) (*scm.Response, error) {
@@ -219,6 +220,45 @@ func convertHook(from *hook) *scm.Hook {
219220
}
220221
}
221222

223+
func convertFromHookEvents(from scm.HookEvents) map[string]bool {
224+
return map[string]bool{
225+
"push_events": from.Push || from.Branch,
226+
"issues_events": from.Issue,
227+
"merge_requests_events": from.PullRequest,
228+
"confidential_issues_events": false,
229+
"tag_push_events": from.Tag,
230+
"note_events": from.IssueComment || from.PullRequestComment || from.ReviewComment,
231+
"confidential_note_events": false,
232+
"job_events": false,
233+
"pipeline_events": false,
234+
"wiki_page_events": false,
235+
"deployment_events": from.Deployment,
236+
}
237+
}
238+
239+
func convertEvents(from *hook) []string {
240+
var events []string
241+
for k, v := range map[string]bool{
242+
"push_events": from.PushEvents,
243+
"issues_events": from.IssuesEvents,
244+
"merge_requests_events": from.MergeRequestsEvents,
245+
"confidential_issues_events": from.ConfidentialIssuesEvents,
246+
"tag_push_events": from.TagPushEvents,
247+
"note_events": from.NoteEvents,
248+
"confidential_note_events": from.ConfidentialNoteEvents,
249+
"job_events": from.JobEvents,
250+
"pipeline_events": from.PipelineEvents,
251+
"wiki_page_events": from.WikiPageEvents,
252+
"deployment_events": from.DeploymentEvents,
253+
} {
254+
if v {
255+
events = append(events, k)
256+
}
257+
}
258+
sort.Strings(events)
259+
return events
260+
}
261+
222262
type status struct {
223263
Name string `json:"name"`
224264
Desc null.String `json:"description"`
@@ -247,26 +287,6 @@ func convertStatus(from *status) *scm.Status {
247287
}
248288
}
249289

250-
func convertEvents(from *hook) []string {
251-
var events []string
252-
if from.IssuesEvents {
253-
events = append(events, "issues")
254-
}
255-
if from.TagPushEvents {
256-
events = append(events, "tag")
257-
}
258-
if from.PushEvents {
259-
events = append(events, "push")
260-
}
261-
if from.NoteEvents {
262-
events = append(events, "comment")
263-
}
264-
if from.MergeRequestsEvents {
265-
events = append(events, "merge")
266-
}
267-
return events
268-
}
269-
270290
func convertState(from string) scm.State {
271291
switch from {
272292
case "canceled":

0 commit comments

Comments
 (0)