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

go-playground / webhooks / 15063965098

16 May 2025 08:17AM UTC coverage: 88.933%. Remained the same
15063965098

Pull #208

github

Kinga Sieminiak
Fix json tag
Pull Request #208: Extend GitHub changes payload

900 of 1012 relevant lines covered (88.93%)

8.8 hits per line

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

87.61
/gitlab/gitlab.go
1
package gitlab
2

3
import (
4
        "encoding/json"
5
        "errors"
6
        "fmt"
7
        "io"
8
        "io/ioutil"
9
        "net/http"
10
)
11

12
// parse errors
13
var (
14
        ErrEventNotSpecifiedToParse      = errors.New("no Event specified to parse")
15
        ErrInvalidHTTPMethod             = errors.New("invalid HTTP Method")
16
        ErrMissingGitLabEventHeader      = errors.New("missing X-Gitlab-Event Header")
17
        ErrGitLabTokenVerificationFailed = errors.New("X-Gitlab-Token validation failed")
18
        ErrEventNotFound                 = errors.New("event not defined to be parsed")
19
        ErrParsingPayload                = errors.New("error parsing payload")
20
        ErrParsingSystemPayload          = errors.New("error parsing system payload")
21
        // ErrHMACVerificationFailed    = errors.New("HMAC verification failed")
22
)
23

24
// GitLab hook types
25
const (
26
        PushEvents               Event = "Push Hook"
27
        TagEvents                Event = "Tag Push Hook"
28
        IssuesEvents             Event = "Issue Hook"
29
        ConfidentialIssuesEvents Event = "Confidential Issue Hook"
30
        CommentEvents            Event = "Note Hook"
31
        MergeRequestEvents       Event = "Merge Request Hook"
32
        WikiPageEvents           Event = "Wiki Page Hook"
33
        PipelineEvents           Event = "Pipeline Hook"
34
        BuildEvents              Event = "Build Hook"
35
        JobEvents                Event = "Job Hook"
36
        SystemHookEvents         Event = "System Hook"
37

38
        objectPush         string = "push"
39
        objectTag          string = "tag_push"
40
        objectMergeRequest string = "merge_request"
41
        objectBuild        string = "build"
42
)
43

44
// Option is a configuration option for the webhook
45
type Option func(*Webhook) error
46

47
// Options is a namespace var for configuration options
48
var Options = WebhookOptions{}
49

50
// WebhookOptions is a namespace for configuration option methods
51
type WebhookOptions struct{}
52

53
// Secret registers the GitLab secret
54
func (WebhookOptions) Secret(secret string) Option {
55
        return func(hook *Webhook) error {
56
                hook.secret = secret
57
                return nil
58
        }
59
}
60

61
// Webhook instance contains all methods needed to process events
62
type Webhook struct {
63
        secret string
64
}
65

66
// Event defines a GitLab hook event type by the X-Gitlab-Event Header
67
type Event string
68

69
// New creates and returns a WebHook instance denoted by the Provider type
70
func New(options ...Option) (*Webhook, error) {
71
        hook := new(Webhook)
72
        for _, opt := range options {
73
                if err := opt(hook); err != nil {
74
                        return nil, errors.New("Error applying Option")
75
                }
76
        }
77
        return hook, nil
1✔
78
}
2✔
79

1✔
80
// Parse verifies and parses the events specified and returns the payload object or an error
1✔
81
func (hook Webhook) Parse(r *http.Request, events ...Event) (interface{}, error) {
1✔
82
        defer func() {
1✔
83
                _, _ = io.Copy(ioutil.Discard, r.Body)
1✔
84
                _ = r.Body.Close()
85
        }()
86

87
        if len(events) == 0 {
88
                return nil, ErrEventNotSpecifiedToParse
89
        }
90
        if r.Method != http.MethodPost {
91
                return nil, ErrInvalidHTTPMethod
92
        }
93

94
        // If we have a Secret set, we should check the MAC
95
        if len(hook.secret) > 0 {
1✔
96
                signature := r.Header.Get("X-Gitlab-Token")
1✔
97
                if signature != hook.secret {
2✔
98
                        return nil, ErrGitLabTokenVerificationFailed
1✔
99
                }
×
100
        }
×
101

102
        event := r.Header.Get("X-Gitlab-Event")
1✔
103
        if len(event) == 0 {
104
                return nil, ErrMissingGitLabEventHeader
105
        }
106

43✔
107
        gitLabEvent := Event(event)
86✔
108

43✔
109
        payload, err := ioutil.ReadAll(r.Body)
43✔
110
        if err != nil || len(payload) == 0 {
43✔
111
                return nil, ErrParsingPayload
112
        }
43✔
113

×
114
        return eventParsing(gitLabEvent, events, payload)
×
115
}
43✔
116

