Skip to content

Commit fe7552f

Browse files
author
Dean Karn
committed
Add GitLab support
1 parent ca13186 commit fe7552f

File tree

6 files changed

+1684
-13
lines changed

6 files changed

+1684
-13
lines changed

README.md

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Library webhooks
77
[![GoDoc](https://godoc.org/gopkg.in/go-playground/webhooks.v2?status.svg)](https://godoc.org/gopkg.in/go-playground/webhooks.v2)
88
![License](https://img.shields.io/dub/l/vibe-d.svg)
99

10-
Library webhooks allows for easy recieving and parsing of GitHub & Bitbucket Webhook Events
10+
Library webhooks allows for easy recieving and parsing of GitHub, Bitbucket and GitLab Webhook Events
1111

1212
Features:
1313

@@ -16,7 +16,7 @@ Features:
1616

1717
Notes:
1818

19-
* Github - Currently only accepting json payloads.
19+
* Currently only accepting json payloads.
2020

2121
Installation
2222
------------
@@ -27,11 +27,11 @@ Use go get.
2727
go get -u gopkg.in/go-playground/webhooks.v2
2828
```
2929

30-
Then import the validator package into your own code.
30+
Then import the package into your own code.
3131

3232
import "gopkg.in/go-playground/webhooks.v2"
3333

34-
Usage and documentation
34+
Usage and Documentation
3535
------
3636

3737
Please see http://godoc.org/gopkg.in/go-playground/webhooks.v2 for detailed usage docs.
@@ -147,14 +147,9 @@ func HandleMultiple(payload interface{}, header webhooks.Header) {
147147
Contributing
148148
------
149149

150-
Pull requests for other service like BitBucket are welcome!
150+
Pull requests for other services are welcome!
151151

152-
There will always be a development branch for each version i.e. `v1-development`. In order to contribute,
153-
please make your pull requests against those branches.
154-
155-
If the changes being proposed or requested are breaking changes, please create an issue, for discussion
156-
or create a pull request against the highest development branch for example this package has a
157-
v1 and v1-development branch however, there will also be a v2-development branch even though v2 doesn't exist yet.
152+
If the changes being proposed or requested are breaking changes, please create an issue for discussion.
158153

159154
License
160155
------

gitlab/gitlab.go

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package gitlab
2+
3+
import (
4+
"encoding/json"
5+
"io/ioutil"
6+
"net/http"
7+
8+
"gopkg.in/go-playground/webhooks.v2"
9+
)
10+
11+
// Webhook instance contains all methods needed to process events
12+
type Webhook struct {
13+
provider webhooks.Provider
14+
secret string
15+
eventFuncs map[Event]webhooks.ProcessPayloadFunc
16+
}
17+
18+
// Config defines the configuration to create a new GitHub Webhook instance
19+
type Config struct {
20+
Secret string
21+
}
22+
23+
// Event defines a GitHub hook event type
24+
type Event string
25+
26+
// GitLab hook types
27+
const (
28+
PushEvents Event = "Push Hook"
29+
TagEvents Event = "Tag Push Hook"
30+
IssuesEvents Event = "Issue Hook"
31+
CommentEvents Event = "Note Hook"
32+
MergerRequestEvents Event = "Merge Request Hook"
33+
WikiPageEvents Event = "Wiki Page Hook"
34+
PipelineEvents Event = "Pipeline Hook"
35+
BuildEvents Event = "Build Hook"
36+
)
37+
38+
// New creates and returns a WebHook instance denoted by the Provider type
39+
func New(config *Config) *Webhook {
40+
return &Webhook{
41+
provider: webhooks.GitLab,
42+
secret: config.Secret,
43+
eventFuncs: map[Event]webhooks.ProcessPayloadFunc{},
44+
}
45+
}
46+
47+
// Provider returns the current hooks provider ID
48+
func (hook Webhook) Provider() webhooks.Provider {
49+
return hook.provider
50+
}
51+
52+
// RegisterEvents registers the function to call when the specified event(s) are encountered
53+
func (hook Webhook) RegisterEvents(fn webhooks.ProcessPayloadFunc, events ...Event) {
54+
55+
for _, event := range events {
56+
hook.eventFuncs[event] = fn
57+
}
58+
}
59+
60+
// ParsePayload parses and verifies the payload and fires off the mapped function, if it exists.
61+
func (hook Webhook) ParsePayload(w http.ResponseWriter, r *http.Request) {
62+
63+
event := r.Header.Get("X-Gitlab-Event")
64+
if len(event) == 0 {
65+
http.Error(w, "400 Bad Request - Missing X-Gitlab-Event Header", http.StatusBadRequest)
66+
return
67+
}
68+
69+
gitLabEvent := Event(event)
70+
71+
fn, ok := hook.eventFuncs[gitLabEvent]
72+
// if no event registered
73+
if !ok {
74+
return
75+
}
76+
77+
payload, err := ioutil.ReadAll(r.Body)
78+
if err != nil || len(payload) == 0 {
79+
http.Error(w, "Error reading Body", http.StatusInternalServerError)
80+
return
81+
}
82+
83+
// If we have a Secret set, we should check the MAC
84+
if len(hook.secret) > 0 {
85+
86+
signature := r.Header.Get("X-Gitlab-Token")
87+
88+
if signature != hook.secret {
89+
http.Error(w, "403 Forbidden - Token missmatch", http.StatusForbidden)
90+
return
91+
}
92+
}
93+
94+
// Make headers available to ProcessPayloadFunc as a webhooks type
95+
hd := webhooks.Header(r.Header)
96+
97+
switch gitLabEvent {
98+
case PushEvents:
99+
var pe PushEventPayload
100+
json.Unmarshal([]byte(payload), &pe)
101+
hook.runProcessPayloadFunc(fn, pe, hd)
102+
103+
case TagEvents:
104+
var te TagEventPayload
105+
json.Unmarshal([]byte(payload), &te)
106+
hook.runProcessPayloadFunc(fn, te, hd)
107+
108+
case IssuesEvents:
109+
var ie IssueEventPayload
110+
json.Unmarshal([]byte(payload), &ie)
111+
hook.runProcessPayloadFunc(fn, ie, hd)
112+
113+
case CommentEvents:
114+
var ce CommentEventPayload
115+
json.Unmarshal([]byte(payload), &ce)
116+
hook.runProcessPayloadFunc(fn, ce, hd)
117+
118+
case MergerRequestEvents:
119+
var mre MergeRequestEventPayload
120+
json.Unmarshal([]byte(payload), &mre)
121+
hook.runProcessPayloadFunc(fn, mre, hd)
122+
123+
case WikiPageEvents:
124+
var wpe WikiPageEventPayload
125+
json.Unmarshal([]byte(payload), &wpe)
126+
hook.runProcessPayloadFunc(fn, wpe, hd)
127+
128+
case PipelineEvents:
129+
var pe PipelineEventPayload
130+
json.Unmarshal([]byte(payload), &pe)
131+
hook.runProcessPayloadFunc(fn, pe, hd)
132+
133+
case BuildEvents:
134+
var be BuildEventPayload
135+
json.Unmarshal([]byte(payload), &be)
136+
hook.runProcessPayloadFunc(fn, be, hd)
137+
}
138+
}
139+
140+
func (hook Webhook) runProcessPayloadFunc(fn webhooks.ProcessPayloadFunc, results interface{}, header webhooks.Header) {
141+
go func(fn webhooks.ProcessPayloadFunc, results interface{}, header webhooks.Header) {
142+
fn(results, header)
143+
}(fn, results, header)
144+
}

0 commit comments

Comments
 (0)