Compare commits

...

7 Commits

Author SHA1 Message Date
Dean Karn fe7552fcf4 Add GitLab support 2017-04-08 11:40:22 -04:00
Dean Karn ca13186bfa Update README.md
Adjustments due to GitHub's new markdown parser
2017-03-27 15:19:31 -04:00
Dean Karn 1e0ece40df cleanup imports + README for v2 2016-10-20 19:51:20 -04:00
Dean Karn 60d6ca11e3 Merge pull request #3 from alrs/headers
HTTP Header Passed to ProcessPayloadFunc
2016-10-20 19:42:36 -04:00
Dean Karn 622d26f48f Merge pull request #4 from go-playground/v1
merge v1 into v2-development
2016-10-20 19:39:08 -04:00
Lars Lehtonen 53781ac0e7 Added header param to README 2016-10-20 16:02:45 -07:00
Lars Lehtonen 16a6ac7a61 Added http headers as another param to ProcessPayloadFunc 2016-10-20 15:53:15 -07:00
12 changed files with 1771 additions and 90 deletions
+24 -29
View File
@@ -1,14 +1,13 @@
Library webhooks Library webhooks
================ ================
<img align="right" src="https://raw.githubusercontent.com/go-playground/webhooks/v1/logo.png"> <img align="right" src="https://raw.githubusercontent.com/go-playground/webhooks/v2/logo.png">![Project status](https://img.shields.io/badge/version-2.0.0-green.svg)
![Project status](https://img.shields.io/badge/version-1.0-green.svg)
[![Build Status](https://semaphoreci.com/api/v1/projects/5b9e2eda-8f8d-40aa-8cb4-e3f6120171fe/587820/badge.svg)](https://semaphoreci.com/joeybloggs/webhooks) [![Build Status](https://semaphoreci.com/api/v1/projects/5b9e2eda-8f8d-40aa-8cb4-e3f6120171fe/587820/badge.svg)](https://semaphoreci.com/joeybloggs/webhooks)
[![Coverage Status](https://coveralls.io/repos/go-playground/webhooks/badge.svg?branch=v1&service=github)](https://coveralls.io/github/go-playground/webhooks?branch=v1) [![Coverage Status](https://coveralls.io/repos/go-playground/webhooks/badge.svg?branch=v2&service=github)](https://coveralls.io/github/go-playground/webhooks?branch=v2)
[![Go Report Card](https://goreportcard.com/badge/go-playground/webhooks)](https://goreportcard.com/report/go-playground/webhooks) [![Go Report Card](https://goreportcard.com/badge/go-playground/webhooks)](https://goreportcard.com/report/go-playground/webhooks)
[![GoDoc](https://godoc.org/gopkg.in/go-playground/webhooks.v1?status.svg)](https://godoc.org/gopkg.in/go-playground/webhooks.v1) [![GoDoc](https://godoc.org/gopkg.in/go-playground/webhooks.v2?status.svg)](https://godoc.org/gopkg.in/go-playground/webhooks.v2)
![License](https://img.shields.io/dub/l/vibe-d.svg) ![License](https://img.shields.io/dub/l/vibe-d.svg)
Library webhooks allows for easy recieving and parsing of GitHub & Bitbucket Webhook Events Library webhooks allows for easy recieving and parsing of GitHub, Bitbucket and GitLab Webhook Events
Features: Features:
@@ -17,27 +16,25 @@ Features:
Notes: Notes:
* Github - Currently only accepting json payloads. * Currently only accepting json payloads.
Installation Installation
------------ ------------
Use go get. Use go get.
go get gopkg.in/go-playground/webhooks.v1 ```shell
go get -u gopkg.in/go-playground/webhooks.v2
```
or to update Then import the package into your own code.
go get -u gopkg.in/go-playground/webhooks.v1 import "gopkg.in/go-playground/webhooks.v2"
Then import the validator package into your own code. Usage and Documentation
import "gopkg.in/go-playground/webhooks.v1"
Usage and documentation
------ ------
Please see http://godoc.org/gopkg.in/go-playground/webhooks.v1 for detailed usage docs. Please see http://godoc.org/gopkg.in/go-playground/webhooks.v2 for detailed usage docs.
##### Examples: ##### Examples:
@@ -49,8 +46,8 @@ import (
"fmt" "fmt"
"strconv" "strconv"
"gopkg.in/go-playground/webhooks.v1" "gopkg.in/go-playground/webhooks.v2"
"gopkg.in/go-playground/webhooks.v1/github" "gopkg.in/go-playground/webhooks.v2/github"
) )
const ( const (
@@ -59,6 +56,7 @@ const (
) )
func main() { func main() {
hook := github.New(&github.Config{Secret: "MyGitHubSuperSecretSecrect...?"}) hook := github.New(&github.Config{Secret: "MyGitHubSuperSecretSecrect...?"})
hook.RegisterEvents(HandleRelease, github.ReleaseEvent) hook.RegisterEvents(HandleRelease, github.ReleaseEvent)
hook.RegisterEvents(HandlePullRequest, github.PullRequestEvent) hook.RegisterEvents(HandlePullRequest, github.PullRequestEvent)
@@ -70,7 +68,7 @@ func main() {
} }
// HandleRelease handles GitHub release events // HandleRelease handles GitHub release events
func HandleRelease(payload interface{}) { func HandleRelease(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Release") fmt.Println("Handling Release")
@@ -86,7 +84,7 @@ func HandleRelease(payload interface{}) {
} }
// HandlePullRequest handles GitHub pull_request events // HandlePullRequest handles GitHub pull_request events
func HandlePullRequest(payload interface{}) { func HandlePullRequest(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Pull Request") fmt.Println("Handling Pull Request")
@@ -95,6 +93,7 @@ func HandlePullRequest(payload interface{}) {
// Do whatever you want from here... // Do whatever you want from here...
fmt.Printf("%+v", pl) fmt.Printf("%+v", pl)
} }
``` ```
Single receiver for events you subscribe to Single receiver for events you subscribe to
@@ -105,8 +104,8 @@ import (
"fmt" "fmt"
"strconv" "strconv"
"gopkg.in/go-playground/webhooks.v1" "gopkg.in/go-playground/webhooks.v2"
"gopkg.in/go-playground/webhooks.v1/github" "gopkg.in/go-playground/webhooks.v2/github"
) )
const ( const (
@@ -115,6 +114,7 @@ const (
) )
func main() { func main() {
hook := github.New(&github.Config{Secret: "MyGitHubSuperSecretSecrect...?"}) hook := github.New(&github.Config{Secret: "MyGitHubSuperSecretSecrect...?"})
hook.RegisterEvents(HandleMultiple, github.ReleaseEvent, github.PullRequestEvent) // Add as many as you want hook.RegisterEvents(HandleMultiple, github.ReleaseEvent, github.PullRequestEvent) // Add as many as you want
@@ -125,7 +125,7 @@ func main() {
} }
// HandleMultiple handles multiple GitHub events // HandleMultiple handles multiple GitHub events
func HandleMultiple(payload interface{}) { func HandleMultiple(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Payload..") fmt.Println("Handling Payload..")
@@ -147,14 +147,9 @@ func HandleMultiple(payload interface{}) {
Contributing Contributing
------ ------
Pull requests for other service like BitBucket are welcome! Pull requests for other services are welcome!
There will always be a development branch for each version i.e. `v1-development`. In order to contribute, If the changes being proposed or requested are breaking changes, please create an issue for discussion.
please make your pull requests against those branches.
If the changes being proposed or requested are breaking changes, please create an issue, for discussion
or create a pull request against the highest development branch for example this package has a
v1 and v1-development branch however, there will also be a v2-development branch even though v2 doesn't exist yet.
License License
------ ------
+24 -22
View File
@@ -5,7 +5,7 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"gopkg.in/go-playground/webhooks.v1" "gopkg.in/go-playground/webhooks.v2"
) )
// Webhook instance contains all methods needed to process events // Webhook instance contains all methods needed to process events
@@ -100,80 +100,82 @@ func (hook Webhook) ParsePayload(w http.ResponseWriter, r *http.Request) {
return return
} }
hd := webhooks.Header(r.Header)
switch bitbucketEvent { switch bitbucketEvent {
case RepoPushEvent: case RepoPushEvent:
var pl RepoPushPayload var pl RepoPushPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case RepoForkEvent: case RepoForkEvent:
var pl RepoForkPayload var pl RepoForkPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case RepoCommitCommentCreatedEvent: case RepoCommitCommentCreatedEvent:
var pl RepoCommitCommentCreatedPayload var pl RepoCommitCommentCreatedPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case RepoCommitStatusCreatedEvent: case RepoCommitStatusCreatedEvent:
var pl RepoCommitStatusCreatedPayload var pl RepoCommitStatusCreatedPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case RepoCommitStatusUpdatedEvent: case RepoCommitStatusUpdatedEvent:
var pl RepoCommitStatusUpdatedPayload var pl RepoCommitStatusUpdatedPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case IssueCreatedEvent: case IssueCreatedEvent:
var pl IssueCreatedPayload var pl IssueCreatedPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case IssueUpdatedEvent: case IssueUpdatedEvent:
var pl IssueUpdatedPayload var pl IssueUpdatedPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case IssueCommentCreatedEvent: case IssueCommentCreatedEvent:
var pl IssueCommentCreatedPayload var pl IssueCommentCreatedPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestCreatedEvent: case PullRequestCreatedEvent:
var pl PullRequestCreatedPayload var pl PullRequestCreatedPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestUpdatedEvent: case PullRequestUpdatedEvent:
var pl PullRequestUpdatedPayload var pl PullRequestUpdatedPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestApprovedEvent: case PullRequestApprovedEvent:
var pl PullRequestApprovedPayload var pl PullRequestApprovedPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestApprovalRemovedEvent: case PullRequestApprovalRemovedEvent:
var pl PullRequestApprovalRemovedPayload var pl PullRequestApprovalRemovedPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestMergedEvent: case PullRequestMergedEvent:
var pl PullRequestMergedPayload var pl PullRequestMergedPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestDeclinedEvent: case PullRequestDeclinedEvent:
var pl PullRequestDeclinedPayload var pl PullRequestDeclinedPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestCommentCreatedEvent: case PullRequestCommentCreatedEvent:
var pl PullRequestCommentCreatedPayload var pl PullRequestCommentCreatedPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestCommentUpdatedEvent: case PullRequestCommentUpdatedEvent:
var pl PullRequestCommentUpdatedPayload var pl PullRequestCommentUpdatedPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestCommentDeletedEvent: case PullRequestCommentDeletedEvent:
var pl PullRequestCommentDeletedPayload var pl PullRequestCommentDeletedPayload
json.Unmarshal([]byte(payload), &pl) json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl) hook.runProcessPayloadFunc(fn, pl, hd)
} }
} }
func (hook Webhook) runProcessPayloadFunc(fn webhooks.ProcessPayloadFunc, results interface{}) { func (hook Webhook) runProcessPayloadFunc(fn webhooks.ProcessPayloadFunc, results interface{}, header webhooks.Header) {
go func(fn webhooks.ProcessPayloadFunc, results interface{}) { go func(fn webhooks.ProcessPayloadFunc, results interface{}, header webhooks.Header) {
fn(results) fn(results, header)
}(fn, results) }(fn, results, header)
} }
+2 -2
View File
@@ -9,7 +9,7 @@ import (
"time" "time"
. "gopkg.in/go-playground/assert.v1" . "gopkg.in/go-playground/assert.v1"
"gopkg.in/go-playground/webhooks.v1" "gopkg.in/go-playground/webhooks.v2"
) )
// NOTES: // NOTES:
@@ -29,7 +29,7 @@ const (
) )
// HandlePayload handles GitHub event(s) // HandlePayload handles GitHub event(s)
func HandlePayload(payload interface{}) { func HandlePayload(payload interface{}, header webhooks.Header) {
} }
+5 -4
View File
@@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"strconv" "strconv"
"gopkg.in/go-playground/webhooks.v1" "gopkg.in/go-playground/webhooks.v2"
"gopkg.in/go-playground/webhooks.v1/github" "gopkg.in/go-playground/webhooks.v2/github"
) )
const ( const (
@@ -14,6 +14,7 @@ const (
) )
func main() { func main() {
hook := github.New(&github.Config{Secret: "MyGitHubSuperSecretSecrect...?"}) hook := github.New(&github.Config{Secret: "MyGitHubSuperSecretSecrect...?"})
hook.RegisterEvents(HandleRelease, github.ReleaseEvent) hook.RegisterEvents(HandleRelease, github.ReleaseEvent)
hook.RegisterEvents(HandlePullRequest, github.PullRequestEvent) hook.RegisterEvents(HandlePullRequest, github.PullRequestEvent)
@@ -25,7 +26,7 @@ func main() {
} }
// HandleRelease handles GitHub release events // HandleRelease handles GitHub release events
func HandleRelease(payload interface{}) { func HandleRelease(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Release") fmt.Println("Handling Release")
@@ -41,7 +42,7 @@ func HandleRelease(payload interface{}) {
} }
// HandlePullRequest handles GitHub pull_request events // HandlePullRequest handles GitHub pull_request events
func HandlePullRequest(payload interface{}) { func HandlePullRequest(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Pull Request") fmt.Println("Handling Pull Request")
+4 -3
View File
@@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"strconv" "strconv"
"gopkg.in/go-playground/webhooks.v1" "gopkg.in/go-playground/webhooks.v2"
"gopkg.in/go-playground/webhooks.v1/github" "gopkg.in/go-playground/webhooks.v2/github"
) )
const ( const (
@@ -14,6 +14,7 @@ const (
) )
func main() { func main() {
hook := github.New(&github.Config{Secret: "MyGitHubSuperSecretSecrect...?"}) hook := github.New(&github.Config{Secret: "MyGitHubSuperSecretSecrect...?"})
hook.RegisterEvents(HandleMultiple, github.ReleaseEvent, github.PullRequestEvent) // Add as many as you want hook.RegisterEvents(HandleMultiple, github.ReleaseEvent, github.PullRequestEvent) // Add as many as you want
@@ -24,7 +25,7 @@ func main() {
} }
// HandleMultiple handles multiple GitHub events // HandleMultiple handles multiple GitHub events
func HandleMultiple(payload interface{}) { func HandleMultiple(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Payload..") fmt.Println("Handling Payload..")
+29 -26
View File
@@ -8,7 +8,7 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"gopkg.in/go-playground/webhooks.v1" "gopkg.in/go-playground/webhooks.v2"
) )
// Webhook instance contains all methods needed to process events // Webhook instance contains all methods needed to process events
@@ -129,96 +129,99 @@ func (hook Webhook) ParsePayload(w http.ResponseWriter, r *http.Request) {
} }
} }
// Make headers available to ProcessPayloadFunc as a webhooks type
hd := webhooks.Header(r.Header)
switch gitHubEvent { switch gitHubEvent {
case CommitCommentEvent: case CommitCommentEvent:
var cc CommitCommentPayload var cc CommitCommentPayload
json.Unmarshal([]byte(payload), &cc) json.Unmarshal([]byte(payload), &cc)
hook.runProcessPayloadFunc(fn, cc) hook.runProcessPayloadFunc(fn, cc, hd)
case CreateEvent: case CreateEvent:
var c CreatePayload var c CreatePayload
json.Unmarshal([]byte(payload), &c) json.Unmarshal([]byte(payload), &c)
hook.runProcessPayloadFunc(fn, c) hook.runProcessPayloadFunc(fn, c, hd)
case DeleteEvent: case DeleteEvent:
var d DeletePayload var d DeletePayload
json.Unmarshal([]byte(payload), &d) json.Unmarshal([]byte(payload), &d)
hook.runProcessPayloadFunc(fn, d) hook.runProcessPayloadFunc(fn, d, hd)
case DeploymentEvent: case DeploymentEvent:
var d DeploymentPayload var d DeploymentPayload
json.Unmarshal([]byte(payload), &d) json.Unmarshal([]byte(payload), &d)
hook.runProcessPayloadFunc(fn, d) hook.runProcessPayloadFunc(fn, d, hd)
case DeploymentStatusEvent: case DeploymentStatusEvent:
var d DeploymentStatusPayload var d DeploymentStatusPayload
json.Unmarshal([]byte(payload), &d) json.Unmarshal([]byte(payload), &d)
hook.runProcessPayloadFunc(fn, d) hook.runProcessPayloadFunc(fn, d, hd)
case ForkEvent: case ForkEvent:
var f ForkPayload var f ForkPayload
json.Unmarshal([]byte(payload), &f) json.Unmarshal([]byte(payload), &f)
hook.runProcessPayloadFunc(fn, f) hook.runProcessPayloadFunc(fn, f, hd)
case GollumEvent: case GollumEvent:
var g GollumPayload var g GollumPayload
json.Unmarshal([]byte(payload), &g) json.Unmarshal([]byte(payload), &g)
hook.runProcessPayloadFunc(fn, g) hook.runProcessPayloadFunc(fn, g, hd)
case IssueCommentEvent: case IssueCommentEvent:
var i IssueCommentPayload var i IssueCommentPayload
json.Unmarshal([]byte(payload), &i) json.Unmarshal([]byte(payload), &i)
hook.runProcessPayloadFunc(fn, i) hook.runProcessPayloadFunc(fn, i, hd)
case IssuesEvent: case IssuesEvent:
var i IssuesPayload var i IssuesPayload
json.Unmarshal([]byte(payload), &i) json.Unmarshal([]byte(payload), &i)
hook.runProcessPayloadFunc(fn, i) hook.runProcessPayloadFunc(fn, i, hd)
case MemberEvent: case MemberEvent:
var m MemberPayload var m MemberPayload
json.Unmarshal([]byte(payload), &m) json.Unmarshal([]byte(payload), &m)
hook.runProcessPayloadFunc(fn, m) hook.runProcessPayloadFunc(fn, m, hd)
case MembershipEvent: case MembershipEvent:
var m MembershipPayload var m MembershipPayload
json.Unmarshal([]byte(payload), &m) json.Unmarshal([]byte(payload), &m)
hook.runProcessPayloadFunc(fn, m) hook.runProcessPayloadFunc(fn, m, hd)
case PageBuildEvent: case PageBuildEvent:
var p PageBuildPayload var p PageBuildPayload
json.Unmarshal([]byte(payload), &p) json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p) hook.runProcessPayloadFunc(fn, p, hd)
case PublicEvent: case PublicEvent:
var p PublicPayload var p PublicPayload
json.Unmarshal([]byte(payload), &p) json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p) hook.runProcessPayloadFunc(fn, p, hd)
case PullRequestReviewCommentEvent: case PullRequestReviewCommentEvent:
var p PullRequestReviewCommentPayload var p PullRequestReviewCommentPayload
json.Unmarshal([]byte(payload), &p) json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p) hook.runProcessPayloadFunc(fn, p, hd)
case PullRequestEvent: case PullRequestEvent:
var p PullRequestPayload var p PullRequestPayload
json.Unmarshal([]byte(payload), &p) json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p) hook.runProcessPayloadFunc(fn, p, hd)
case PushEvent: case PushEvent:
var p PushPayload var p PushPayload
json.Unmarshal([]byte(payload), &p) json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p) hook.runProcessPayloadFunc(fn, p, hd)
case RepositoryEvent: case RepositoryEvent:
var r RepositoryPayload var r RepositoryPayload
json.Unmarshal([]byte(payload), &r) json.Unmarshal([]byte(payload), &r)
hook.runProcessPayloadFunc(fn, r) hook.runProcessPayloadFunc(fn, r, hd)
case ReleaseEvent: case ReleaseEvent:
var r ReleasePayload var r ReleasePayload
json.Unmarshal([]byte(payload), &r) json.Unmarshal([]byte(payload), &r)
hook.runProcessPayloadFunc(fn, r) hook.runProcessPayloadFunc(fn, r, hd)
case StatusEvent: case StatusEvent:
var s StatusPayload var s StatusPayload
json.Unmarshal([]byte(payload), &s) json.Unmarshal([]byte(payload), &s)
hook.runProcessPayloadFunc(fn, s) hook.runProcessPayloadFunc(fn, s, hd)
case TeamAddEvent: case TeamAddEvent:
var t TeamAddPayload var t TeamAddPayload
json.Unmarshal([]byte(payload), &t) json.Unmarshal([]byte(payload), &t)
hook.runProcessPayloadFunc(fn, t) hook.runProcessPayloadFunc(fn, t, hd)
case WatchEvent: case WatchEvent:
var w WatchPayload var w WatchPayload
json.Unmarshal([]byte(payload), &w) json.Unmarshal([]byte(payload), &w)
hook.runProcessPayloadFunc(fn, w) hook.runProcessPayloadFunc(fn, w, hd)
} }
} }
func (hook Webhook) runProcessPayloadFunc(fn webhooks.ProcessPayloadFunc, results interface{}) { func (hook Webhook) runProcessPayloadFunc(fn webhooks.ProcessPayloadFunc, results interface{}, header webhooks.Header) {
go func(fn webhooks.ProcessPayloadFunc, results interface{}) { go func(fn webhooks.ProcessPayloadFunc, results interface{}, header webhooks.Header) {
fn(results) fn(results, header)
}(fn, results) }(fn, results, header)
} }
+2 -2
View File
@@ -9,7 +9,7 @@ import (
"time" "time"
. "gopkg.in/go-playground/assert.v1" . "gopkg.in/go-playground/assert.v1"
"gopkg.in/go-playground/webhooks.v1" "gopkg.in/go-playground/webhooks.v2"
) )
// NOTES: // NOTES:
@@ -29,7 +29,7 @@ const (
) )
// HandlePayload handles GitHub event(s) // HandlePayload handles GitHub event(s)
func HandlePayload(payload interface{}) { func HandlePayload(payload interface{}, header webhooks.Header) {
} }
+144
View File
@@ -0,0 +1,144 @@
package gitlab
import (
"encoding/json"
"io/ioutil"
"net/http"
"gopkg.in/go-playground/webhooks.v2"
)
// Webhook instance contains all methods needed to process events
type Webhook struct {
provider webhooks.Provider
secret string
eventFuncs map[Event]webhooks.ProcessPayloadFunc
}
// Config defines the configuration to create a new GitHub Webhook instance
type Config struct {
Secret string
}
// Event defines a GitHub hook event type
type Event string
// GitLab hook types
const (
PushEvents Event = "Push Hook"
TagEvents Event = "Tag Push Hook"
IssuesEvents Event = "Issue Hook"
CommentEvents Event = "Note Hook"
MergerRequestEvents Event = "Merge Request Hook"
WikiPageEvents Event = "Wiki Page Hook"
PipelineEvents Event = "Pipeline Hook"
BuildEvents Event = "Build Hook"
)
// New creates and returns a WebHook instance denoted by the Provider type
func New(config *Config) *Webhook {
return &Webhook{
provider: webhooks.GitLab,
secret: config.Secret,
eventFuncs: map[Event]webhooks.ProcessPayloadFunc{},
}
}
// Provider returns the current hooks provider ID
func (hook Webhook) Provider() webhooks.Provider {
return hook.provider
}
// RegisterEvents registers the function to call when the specified event(s) are encountered
func (hook Webhook) RegisterEvents(fn webhooks.ProcessPayloadFunc, events ...Event) {
for _, event := range events {
hook.eventFuncs[event] = fn
}
}
// ParsePayload parses and verifies the payload and fires off the mapped function, if it exists.
func (hook Webhook) ParsePayload(w http.ResponseWriter, r *http.Request) {
event := r.Header.Get("X-Gitlab-Event")
if len(event) == 0 {
http.Error(w, "400 Bad Request - Missing X-Gitlab-Event Header", http.StatusBadRequest)
return
}
gitLabEvent := Event(event)
fn, ok := hook.eventFuncs[gitLabEvent]
// if no event registered
if !ok {
return
}
payload, err := ioutil.ReadAll(r.Body)
if err != nil || len(payload) == 0 {
http.Error(w, "Error reading Body", http.StatusInternalServerError)
return
}
// If we have a Secret set, we should check the MAC
if len(hook.secret) > 0 {
signature := r.Header.Get("X-Gitlab-Token")
if signature != hook.secret {
http.Error(w, "403 Forbidden - Token missmatch", http.StatusForbidden)
return
}
}
// Make headers available to ProcessPayloadFunc as a webhooks type
hd := webhooks.Header(r.Header)
switch gitLabEvent {
case PushEvents:
var pe PushEventPayload
json.Unmarshal([]byte(payload), &pe)
hook.runProcessPayloadFunc(fn, pe, hd)
case TagEvents:
var te TagEventPayload
json.Unmarshal([]byte(payload), &te)
hook.runProcessPayloadFunc(fn, te, hd)
case IssuesEvents:
var ie IssueEventPayload
json.Unmarshal([]byte(payload), &ie)
hook.runProcessPayloadFunc(fn, ie, hd)
case CommentEvents:
var ce CommentEventPayload
json.Unmarshal([]byte(payload), &ce)
hook.runProcessPayloadFunc(fn, ce, hd)
case MergerRequestEvents:
var mre MergeRequestEventPayload
json.Unmarshal([]byte(payload), &mre)
hook.runProcessPayloadFunc(fn, mre, hd)
case WikiPageEvents:
var wpe WikiPageEventPayload
json.Unmarshal([]byte(payload), &wpe)
hook.runProcessPayloadFunc(fn, wpe, hd)
case PipelineEvents:
var pe PipelineEventPayload
json.Unmarshal([]byte(payload), &pe)
hook.runProcessPayloadFunc(fn, pe, hd)
case BuildEvents:
var be BuildEventPayload
json.Unmarshal([]byte(payload), &be)
hook.runProcessPayloadFunc(fn, be, hd)
}
}
func (hook Webhook) runProcessPayloadFunc(fn webhooks.ProcessPayloadFunc, results interface{}, header webhooks.Header) {
go func(fn webhooks.ProcessPayloadFunc, results interface{}, header webhooks.Header) {
fn(results, header)
}(fn, results, header)
}
File diff suppressed because it is too large Load Diff
+404
View File
@@ -0,0 +1,404 @@
package gitlab
import (
"strings"
"time"
)
type customTime struct {
time.Time
}
func (t *customTime) UnmarshalJSON(b []byte) (err error) {
layout := []string{
"2006-01-02 15:04:05 MST",
"2006-01-02 15:04:05 Z07:00",
"2006-01-02 15:04:05 Z0700",
time.RFC3339,
}
s := strings.Trim(string(b), "\"")
if s == "null" {
t.Time = time.Time{}
return
}
for _, l := range layout {
t.Time, err = time.Parse(l, s)
if err == nil {
break
}
}
return
}
// IssueEventPayload contains the information for GitLab's issue event
type IssueEventPayload struct {
ObjectKind string `json:"object_kind"`
User User `json:"user"`
Project Project `json:"project"`
Repository Repository `json:"repository"`
ObjectAttributes ObjectAttributes `json:"object_attributes"`
Assignee Assignee `json:"assignee"`
}
// MergeRequestEventPayload contains the information for GitLab's merge request event
type MergeRequestEventPayload struct {
ObjectKind string `json:"object_kind"`
User User `json:"user"`
ObjectAttributes ObjectAttributes `json:"object_attributes"`
}
// PushEventPayload contains the information for GitLab's push event
type PushEventPayload struct {
ObjectKind string `json:"object_kind"`
Before string `json:"before"`
After string `json:"after"`
Ref string `json:"ref"`
CheckoutSHA string `json:"checkout_sha"`
UserID int `json:"user_id"`
UserName string `json:"user_name"`
UserEmail string `json:"user_email"`
UserAvatar string `json:"user_avatar"`
ProjectID int `json:"project_id"`
Project Project `json:"Project"`
Repository Repository `json:"repository"`
Commits []Commit `json:"commits"`
TotalCommitsCount int `json:"total_commits_count"`
}
// TagEventPayload contains the information for GitLab's tag push event
type TagEventPayload struct {
ObjectKind string `json:"object_kind"`
Before string `json:"before"`
After string `json:"after"`
Ref string `json:"ref"`
CheckoutSHA string `json:"checkout_sha"`
UserID int `json:"user_id"`
UserName string `json:"user_name"`
UserAvatar string `json:"user_avatar"`
ProjectID int `json:"project_id"`
Project Project `json:"Project"`
Repository Repository `json:"repository"`
Commits []Commit `json:"commits"`
TotalCommitsCount int `json:"total_commits_count"`
}
// WikiPageEventPayload contains the information for GitLab's wiki created/updated event
type WikiPageEventPayload struct {
ObjectKind string `json:"object_kind"`
User User `json:"user"`
Project Project `json:"project"`
Wiki Wiki `json:"wiki"`
ObjectAttributes ObjectAttributes `json:"object_attributes"`
}
// PipelineEventPayload contains the information for GitLab's pipeline status change event
type PipelineEventPayload struct {
ObjectKind string `json:"object_kind"`
User User `json:"user"`
Project Project `json:"project"`
Commit Commit `json:"commit"`
ObjectAttributes ObjectAttributes `json:"object_attributes"`
Builds []Build `json:"builds"`
}
// CommentEventPayload contains the information for GitLab's comment event
type CommentEventPayload struct {
ObjectKind string `json:"object_kind"`
User User `json:"user"`
ProjectID int `json:"project_id"`
Project Project `json:"project"`
Repository Repository `json:"repository"`
ObjectAttributes ObjectAttributes `json:"object_attributes"`
MergeRequest MergeRequest `json:"merge_request"`
Commit Commit `json:"commit"`
Issue Issue `json:"issue"`
Snippet Snippet `json:"snippet"`
}
// BuildEventPayload contains the information for GitLab's build status change event
type BuildEventPayload struct {
ObjectKind string `json:"object_kind"`
Ref string `json:"ref"`
Tag bool `json:"tag"`
BeforeSHA string `json:"before_sha"`
SHA string `json:"sha"`
BuildID int `json:"build_id"`
BuildName string `json:"build_name"`
BuildStage string `json:"build_stage"`
BuildStatus string `json:"build_status"`
BuildStartedAt customTime `json:"build_started_at"`
BuildFinishedAt customTime `json:"build_finished_at"`
BuildDuration int `json:"build_duration"`
BuildAllowFailure bool `json:"build_allow_failure"`
ProjectID int `json:"project_id"`
ProjectName string `json:"project_name"`
User User `json:"user"`
Commit BuildCommit `json:"commit"`
Repository Repository `json:"repository"`
}
// Issue contais all of the GitLab issue information
type Issue struct {
ID int `json:"id"`
Title string `json:"title"`
AssigneeID int `json:"assignee_id"`
AuthorID int `json:"author_id"`
ProjectID int `json:"project_id"`
CreatedAt customTime `json:"created_at"`
UpdatedAt customTime `json:"updated_at"`
Position int `json:"position"`
BranchName string `json:"branch_name"`
Description string `json:"description"`
MilestoneID int `json:"milestone_id"`
State string `json:"state"`
IID int `json:"iid"`
}
// Build contais all of the GitLab build information
type Build struct {
ID int `json:"id"`
Stage string `json:"stage"`
Name string `json:"name"`
Status string `json:"status"`
CreatedAt customTime `json:"created_at"`
StartedAt customTime `json:"started_at"`
FinishedAt customTime `json:"finished_at"`
When string `json:"when"`
Manual bool `json:"manual"`
User User `json:"user"`
Runner string `json:"runner"`
ArtifactsFile ArtifactsFile `json:"artifactsfile"`
}
// ArtifactsFile contais all of the GitLab artifact information
type ArtifactsFile struct {
Filename string `json:"filename"`
Size string `json:"size"`
}
// Wiki contais all of the GitLab wiki information
type Wiki struct {
WebURL string `json:"web_url"`
GitSSHURL string `json:"git_ssh_url"`
GitHTTPURL string `json:"git_http_url"`
PathWithNamespace string `json:"path_with_namespace"`
DefaultBranch string `json:"default_branch"`
}
// Commit contais all of the GitLab commit information
type Commit struct {
ID string `json:"id"`
Message string `json:"message"`
Timestamp customTime `json:"timestamp"`
URL string `json:"url"`
Author Author `json:"author"`
Added []string `json:"added"`
Modified []string `json:"modified"`
Removed []string `json:"removed"`
}
// BuildCommit contais all of the GitLab build commit information
type BuildCommit struct {
ID int `json:"id"`
SHA string `json:"sha"`
Message string `json:"message"`
AuthorName string `json:"auuthor_name"`
AuthorEmail string `json:"author_email"`
Status string `json:"status"`
Duration int `json:"duration"`
StartedAt customTime `json:"started_at"`
FinishedAt customTime `json:"finished_at"`
}
// Snippet contais all of the GitLab snippet information
type Snippet struct {
ID int `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
AuthorID int `json:"author_id"`
ProjectID int `json:"project_id"`
CreatedAt customTime `json:"created_at"`
UpdatedAt customTime `json:"updated_at"`
FileName string `json:"file_name"`
ExpiresAt customTime `json:"expires_at"`
Type string `json:"type"`
VisibilityLevel int `json:"visibility_level"`
}
// User contais all of the GitLab user information
type User struct {
Name string `json:"name"`
UserName string `json:"username"`
AvatarURL string `json:"avatar_url"`
}
// Project contais all of the GitLab project information
type Project struct {
Name string `json:"name"`
Description string `json:"description"`
WebURL string `json:"web_url"`
AvatarURL string `json:"avatar_url"`
GitSSSHURL string `json:"git_ssh_url"`
GitHTTPURL string `json:"git_http_url"`
Namespace string `json:"namespace"`
VisibilityLevel int `json:"visibility_level"`
PathWithNamespace string `json:"path_with_namespace"`
DefaultBranch string `json:"default_branch"`
Homepage string `json:"homepage"`
URL string `json:"url"`
SSHURL string `json:"ssh_url"`
HTTPURL string `json:"http_url"`
}
// Repository contais all of the GitLab repository information
type Repository struct {
Name string `json:"name"`
URL string `json:"url"`
Description string `json:"description"`
Homepage string `json:"homepage"`
}
// ObjectAttributes contais all of the GitLab object attributes information
type ObjectAttributes struct {
ID int `json:"id"`
Title string `json:"title"`
AssigneeID int `json:"assignee_id"`
AuthorID int `json:"author_id"`
ProjectID int `json:"project_id"`
CreatedAt customTime `json:"created_at"`
UpdatedAt customTime `json:"updated_at"`
Position int `json:"position"`
BranchName string `json:"branch_name"`
Description string `json:"description"`
MilestoneID int `json:"milestone_id"`
State string `json:"state"`
IID int `json:"iid"`
URL string `json:"url"`
Action string `json:"action"`
TargetBranch string `json:"target_branch"`
SourceBranch string `json:"source_branch"`
SourceProjectID int `json:"source_project_id"`
TargetProjectID int `json:"target_project_id"`
StCommits string `json:"st_commits"`
MergeStatus string `json:"merge_status"`
Content string `json:"content"`
Format string `json:"format"`
Message string `json:"message"`
Slug string `json:"slug"`
Ref string `json:"ref"`
Tag bool `json:"tag"`
SHA string `json:"sha"`
BeforeSHA string `json:"before_sha"`
Status string `json:"status"`
Stages []string `json:"stages"`
Duration int `json:"duration"`
Note string `json:"note"`
NotebookType string `json:"noteable_type"`
At customTime `json:"attachment"`
LineCode string `json:"line_code"`
CommitID string `json:"commit_id"`
NoteableID int `json:"noteable_id"`
System bool `json:"system"`
WorkInProgress bool `json:"work_in_progress"`
StDiffs []StDiff `json:"st_diffs"`
Source Source `json:"source"`
Target Target `json:"target"`
LastCommit LastCommit `json:"last_commit"`
Assignee Assignee `json:"assignee"`
}
// MergeRequest contais all of the GitLab merge request information
type MergeRequest struct {
ID int `json:"id"`
TargetBranch string `json:"target_branch"`
SourceBranch string `json:"source_branch"`
SourceProjectID string `json:"source_project_id"`
AssigneeID int `json:"assignee_id"`
AuthorID int `json:"author_id"`
Title string `json:"title"`
CreatedAt customTime `json:"created_at"`
UpdatedAt customTime `json:"updated_at"`
MilestoneID int `json:"milestone_id"`
State string `json:"state"`
MergeStatus string `json:"merge_status"`
TargetProjectID int `json:"target_project_id"`
IID int `json:"iid"`
Description string `json:"description"`
Position int `json:"position"`
LockedAt customTime `json:"locked_at"`
Source Source `json:"source"`
Target Target `json:"target"`
LastCommit LastCommit `json:"last_commit"`
WorkInProgress bool `json:"work_in_progress"`
Assignee Assignee `json:"assignee"`
}
// Assignee contais all of the GitLab assignee information
type Assignee struct {
Name string `json:"name"`
Username string `json:"username"`
AvatarURL string `json:"avatar_url"`
}
// StDiff contais all of the GitLab diff information
type StDiff struct {
Diff string `json:"diff"`
NewPath string `json:"new_path"`
OldPath string `json:"old_path"`
AMode string `json:"a_mode"`
BMode string `json:"b_mode"`
NewFile bool `json:"new_file"`
RenamedFile bool `json:"renamed_file"`
DeletedFile bool `json:"deleted_file"`
}
// Source contais all of the GitLab source information
type Source struct {
Name string `json:"name"`
Description string `json:"description"`
WebURL string `json:"web_url"`
AvatarURL string `json:"avatar_url"`
GitSSHURL string `json:"git_ssh_url"`
GitHTTPURL string `json:"git_http_url"`
Namespace string `json:"namespace"`
VisibilityLevel int `json:"visibility_level"`
PathWithNamespace string `json:"path_with_namespace"`
DefaultBranch string `json:"default_branch"`
Homepage string `json:"homepage"`
URL string `json:"url"`
SSHURL string `json:"ssh_url"`
HTTPURL string `json:"http_url"`
}
// Target contais all of the GitLab target information
type Target struct {
Name string `json:"name"`
Description string `json:"description"`
WebURL string `json:"web_url"`
AvatarURL string `json:"avatar_url"`
GitSSHURL string `json:"git_ssh_url"`
GitHTTPURL string `json:"git_http_url"`
Namespace string `json:"namespace"`
VisibilityLevel int `json:"visibility_level"`
PathWithNamespace string `json:"path_with_namespace"`
DefaultBranch string `json:"default_branch"`
Homepage string `json:"homepage"`
URL string `json:"url"`
SSHURL string `json:"ssh_url"`
HTTPURL string `json:"http_url"`
}
// LastCommit contais all of the GitLab last commit information
type LastCommit struct {
ID string `json:"id"`
Message string `json:"message"`
Timestamp customTime `json:"timestamp"`
URL string `json:"url"`
Author Author `json:"author"`
}
// Author contais all of the GitLab author information
type Author struct {
Name string `json:"name"`
Email string `json:"email"`
}
+8 -2
View File
@@ -2,6 +2,9 @@ package webhooks
import "net/http" import "net/http"
// Header provides http.Header to minimize imports
type Header http.Header
// Provider defines the type of webhook // Provider defines the type of webhook
type Provider int type Provider int
@@ -11,6 +14,8 @@ func (p Provider) String() string {
return "GitHub" return "GitHub"
case Bitbucket: case Bitbucket:
return "Bitbucket" return "Bitbucket"
case GitLab:
return "GitLab"
default: default:
return "Unknown" return "Unknown"
} }
@@ -20,6 +25,7 @@ func (p Provider) String() string {
const ( const (
GitHub Provider = iota GitHub Provider = iota
Bitbucket Bitbucket
GitLab
) )
// Webhook interface defines a webhook to recieve events // Webhook interface defines a webhook to recieve events
@@ -34,7 +40,7 @@ type server struct {
} }
// ProcessPayloadFunc is a common function for payload return values // ProcessPayloadFunc is a common function for payload return values
type ProcessPayloadFunc func(payload interface{}) type ProcessPayloadFunc func(payload interface{}, header Header)
// Run runs a server // Run runs a server
func Run(hook Webhook, addr string, path string) error { func Run(hook Webhook, addr string, path string) error {
@@ -64,7 +70,7 @@ func RunServer(s *http.Server, hook Webhook, path string) error {
// RunTLSServer runs a custom server with TLS configuration. // RunTLSServer runs a custom server with TLS configuration.
// NOTE: http.Server Handler will be overridden by this library, just set it to nil. // NOTE: http.Server Handler will be overridden by this library, just set it to nil.
// Setting the Certificates can be done in the http.Server.TLSConfig.Certificates // Setting the Certificates can be done in the http.Server.TLSConfig.Certificates
// see example here: https://gopkg.in/go-playground/webhooks.v1/blob/master/webhooks_test.go#L178 // see example here: https://github.com/go-playground/webhooks/blob/v2/webhooks_test.go#L178
func RunTLSServer(s *http.Server, hook Webhook, path string) error { func RunTLSServer(s *http.Server, hook Webhook, path string) error {
srv := &server{ srv := &server{
+1
View File
@@ -236,5 +236,6 @@ func TestProviderString(t *testing.T) {
Equal(t, GitHub.String(), "GitHub") Equal(t, GitHub.String(), "GitHub")
Equal(t, Bitbucket.String(), "Bitbucket") Equal(t, Bitbucket.String(), "Bitbucket")
Equal(t, GitLab.String(), "GitLab")
Equal(t, Provider(999999).String(), "Unknown") Equal(t, Provider(999999).String(), "Unknown")
} }