1package gitlab
2
3import (
4 "encoding/json"
5 "fmt"
6 "net/http"
7)
8
9// EventType represents a Gitlab event type.
10type EventType string
11
12// List of available event types.
13const (
14 EventTypeBuild EventType = "Build Hook"
15 EventTypeIssue EventType = "Issue Hook"
16 EventTypeJob EventType = "Job Hook"
17 EventTypeMergeRequest EventType = "Merge Request Hook"
18 EventTypeNote EventType = "Note Hook"
19 EventTypePipeline EventType = "Pipeline Hook"
20 EventTypePush EventType = "Push Hook"
21 EventTypeTagPush EventType = "Tag Push Hook"
22 EventTypeWikiPage EventType = "Wiki Page Hook"
23)
24
25const (
26 noteableTypeCommit = "Commit"
27 noteableTypeMergeRequest = "MergeRequest"
28 noteableTypeIssue = "Issue"
29 noteableTypeSnippet = "Snippet"
30)
31
32type noteEvent struct {
33 ObjectKind string `json:"object_kind"`
34 ObjectAttributes struct {
35 NoteableType string `json:"noteable_type"`
36 } `json:"object_attributes"`
37}
38
39const eventTypeHeader = "X-Gitlab-Event"
40
41// WebhookEventType returns the event type for the given request.
42func WebhookEventType(r *http.Request) EventType {
43 return EventType(r.Header.Get(eventTypeHeader))
44}
45
46// ParseWebhook parses the event payload. For recognized event types, a
47// value of the corresponding struct type will be returned. An error will
48// be returned for unrecognized event types.
49//
50// Example usage:
51//
52// func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
53// payload, err := ioutil.ReadAll(r.Body)
54// if err != nil { ... }
55// event, err := gitlab.ParseWebhook(gitlab.WebhookEventType(r), payload)
56// if err != nil { ... }
57// switch event := event.(type) {
58// case *gitlab.PushEvent:
59// processPushEvent(event)
60// case *gitlab.MergeEvent:
61// processMergeEvent(event)
62// ...
63// }
64// }
65//
66func ParseWebhook(eventType EventType, payload []byte) (event interface{}, err error) {
67 switch eventType {
68 case EventTypeBuild:
69 event = &BuildEvent{}
70 case EventTypeIssue:
71 event = &IssueEvent{}
72 case EventTypeJob:
73 event = &JobEvent{}
74 case EventTypeMergeRequest:
75 event = &MergeEvent{}
76 case EventTypePipeline:
77 event = &PipelineEvent{}
78 case EventTypePush:
79 event = &PushEvent{}
80 case EventTypeTagPush:
81 event = &TagEvent{}
82 case EventTypeWikiPage:
83 event = &WikiPageEvent{}
84 case EventTypeNote:
85 note := ¬eEvent{}
86 err := json.Unmarshal(payload, note)
87 if err != nil {
88 return nil, err
89 }
90
91 if note.ObjectKind != "note" {
92 return nil, fmt.Errorf("unexpected object kind %s", note.ObjectKind)
93 }
94
95 switch note.ObjectAttributes.NoteableType {
96 case noteableTypeCommit:
97 event = &CommitCommentEvent{}
98 case noteableTypeMergeRequest:
99 event = &MergeCommentEvent{}
100 case noteableTypeIssue:
101 event = &IssueCommentEvent{}
102 case noteableTypeSnippet:
103 event = &SnippetCommentEvent{}
104 default:
105 return nil, fmt.Errorf("unexpected noteable type %s", note.ObjectAttributes.NoteableType)
106 }
107
108 default:
109 return nil, fmt.Errorf("unexpected event type: %s", eventType)
110 }
111
112 if err := json.Unmarshal(payload, event); err != nil {
113 return nil, err
114 }
115
116 return event, nil
117}