-
Notifications
You must be signed in to change notification settings - Fork 271
Expand file tree
/
Copy pathgerrit.go
More file actions
116 lines (94 loc) · 2.62 KB
/
gerrit.go
File metadata and controls
116 lines (94 loc) · 2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package gerrit
import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"strings"
)
var (
ErrEventNotSpecifiedToParse = errors.New("no Event specified to parse")
ErrInvalidHTTPMethod = errors.New("invalid HTTP Method")
ErrMissingGerritEvent = errors.New("missing type field")
ErrMissingHubSignatureHeader = errors.New("missing X-Hub-Signature-256 Header")
ErrEventNotFound = errors.New("event not defined to be parsed")
ErrParsingPayload = errors.New("error parsing payload")
ErrHMACVerificationFailed = errors.New("HMAC verification failed")
)
type Event string
const (
ChangeMergedEvent Event = "change-merged"
)
// Option is a configuration option for the webhook
type Option func(*Webhook) error
// Options is a namespace var for configuration options
var Options = WebhookOptions{}
// WebhookOptions is a namespace for configuration option methods
type WebhookOptions struct{}
// GerritWebhook instance contains all methods needed to process events
type Webhook struct {}
// New creates and returns a GerritWebhook instance
func New(options ...Option) (*Webhook, error) {
hook := new(Webhook)
for _, opt := range options {
if err := opt(hook); err != nil {
return nil, errors.New("error applying option")
}
}
return hook, nil
}
func (hook *Webhook) Parse(r *http.Request, events ...Event) (interface{}, error) {
defer func() {
_, _ = io.Copy(io.Discard, r.Body)
_ = r.Body.Close()
}()
if len(events) == 0 {
return nil, ErrEventNotSpecifiedToParse
}
if r.Method != http.MethodPost {
return nil, ErrInvalidHTTPMethod
}
payload, err := io.ReadAll(r.Body)
if err != nil || len(payload) == 0 {
return nil, ErrParsingPayload
}
var envelope Envelope
err = json.Unmarshal([]byte(payload), &envelope)
if err != nil {
return nil, ErrParsingPayload
}
event := envelope.Type
if event == "" {
return nil, ErrMissingGerritEvent
}
gerritEvent := Event(event)
var found bool
for _, evt := range events {
if evt == gerritEvent {
found = true
break
}
}
// event not defined to be parsed
if !found {
return nil, ErrEventNotFound
}
switch gerritEvent {
case ChangeMergedEvent:
var pl ChangeMergedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
default:
return nil, fmt.Errorf("unknown event %s", gerritEvent)
}
}
func ExtractRepoURL(payload ChangeMergedPayload) (string, error) {
// URL is in the format of https://<gerrit-host>/c/<project>/+/<change-id>
parts := strings.Split(payload.Change.URL, "/")
if len(parts) < 7 {
return "", fmt.Errorf("invalid URL %s", payload.Change.URL)
}
url := fmt.Sprintf("%s//%s/%s", parts[0], parts[2], parts[4])
return url, nil
}