Skip to content

Commit 82cb830

Browse files
authored
feat: adding support for multiple events in GitLab webhook (#696)
* feat: adding support for multiple events in GitLab webhook * chore: fixing build error * chore: fixing test error * chore: reverting back to travis until we fix circle ci memory issue * chore: remove defunct dockerfile * fix: gitlab event source events * fix: rename project id
1 parent df314d3 commit 82cb830

10 files changed

Lines changed: 128 additions & 183 deletions

File tree

Dockerfile

Lines changed: 0 additions & 17 deletions
This file was deleted.

api/event-source.html

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,24 +1114,24 @@ <h3 id="argoproj.io/v1alpha1.GitlabEventSource">GitlabEventSource
11141114
</tr>
11151115
<tr>
11161116
<td>
1117-
<code>projectId</code></br>
1117+
<code>projectID</code></br>
11181118
<em>
11191119
string
11201120
</em>
11211121
</td>
11221122
<td>
1123-
<p>ProjectId is the id of project for which integration needs to setup</p>
1123+
<p>ProjectID is the id of project for which integration needs to setup</p>
11241124
</td>
11251125
</tr>
11261126
<tr>
11271127
<td>
1128-
<code>event</code></br>
1128+
<code>events</code></br>
11291129
<em>
1130-
string
1130+
[]string
11311131
</em>
11321132
</td>
11331133
<td>
1134-
<p>Event is a gitlab event to listen to.
1134+
<p>Events are gitlab event to listen to.
11351135
Refer <a href="https://github.com/xanzy/go-gitlab/blob/bf34eca5d13a9f4c3f501d8a97b8ac226d55e4d9/projects.go#L794">https://github.com/xanzy/go-gitlab/blob/bf34eca5d13a9f4c3f501d8a97b8ac226d55e4d9/projects.go#L794</a>.</p>
11361136
</td>
11371137
</tr>
@@ -1173,18 +1173,6 @@ <h3 id="argoproj.io/v1alpha1.GitlabEventSource">GitlabEventSource
11731173
</tr>
11741174
<tr>
11751175
<td>
1176-
<code>namespace</code></br>
1177-
<em>
1178-
string
1179-
</em>
1180-
</td>
1181-
<td>
1182-
<em>(Optional)</em>
1183-
<p>Namespace refers to Kubernetes namespace which is used to retrieve access token from.</p>
1184-
</td>
1185-
</tr>
1186-
<tr>
1187-
<td>
11881176
<code>deleteHookOnFinish</code></br>
11891177
<em>
11901178
bool
@@ -1195,18 +1183,6 @@ <h3 id="argoproj.io/v1alpha1.GitlabEventSource">GitlabEventSource
11951183
<p>DeleteHookOnFinish determines whether to delete the GitLab hook for the project once the event source is stopped.</p>
11961184
</td>
11971185
</tr>
1198-
<tr>
1199-
<td>
1200-
<code>allowDuplicate</code></br>
1201-
<em>
1202-
bool
1203-
</em>
1204-
</td>
1205-
<td>
1206-
<p>AllowDuplicate allows the gateway to register the same webhook integrations for multiple event source configurations.
1207-
Defaults to false.</p>
1208-
</td>
1209-
</tr>
12101186
</tbody>
12111187
</table>
12121188
<h3 id="argoproj.io/v1alpha1.HDFSEventSource">HDFSEventSource

api/event-source.md

Lines changed: 4 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2193,15 +2193,15 @@ Webhook holds configuration to run a http server
21932193

21942194
<td>
21952195

2196-
<code>projectId</code></br> <em> string </em>
2196+
<code>projectID</code></br> <em> string </em>
21972197

21982198
</td>
21992199

22002200
<td>
22012201

22022202
<p>
22032203

2204-
ProjectId is the id of project for which integration needs to setup
2204+
ProjectID is the id of project for which integration needs to setup
22052205

22062206
</p>
22072207

@@ -2213,15 +2213,15 @@ ProjectId is the id of project for which integration needs to setup
22132213

22142214
<td>
22152215

2216-
<code>event</code></br> <em> string </em>
2216+
<code>events</code></br> <em> \[\]string </em>
22172217

22182218
</td>
22192219

22202220
<td>
22212221

22222222
<p>
22232223

2224-
Event is a gitlab event to listen to. Refer
2224+
Events are gitlab event to listen to. Refer
22252225
<a href="https://github.com/xanzy/go-gitlab/blob/bf34eca5d13a9f4c3f501d8a97b8ac226d55e4d9/projects.go#L794">https://github.com/xanzy/go-gitlab/blob/bf34eca5d13a9f4c3f501d8a97b8ac226d55e4d9/projects.go\#L794</a>.
22262226

22272227
</p>
@@ -2299,29 +2299,6 @@ GitlabBaseURL is the base URL for API requests to a custom endpoint
22992299

23002300
<td>
23012301

2302-
<code>namespace</code></br> <em> string </em>
2303-
2304-
</td>
2305-
2306-
<td>
2307-
2308-
<em>(Optional)</em>
2309-
2310-
<p>
2311-
2312-
Namespace refers to Kubernetes namespace which is used to retrieve
2313-
access token from.
2314-
2315-
</p>
2316-
2317-
</td>
2318-
2319-
</tr>
2320-
2321-
<tr>
2322-
2323-
<td>
2324-
23252302
<code>deleteHookOnFinish</code></br> <em> bool </em>
23262303

23272304
</td>
@@ -2341,28 +2318,6 @@ project once the event source is stopped.
23412318

23422319
</tr>
23432320

2344-
<tr>
2345-
2346-
<td>
2347-
2348-
<code>allowDuplicate</code></br> <em> bool </em>
2349-
2350-
</td>
2351-
2352-
<td>
2353-
2354-
<p>
2355-
2356-
AllowDuplicate allows the gateway to register the same webhook
2357-
integrations for multiple event source configurations. Defaults to
2358-
false.
2359-
2360-
</p>
2361-
2362-
</td>
2363-
2364-
</tr>
2365-
23662321
</tbody>
23672322

23682323
</table>

examples/event-sources/gitlab.yaml

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ spec:
88
gitlab:
99
example:
1010
# id of the project
11-
projectId: "1"
11+
projectID: "1"
1212
# Github will send events to following port and endpoint
1313
webhook:
1414
# endpoint to listen to events on
@@ -21,14 +21,11 @@ spec:
2121
# This url must be reachable from outside the cluster.
2222
# The gateway pod is backed by the service defined in the gateway spec. So get the URL for that service Github can reach to.
2323
url: http://url-that-is-reachable-from-GitLab
24-
# event to listen to
24+
# events to listen to
2525
# Visit https://docs.gitlab.com/ee/user/project/integrations/webhooks.html#events
26-
event: PushEvents
27-
28-
# # Namespace where the api token secret live.
29-
# # +Optional. Default to gateway's namespace.
30-
# namespace: "argo-events"
31-
26+
events:
27+
- PushEvents
28+
- TagPushEvents
3229
# accessToken refers to K8s secret that stores the gitlab api token
3330
accessToken:
3431
# Key within the K8s secret whose corresponding value (must be base64 encoded) is access token
@@ -52,7 +49,8 @@ spec:
5249
# serverCertPath: "some path in pod"
5350
# # path to file that is mounted in gateway pod which contains private key
5451
# serverKeyPath: "some path in pod"
55-
# event: "PushEvents"
52+
# events:
53+
# - PushEvents
5654
# accessToken:
5755
# key: accesskey
5856
# name: gitlab-access

gateways/server/gitlab/start.go

Lines changed: 84 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,11 @@ func (router *Router) PostActivate() error {
125125

126126
logger := route.Logger.WithFields(map[string]interface{}{
127127
common.LabelEventSource: route.EventSource.Name,
128-
"event-type": gitlabEventSource.Event,
129-
"project-id": gitlabEventSource.ProjectId,
128+
"project-id": gitlabEventSource.ProjectID,
130129
})
131130

132131
logger.Infoln("retrieving the access token credentials...")
133-
c, err := router.getCredentials(gitlabEventSource.AccessToken, gitlabEventSource.Namespace)
132+
c, err := router.getCredentials(gitlabEventSource.AccessToken, router.namespace)
134133
if err != nil {
135134
return errors.Errorf("failed to get gitlab credentials. err: %+v", err)
136135
}
@@ -143,51 +142,96 @@ func (router *Router) PostActivate() error {
143142

144143
formattedUrl := common.FormattedURL(gitlabEventSource.Webhook.URL, gitlabEventSource.Webhook.Endpoint)
145144

146-
// Get existing webhooks and check if the integration for same url and event type is already available
147-
if !gitlabEventSource.AllowDuplicate {
148-
hooks, _, err := router.gitlabClient.Projects.ListProjectHooks(router.gitlabEventSource.ProjectId, &gitlab.ListProjectHooksOptions{})
149-
if err != nil {
150-
return errors.Wrapf(err, "failed to list existing hooks to check for duplicates for project id %s", router.gitlabEventSource.ProjectId)
151-
}
145+
hooks, _, err := router.gitlabClient.Projects.ListProjectHooks(gitlabEventSource.ProjectID, &gitlab.ListProjectHooksOptions{})
146+
if err != nil {
147+
return errors.Wrapf(err, "failed to list existing hooks to check for duplicates for project id %s", router.gitlabEventSource.ProjectID)
148+
}
149+
150+
var existingHook *gitlab.ProjectHook
151+
isAlreadyExists := false
152152

153-
for _, hook := range hooks {
154-
elem := reflect.ValueOf(hook).Elem().FieldByName(router.gitlabEventSource.Event)
155-
if ok := elem.IsValid(); !ok {
156-
return errors.Errorf("unknown event %s", router.gitlabEventSource.Event)
157-
}
158-
value := elem.Bool()
159-
160-
if value && hook.URL == formattedUrl {
161-
logger.Infoln("webhook already exists, won't register it...")
162-
return nil
163-
}
153+
for _, hook := range hooks {
154+
if hook.URL == formattedUrl {
155+
existingHook = hook
156+
isAlreadyExists = true
164157
}
165158
}
166159

167-
opt := &gitlab.AddProjectHookOptions{
168-
URL: &formattedUrl,
169-
Token: &c.token,
170-
EnableSSLVerification: &router.gitlabEventSource.EnableSSLVerification,
160+
defaultEventValue := false
161+
162+
editOpt := &gitlab.EditProjectHookOptions{
163+
URL: &formattedUrl,
164+
ConfidentialNoteEvents: &defaultEventValue,
165+
PushEvents: &defaultEventValue,
166+
IssuesEvents: &defaultEventValue,
167+
ConfidentialIssuesEvents: &defaultEventValue,
168+
MergeRequestsEvents: &defaultEventValue,
169+
TagPushEvents: &defaultEventValue,
170+
NoteEvents: &defaultEventValue,
171+
JobEvents: &defaultEventValue,
172+
PipelineEvents: &defaultEventValue,
173+
WikiPageEvents: &defaultEventValue,
174+
EnableSSLVerification: &router.gitlabEventSource.EnableSSLVerification,
175+
Token: &c.token,
171176
}
172177

173-
logger.Infoln("configuring the type of the GitLab event the hook must register against...")
174-
elem := reflect.ValueOf(opt).Elem().FieldByName(router.gitlabEventSource.Event)
175-
if ok := elem.IsValid(); !ok {
176-
return errors.Errorf("unknown event %s", router.gitlabEventSource.Event)
178+
addOpt := &gitlab.AddProjectHookOptions{
179+
URL: &formattedUrl,
180+
Token: &c.token,
181+
EnableSSLVerification: &router.gitlabEventSource.EnableSSLVerification,
182+
ConfidentialNoteEvents: &defaultEventValue,
183+
PushEvents: &defaultEventValue,
184+
IssuesEvents: &defaultEventValue,
185+
ConfidentialIssuesEvents: &defaultEventValue,
186+
MergeRequestsEvents: &defaultEventValue,
187+
TagPushEvents: &defaultEventValue,
188+
NoteEvents: &defaultEventValue,
189+
JobEvents: &defaultEventValue,
190+
PipelineEvents: &defaultEventValue,
191+
WikiPageEvents: &defaultEventValue,
177192
}
178193

179-
iev := reflect.New(elem.Type().Elem())
180-
reflect.Indirect(iev).SetBool(true)
181-
elem.Set(iev)
194+
var opt interface{}
182195

183-
logger.Infoln("creating project hook...")
184-
hook, _, err := router.gitlabClient.Projects.AddProjectHook(router.gitlabEventSource.ProjectId, opt)
185-
if err != nil {
186-
return errors.Errorf("failed to add project hook. err: %+v", err)
196+
opt = addOpt
197+
if isAlreadyExists {
198+
opt = editOpt
199+
}
200+
201+
logger.Infoln("configuring the GitLab events for the hook...")
202+
203+
for _, event := range gitlabEventSource.Events {
204+
elem := reflect.ValueOf(opt).Elem().FieldByName(event)
205+
if ok := elem.IsValid(); !ok {
206+
return errors.Errorf("unknown event %s", event)
207+
}
208+
209+
iev := reflect.New(elem.Type().Elem())
210+
reflect.Indirect(iev).SetBool(true)
211+
elem.Set(iev)
187212
}
188213

189-
router.hook = hook
190-
logger.WithField("hook-id", hook.ID).Info("hook created for the project")
214+
var newHook *gitlab.ProjectHook
215+
216+
if !isAlreadyExists {
217+
logger.Infoln("creating project hook...")
218+
newHook, _, err = router.gitlabClient.Projects.AddProjectHook(router.gitlabEventSource.ProjectID, opt.(*gitlab.AddProjectHookOptions))
219+
if err != nil {
220+
return errors.Errorf("failed to add project hook. err: %+v", err)
221+
}
222+
} else {
223+
logger.Infoln("project hook already exists, updating it...")
224+
if existingHook == nil {
225+
return errors.Errorf("existing hook contents are empty, unable to edit existing webhook")
226+
}
227+
newHook, _, err = router.gitlabClient.Projects.EditProjectHook(router.gitlabEventSource.ProjectID, existingHook.ID, opt.(*gitlab.EditProjectHookOptions))
228+
if err != nil {
229+
return errors.Errorf("failed to add project hook. err: %+v", err)
230+
}
231+
}
232+
233+
router.hook = newHook
234+
logger.WithField("hook-id", newHook.ID).Info("hook registered for the project")
191235
return nil
192236
}
193237

@@ -199,12 +243,12 @@ func (router *Router) PostInactivate() error {
199243
if gitlabEventSource.DeleteHookOnFinish {
200244
logger := route.Logger.WithFields(map[string]interface{}{
201245
common.LabelEventSource: route.EventSource.Name,
202-
"project-id": gitlabEventSource.ProjectId,
246+
"project-id": gitlabEventSource.ProjectID,
203247
"hook-id": router.hook.ID,
204248
})
205249

206250
logger.Infoln("deleting project hook...")
207-
if _, err := router.gitlabClient.Projects.DeleteProjectHook(router.gitlabEventSource.ProjectId, router.hook.ID); err != nil {
251+
if _, err := router.gitlabClient.Projects.DeleteProjectHook(router.gitlabEventSource.ProjectID, router.hook.ID); err != nil {
208252
return errors.Errorf("failed to delete hook. err: %+v", err)
209253
}
210254

@@ -227,15 +271,12 @@ func (listener *EventListener) StartEventSource(eventSource *gateways.EventSourc
227271
return err
228272
}
229273

230-
if gitlabEventSource.Namespace == "" {
231-
gitlabEventSource.Namespace = listener.Namespace
232-
}
233-
234274
route := webhook.NewRoute(gitlabEventSource.Webhook, listener.Logger, eventSource)
235275

236276
return webhook.ManageRoute(&Router{
237277
route: route,
238278
k8sClient: listener.K8sClient,
239279
gitlabEventSource: gitlabEventSource,
280+
namespace: listener.Namespace,
240281
}, controller, eventStream)
241282
}

0 commit comments

Comments
 (0)