Skip to content

Commit 6b442b3

Browse files
committed
add gitea support
1 parent 1751865 commit 6b442b3

File tree

3 files changed

+559
-0
lines changed

3 files changed

+559
-0
lines changed

gitea/gitea.go

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
package gitea
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
"fmt"
7+
"io"
8+
"io/ioutil"
9+
"net/http"
10+
11+
models "code.gitea.io/gitea/modules/structs"
12+
)
13+
14+
// parse errors
15+
var (
16+
ErrEventNotSpecifiedToParse = errors.New("no Event specified to parse")
17+
ErrInvalidHTTPMethod = errors.New("invalid HTTP Method")
18+
ErrMissingGiteaEventHeader = errors.New("missing X-Gitea-Event Header")
19+
ErrMissingGiteaSignatureHeader = errors.New("missing X-Gitea-Signature Header")
20+
ErrEventNotFound = errors.New("event not defined to be parsed")
21+
ErrParsingPayload = errors.New("error parsing payload")
22+
ErrHMACVerificationFailed = errors.New("HMAC verification failed")
23+
)
24+
25+
// Option is a configuration option for the webhook
26+
type Option func(*Webhook) error
27+
28+
// Options is a namespace var for configuration options
29+
var Options = WebhookOptions{}
30+
31+
// WebhookOptions is a namespace for configuration option methods
32+
type WebhookOptions struct{}
33+
34+
// Secret registers the GitLab secret
35+
func (WebhookOptions) Secret(secret string) Option {
36+
return func(hook *Webhook) error {
37+
hook.secret = secret
38+
return nil
39+
}
40+
}
41+
42+
// Webhook instance contains all methods needed to process events
43+
type Webhook struct {
44+
secret string
45+
}
46+
47+
// Event defines a Gitea hook event type
48+
type Event string
49+
50+
// Gitea hook types
51+
const (
52+
CreateEvent Event = "create"
53+
DeleteEvent Event = "delete"
54+
ForkEvent Event = "fork"
55+
PushEvent Event = "push"
56+
IssuesEvent Event = "issues"
57+
IssueCommentEvent Event = "issue_comment"
58+
PullRequestEvent Event = "pull_request"
59+
ReleaseEvent Event = "release"
60+
)
61+
62+
// New creates and returns a WebHook instance denoted by the Provider type
63+
func New(options ...Option) (*Webhook, error) {
64+
hook := new(Webhook)
65+
for _, opt := range options {
66+
if err := opt(hook); err != nil {
67+
return nil, errors.New("Error applying Option")
68+
}
69+
}
70+
return hook, nil
71+
}
72+
73+
func (hook Webhook) verifySecret(secret string) error {
74+
if len(hook.secret) > 0 && hook.secret != secret {
75+
return fmt.Errorf("secret %s not match", secret)
76+
}
77+
78+
return nil
79+
}
80+
81+
// Parse verifies and parses the events specified and returns the payload object or an error
82+
func (hook Webhook) Parse(r *http.Request, events ...Event) (interface{}, error) {
83+
defer func() {
84+
_, _ = io.Copy(ioutil.Discard, r.Body)
85+
_ = r.Body.Close()
86+
}()
87+
88+
if len(events) == 0 {
89+
return nil, ErrEventNotSpecifiedToParse
90+
}
91+
if r.Method != http.MethodPost {
92+
return nil, ErrInvalidHTTPMethod
93+
}
94+
95+
event := r.Header.Get("X-Gitea-Event")
96+
if len(event) == 0 {
97+
return nil, ErrMissingGiteaEventHeader
98+
}
99+
100+
giteaEvent := Event(event)
101+
102+
var found bool
103+
for _, evt := range events {
104+
if evt == giteaEvent {
105+
found = true
106+
break
107+
}
108+
}
109+
// event not defined to be parsed
110+
if !found {
111+
return nil, ErrEventNotFound
112+
}
113+
114+
payload, err := ioutil.ReadAll(r.Body)
115+
if err != nil || len(payload) == 0 {
116+
return nil, ErrParsingPayload
117+
}
118+
119+
switch giteaEvent {
120+
case CreateEvent:
121+
var pl models.CreatePayload
122+
err = json.Unmarshal([]byte(payload), &pl)
123+
124+
if err == nil {
125+
err = hook.verifySecret(pl.Secret)
126+
}
127+
128+
return pl, err
129+
130+
case ReleaseEvent:
131+
var pl models.ReleasePayload
132+
err = json.Unmarshal([]byte(payload), &pl)
133+
134+
if err == nil {
135+
err = hook.verifySecret(pl.Secret)
136+
}
137+
138+
return pl, err
139+
140+
case PushEvent:
141+
var pl models.PushPayload
142+
err = json.Unmarshal([]byte(payload), &pl)
143+
144+
if err == nil {
145+
err = hook.verifySecret(pl.Secret)
146+
}
147+
148+
return pl, err
149+
150+
case DeleteEvent:
151+
var pl models.DeletePayload
152+
err = json.Unmarshal([]byte(payload), &pl)
153+
154+
if err == nil {
155+
err = hook.verifySecret(pl.Secret)
156+
}
157+
158+
return pl, err
159+
160+
case ForkEvent:
161+
var pl models.ForkPayload
162+
err = json.Unmarshal([]byte(payload), &pl)
163+
164+
if err == nil {
165+
err = hook.verifySecret(pl.Secret)
166+
}
167+
168+
return pl, err
169+
170+
case IssuesEvent:
171+
var pl models.IssuePayload
172+
err = json.Unmarshal([]byte(payload), &pl)
173+
174+
if err == nil {
175+
err = hook.verifySecret(pl.Secret)
176+
}
177+
178+
return pl, err
179+
180+
case IssueCommentEvent:
181+
var pl models.IssueCommentPayload
182+
err = json.Unmarshal([]byte(payload), &pl)
183+
184+
if err == nil {
185+
err = hook.verifySecret(pl.Secret)
186+
}
187+
188+
return pl, err
189+
190+
case PullRequestEvent:
191+
var pl models.PullRequestPayload
192+
err = json.Unmarshal([]byte(payload), &pl)
193+
194+
if err == nil {
195+
err = hook.verifySecret(pl.Secret)
196+
}
197+
198+
return pl, err
199+
200+
default:
201+
return nil, fmt.Errorf("unknown event %s", giteaEvent)
202+
}
203+
}

go.mod

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module gopkg.in/go-playground/webhooks.v5
2+
3+
go 1.12
4+
5+
require (
6+
code.gitea.io/git v0.0.0-20190411170847-63b74d438b29 // indirect
7+
code.gitea.io/gitea v1.9.0-dev.0.20190511102134-34eee25bd42d
8+
code.gitea.io/sdk/gitea v0.0.0-20190602153954-7e711e06b588 // indirect
9+
github.com/go-gitea/gitea v1.8.2
10+
github.com/gogits/go-gogs-client v0.0.0-20181217004319-1cd0db3113de
11+
github.com/mvdan/xurls v1.1.0 // indirect
12+
github.com/stretchr/testify v1.3.0
13+
)

0 commit comments

Comments
 (0)