• 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

88.76
/gogs/gogs.go
1
package gogs
2

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

11
        "crypto/hmac"
12
        "crypto/sha256"
13
        "encoding/hex"
14

15
        client "github.com/gogits/go-gogs-client"
16
)
17

18
// parse errors
19
var (
20
        ErrEventNotSpecifiedToParse   = errors.New("no Event specified to parse")
21
        ErrInvalidHTTPMethod          = errors.New("invalid HTTP Method")
22
        ErrMissingGogsEventHeader     = errors.New("missing X-Gogs-Event Header")
23
        ErrMissingGogsSignatureHeader = errors.New("missing X-Gogs-Signature Header")
24
        ErrEventNotFound              = errors.New("event not defined to be parsed")
25
        ErrParsingPayload             = errors.New("error parsing payload")
26
        ErrHMACVerificationFailed     = errors.New("HMAC verification failed")
27
)
28

29
// Option is a configuration option for the webhook
30
type Option func(*Webhook) error
31

32
// Options is a namespace var for configuration options
33
var Options = WebhookOptions{}
34

35
// WebhookOptions is a namespace for configuration option methods
36
type WebhookOptions struct{}
37

38
// Secret registers the GitLab secret
1✔
39
func (WebhookOptions) Secret(secret string) Option {
2✔
40
        return func(hook *Webhook) error {
1✔
41
                hook.secret = secret
1✔
42
                return nil
1✔
43
        }
44
}
45

46
// Webhook instance contains all methods needed to process events
47
type Webhook struct {
48
        secret string
49
}
50

51
// Event defines a Gogs hook event type
52
type Event string
53

54
// Gogs hook types
55
const (
56
        CreateEvent       Event = "create"
57
        DeleteEvent       Event = "delete"
58
        ForkEvent         Event = "fork"
59
        PushEvent         Event = "push"
60
        IssuesEvent       Event = "issues"
61
        IssueCommentEvent Event = "issue_comment"
62
        PullRequestEvent  Event = "pull_request"
63
        ReleaseEvent      Event = "release"
64
)
65

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

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

13✔
84
        if len(events) == 0 {
×
85
                return nil, ErrEventNotSpecifiedToParse
×
86
        }
13✔
87
        if r.Method != http.MethodPost {
×
88
                return nil, ErrInvalidHTTPMethod
×
89
        }
90

13✔
91
        event := r.Header.Get("X-Gogs-Event")
15✔
92
        if len(event) == 0 {
2✔
93
                return nil, ErrMissingGogsEventHeader
2✔
94
        }
95

11✔
96
        gogsEvent := Event(event)
11✔
97

11✔
98
        var found bool
22✔
99
        for _, evt := range events {
21✔
100
                if evt == gogsEvent {
10✔
101
                        found = true
10✔
102
                        break
103
                }
104
        }
105
        // event not defined to be parsed
12✔
106
        if !found {
1✔
107
                return nil, ErrEventNotFound
1✔
108
        }
109

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

115
        // If we have a Secret set, we should check the MAC
18✔
116
        if len(hook.secret) > 0 {
9✔
117
                signature := r.Header.Get("X-Gogs-Signature")
10✔
118
                if len(signature) == 0 {
1✔
119
                        return nil, ErrMissingGogsSignatureHeader
1✔
120
                }
121

8✔
122
                mac := hmac.New(sha256.New, []byte(hook.secret))
8✔
123
                _, _ = mac.Write(payload)
8✔
124

8✔
125
                expectedMAC := hex.EncodeToString(mac.Sum(nil))
8✔
126

8✔
127
                if !hmac.Equal([]byte(signature), []byte(expectedMAC)) {
×
128
                        return nil, ErrHMACVerificationFailed
×
129
                }
130
        }
131

8✔
132
        switch gogsEvent {
1✔
133
        case CreateEvent:
1✔
134
                var pl client.CreatePayload
1✔
135
                err = json.Unmarshal([]byte(payload), &pl)
1✔
136
                return pl, err
137

1✔
138
        case ReleaseEvent:
1✔
139
                var pl client.ReleasePayload
1✔
140
                err = json.Unmarshal([]byte(payload), &pl)
1✔
141
                return pl, err
142

1✔
143
        case PushEvent:
1✔
144
                var pl client.PushPayload
1✔
145
                err = json.Unmarshal([]byte(payload), &pl)
1✔
146
                return pl, err
147

1✔
148
        case DeleteEvent:
1✔
149
                var pl client.DeletePayload
1✔
150
                err = json.Unmarshal([]byte(payload), &pl)
1✔
151
                return pl, err
152

1✔
153
        case ForkEvent:
1✔
154
                var pl client.ForkPayload
1✔
155
                err = json.Unmarshal([]byte(payload), &pl)
1✔
156
                return pl, err
157

1✔
158
        case IssuesEvent:
1✔
159
                var pl client.IssuesPayload
1✔
160
                err = json.Unmarshal([]byte(payload), &pl)
1✔
161
                return pl, err
162

1✔
163
        case IssueCommentEvent:
1✔
164
                var pl client.IssueCommentPayload
1✔
165
                err = json.Unmarshal([]byte(payload), &pl)
1✔
166
                return pl, err
167

1✔
168
        case PullRequestEvent:
1✔
169
                var pl client.PullRequestPayload
1✔
170
                err = json.Unmarshal([]byte(payload), &pl)
1✔
171
                return pl, err
172

×
173
        default:
×
174
                return nil, fmt.Errorf("unknown event %s", gogsEvent)
175
        }
176
}
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

© 2025 Coveralls, Inc