Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
233 lines
6.1 KiB
233 lines
6.1 KiB
package gitlab |
|
|
|
import ( |
|
"encoding/json" |
|
"fmt" |
|
"net/http" |
|
) |
|
|
|
// EventType represents a Gitlab event type. |
|
type EventType string |
|
|
|
// List of available event types. |
|
const ( |
|
EventTypeBuild EventType = "Build Hook" |
|
EventTypeIssue EventType = "Issue Hook" |
|
EventConfidentialIssue EventType = "Confidential Issue Hook" |
|
EventTypeJob EventType = "Job Hook" |
|
EventTypeMergeRequest EventType = "Merge Request Hook" |
|
EventTypeNote EventType = "Note Hook" |
|
EventConfidentialNote EventType = "Confidential Note Hook" |
|
EventTypePipeline EventType = "Pipeline Hook" |
|
EventTypePush EventType = "Push Hook" |
|
EventTypeSystemHook EventType = "System Hook" |
|
EventTypeTagPush EventType = "Tag Push Hook" |
|
EventTypeWikiPage EventType = "Wiki Page Hook" |
|
) |
|
|
|
const ( |
|
noteableTypeCommit = "Commit" |
|
noteableTypeMergeRequest = "MergeRequest" |
|
noteableTypeIssue = "Issue" |
|
noteableTypeSnippet = "Snippet" |
|
) |
|
|
|
type noteEvent struct { |
|
ObjectKind string `json:"object_kind"` |
|
ObjectAttributes struct { |
|
NoteableType string `json:"noteable_type"` |
|
} `json:"object_attributes"` |
|
} |
|
|
|
const eventTypeHeader = "X-Gitlab-Event" |
|
|
|
// HookEventType returns the event type for the given request. |
|
func HookEventType(r *http.Request) EventType { |
|
return EventType(r.Header.Get(eventTypeHeader)) |
|
} |
|
|
|
// ParseHook tries to parse both web- and system hooks. |
|
// |
|
// Example usage: |
|
// |
|
// func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
// payload, err := ioutil.ReadAll(r.Body) |
|
// if err != nil { ... } |
|
// event, err := gitlab.ParseHook(gitlab.HookEventType(r), payload) |
|
// if err != nil { ... } |
|
// switch event := event.(type) { |
|
// case *gitlab.PushEvent: |
|
// processPushEvent(event) |
|
// case *gitlab.MergeEvent: |
|
// processMergeEvent(event) |
|
// ... |
|
// } |
|
// } |
|
// |
|
func ParseHook(eventType EventType, payload []byte) (event interface{}, err error) { |
|
switch eventType { |
|
case EventTypeSystemHook: |
|
return ParseSystemhook(payload) |
|
default: |
|
return ParseWebhook(eventType, payload) |
|
} |
|
} |
|
|
|
// ParseSystemhook parses the event payload. For recognized event types, a |
|
// value of the corresponding struct type will be returned. An error will be |
|
// returned for unrecognized event types. |
|
// |
|
// Example usage: |
|
// |
|
// func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
// payload, err := ioutil.ReadAll(r.Body) |
|
// if err != nil { ... } |
|
// event, err := gitlab.ParseSystemhook(payload) |
|
// if err != nil { ... } |
|
// switch event := event.(type) { |
|
// case *gitlab.PushSystemEvent: |
|
// processPushSystemEvent(event) |
|
// case *gitlab.MergeSystemEvent: |
|
// processMergeSystemEvent(event) |
|
// ... |
|
// } |
|
// } |
|
// |
|
func ParseSystemhook(payload []byte) (event interface{}, err error) { |
|
e := &systemHookEvent{} |
|
err = json.Unmarshal(payload, e) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
switch e.EventName { |
|
case "push": |
|
event = &PushSystemEvent{} |
|
case "tag_push": |
|
event = &TagPushSystemEvent{} |
|
case "repository_update": |
|
event = &RepositoryUpdateSystemEvent{} |
|
case |
|
"project_create", |
|
"project_update", |
|
"project_destroy", |
|
"project_transfer", |
|
"project_rename": |
|
event = &ProjectSystemEvent{} |
|
case |
|
"group_create", |
|
"group_destroy", |
|
"group_rename": |
|
event = &GroupSystemEvent{} |
|
case |
|
"key_create", |
|
"key_destroy": |
|
event = &KeySystemEvent{} |
|
case |
|
"user_create", |
|
"user_destroy", |
|
"user_rename": |
|
event = &UserSystemEvent{} |
|
case |
|
"user_add_to_group", |
|
"user_remove_from_group", |
|
"user_update_for_group": |
|
event = &UserGroupSystemEvent{} |
|
case |
|
"user_add_to_team", |
|
"user_remove_from_team", |
|
"user_update_for_team": |
|
event = &UserTeamSystemEvent{} |
|
default: |
|
switch e.ObjectKind { |
|
case "merge_request": |
|
event = &MergeEvent{} |
|
default: |
|
return nil, fmt.Errorf("unexpected system hook type %s", e.EventName) |
|
} |
|
} |
|
|
|
if err := json.Unmarshal(payload, event); err != nil { |
|
return nil, err |
|
} |
|
|
|
return event, nil |
|
} |
|
|
|
// WebhookEventType returns the event type for the given request. |
|
func WebhookEventType(r *http.Request) EventType { |
|
return EventType(r.Header.Get(eventTypeHeader)) |
|
} |
|
|
|
// ParseWebhook parses the event payload. For recognized event types, a |
|
// value of the corresponding struct type will be returned. An error will |
|
// be returned for unrecognized event types. |
|
// |
|
// Example usage: |
|
// |
|
// func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
// payload, err := ioutil.ReadAll(r.Body) |
|
// if err != nil { ... } |
|
// event, err := gitlab.ParseWebhook(gitlab.HookEventType(r), payload) |
|
// if err != nil { ... } |
|
// switch event := event.(type) { |
|
// case *gitlab.PushEvent: |
|
// processPushEvent(event) |
|
// case *gitlab.MergeEvent: |
|
// processMergeEvent(event) |
|
// ... |
|
// } |
|
// } |
|
// |
|
func ParseWebhook(eventType EventType, payload []byte) (event interface{}, err error) { |
|
switch eventType { |
|
case EventTypeBuild: |
|
event = &BuildEvent{} |
|
case EventTypeIssue, EventConfidentialIssue: |
|
event = &IssueEvent{} |
|
case EventTypeJob: |
|
event = &JobEvent{} |
|
case EventTypeMergeRequest: |
|
event = &MergeEvent{} |
|
case EventTypePipeline: |
|
event = &PipelineEvent{} |
|
case EventTypePush: |
|
event = &PushEvent{} |
|
case EventTypeTagPush: |
|
event = &TagEvent{} |
|
case EventTypeWikiPage: |
|
event = &WikiPageEvent{} |
|
case EventTypeNote, EventConfidentialNote: |
|
note := ¬eEvent{} |
|
err := json.Unmarshal(payload, note) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
if note.ObjectKind != "note" { |
|
return nil, fmt.Errorf("unexpected object kind %s", note.ObjectKind) |
|
} |
|
|
|
switch note.ObjectAttributes.NoteableType { |
|
case noteableTypeCommit: |
|
event = &CommitCommentEvent{} |
|
case noteableTypeMergeRequest: |
|
event = &MergeCommentEvent{} |
|
case noteableTypeIssue: |
|
event = &IssueCommentEvent{} |
|
case noteableTypeSnippet: |
|
event = &SnippetCommentEvent{} |
|
default: |
|
return nil, fmt.Errorf("unexpected noteable type %s", note.ObjectAttributes.NoteableType) |
|
} |
|
|
|
default: |
|
return nil, fmt.Errorf("unexpected event type: %s", eventType) |
|
} |
|
|
|
if err := json.Unmarshal(payload, event); err != nil { |
|
return nil, err |
|
} |
|
|
|
return event, nil |
|
}
|
|
|