×
117
func eventParsing(gitLabEvent Event, events []Event, payload []byte) (interface{}, error) {
×
118

119
        var found bool
120
        for _, evt := range events {
86✔
121
                if evt == gitLabEvent {
43✔
122
                        found = true
46✔
123
                        break
3✔
124
                }
3✔
125
        }
126
        // event not defined to be parsed
127
        if !found {
40✔
128
                return nil, ErrEventNotFound
40✔
129
        }
×
130

×
131
        switch gitLabEvent {
132
        case PushEvents:
40✔
133
                var pl PushEventPayload
40✔
134
                err := json.Unmarshal([]byte(payload), &pl)
40✔
135
                return pl, err
41✔
136

1✔
137
        case TagEvents:
1✔
138
                var pl TagEventPayload
139
                err := json.Unmarshal([]byte(payload), &pl)
39✔
140
                return pl, err
141

142
        case ConfidentialIssuesEvents:
43✔
143
                var pl ConfidentialIssueEventPayload
43✔
144
                err := json.Unmarshal([]byte(payload), &pl)
43✔
145
                return pl, err
90✔
146

90✔
147
        case IssuesEvents:
43✔
148
                var pl IssueEventPayload
43✔
149
                err := json.Unmarshal([]byte(payload), &pl)
150
                return pl, err
151

152
        case CommentEvents:
43✔
153
                var pl CommentEventPayload
×
154
                err := json.Unmarshal([]byte(payload), &pl)
×
155
                return pl, err
156

43✔
157
        case MergeRequestEvents:
2✔
158
                var pl MergeRequestEventPayload
2✔
159
                err := json.Unmarshal([]byte(payload), &pl)
2✔
160
                return pl, err
2✔
161

162
        case WikiPageEvents:
2✔
163
                var pl WikiPageEventPayload
2✔
164
                err := json.Unmarshal([]byte(payload), &pl)
2✔
165
                return pl, err
2✔
166

167
        case PipelineEvents:
1✔
168
                var pl PipelineEventPayload
1✔
169
                err := json.Unmarshal([]byte(payload), &pl)
1✔
170
                return pl, err
1✔
171

172
        case BuildEvents:
1✔
173
                var pl BuildEventPayload
1✔
174
                err := json.Unmarshal([]byte(payload), &pl)
1✔
175
                return pl, err
1✔
176
        case JobEvents:
177
                var pl JobEventPayload
1✔
178
                err := json.Unmarshal([]byte(payload), &pl)
1✔
179
                if err != nil {
1✔
180
                        return nil, err
1✔
181
                }
182
                if pl.ObjectKind == objectBuild {
4✔
183
                        return eventParsing(BuildEvents, events, payload)
4✔
184
                }
4✔
185
                return pl, nil
4✔
186

187
        case SystemHookEvents:
2✔
188
                var pl SystemHookPayload
2✔
189
                err := json.Unmarshal([]byte(payload), &pl)
2✔
190
                if err != nil {
2✔
191
                        return nil, err
192
                }
1✔
193
                switch pl.ObjectKind {
1✔
194
                case objectPush:
1✔
195
                        return eventParsing(PushEvents, events, payload)
1✔
196
                case objectTag:
197
                        return eventParsing(TagEvents, events, payload)
1✔
198
                case objectMergeRequest:
1✔
199
                        return eventParsing(MergeRequestEvents, events, payload)
1✔
200
                default:
1✔
201
                        switch pl.EventName {
202
                        case objectPush:
2✔
203
                                return eventParsing(PushEvents, events, payload)
2✔
204
                        case objectTag:
2✔
205
                                return eventParsing(TagEvents, events, payload)
2✔
206
                        case objectMergeRequest:
207
                                return eventParsing(MergeRequestEvents, events, payload)
1✔
208
                        default:
1✔
209
                                return nil, fmt.Errorf("unknown system hook event %s", gitLabEvent)
1✔
210
                        }
1✔
211
                }
×
212
        default:
×
213
                return nil, fmt.Errorf("unknown event %s", gitLabEvent)
2✔
214
        }
1✔
215
}
1✔
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

© 2026 Coveralls, Inc