Compare commits

...

86 Commits

Author SHA1 Message Date
Dean Karn adb918738a Update README.md 2018-07-20 07:02:01 -07:00
Dean Karn 9cc34fc5d1 Merge pull request #38 from bafko/37-pushpayload
Updated Github PushPayload
2018-07-20 07:01:43 -07:00
bafko 63866ac80d Updated Github PushPayload 2018-07-19 17:26:06 +02:00
Dean Karn 866b461aac Update README.md 2018-07-15 20:49:11 -07:00
Dean Karn 0035246764 Merge pull request #36 from binkkatal/feature/owner_fields_in_github_push_event_payload
Add fields in PushPayload for repository owner
2018-07-15 20:48:34 -07:00
binkkatal 443e255708 Fix failing TestCommitCommentEvent
Due to a slight change in the payload , the ssh for payload changed.
This was the reason for failing test case
2018-07-14 11:38:41 +05:30
binkkatal eb56c26534 Skip TestCommitCommentEvent 2018-07-14 11:30:50 +05:30
binkkatal 2d55603413 Add fields in PushPayload for repository owner
All other webhook events have all the repository owner fields except push event.
This commit adds owner fields in `PushPayload`
```
Login             string `json:"login"`
ID                int64  `json:"id"`
AvatarURL         string `json:"avatar_url"`
GravatarID        string `json:"gravatar_id"`
URL               string `json:"url"`
HTMLURL           string `json:"html_url"`
FollowersURL      string `json:"followers_url"`
FollowingURL      string `json:"following_url"`
GistsURL          string `json:"gists_url"`
StarredURL        string `json:"starred_url"`
SubscriptionsURL  string `json:"subscriptions_url"`
OrganizationsURL  string `json:"organizations_url"`
ReposURL          string `json:"repos_url"`
EventsURL         string `json:"events_url"`
ReceivedEventsURL string `json:"received_events_url"`
Type              string `json:"type"`
SiteAdmin         bool   `json:"site_admin"`
```
2018-07-08 16:47:39 +05:30
Dean Karn b9b0e19032 Update README.md 2018-06-28 12:55:36 -07:00
Dean Karn e4aa8cba6c Update README.md 2018-06-28 12:47:55 -07:00
Dean Karn 28d44801e9 Merge pull request #32 from c-Brooks/v4
Make Logger interface more flexible
2018-06-28 12:45:57 -07:00
Dean Karn 7e745505c0 Merge pull request #34 from go-playground/v3
Merge latest v3 changes
2018-06-28 12:34:55 -07:00
Dean Karn 8ffb2ffc32 Update README.md 2018-06-28 12:32:45 -07:00
Dean Karn 84dc839b94 Merge pull request #33 from kishorenc/fix_deployment_payload
Deployment Payload fields should be of type string.
2018-06-28 12:32:17 -07:00
Kishore Nallan 2c541a737f Deployment Payload fields should be string. 2018-06-28 16:33:41 +05:30
Corey Brooks d9e847f7ea Make Logger interface more flexible 2018-06-21 09:28:35 -07:00
Dean Karn be944ed461 update REAME + travis.yml 2018-05-08 07:55:49 -07:00
Dean Karn 16896cdb6b Merge pull request #29 from naiba/v3
Add gogs support
2018-05-08 07:51:34 -07:00
奶爸 3e1bb69b7d fix merge issue 2018-05-08 22:09:43 +08:00
奶爸 c9c9d981d7 godmt 2018-05-07 18:42:23 +08:00
奶爸 22713e3054 add gogs support 2018-05-07 18:41:12 +08:00
奶爸 0ebe5231e2 merge 2018-04-11 16:13:03 +08:00
奶爸 b26a00f48c remove space 2018-04-11 16:11:21 +08:00
Dean Karn 5580947e3e Update README.md 2018-04-08 09:15:57 -07:00
Dean Karn 8db8abb389 Merge pull request #28 from rtnpro/parse-github-pull-request-labels
Parse Github pull request labels from pull request payload.
2018-04-08 09:15:30 -07:00
Ratnadeep Debnath 9e4b7fa61b Parse Github pull request labels from pull request payload. 2018-04-02 12:14:20 +05:30
奶爸 a831111e26 Merge remote-tracking branch 'upstream/v3' into v3 2018-03-23 11:19:22 +08:00
Dean Karn f2acbcde40 Update README.md 2018-03-21 08:13:12 -07:00
Dean Karn 3ad83a882d Update README.md 2018-03-21 08:12:58 -07:00
Dean Karn 32331e68eb Merge pull request #27 from lukepatrick/v3
fix(bitbucket) typo in Event
2018-03-21 08:12:28 -07:00
奶爸 6d731433c9 Merge remote-tracking branch 'upstream/v3' into v3 2018-03-21 16:25:13 +08:00
lukepatrick 1253715fd8 fix(bitbucket) typo in Event 2018-03-20 11:20:36 -06:00
奶爸 d4d9692af0 [fix]Gogs sign verify 2018-03-20 11:27:21 +08:00
Dean Karn 1b6492ce45 Merge pull request #26 from kuiro5/add-requested-reviewers
Add RequestedReviewers to PullRequestPayload
2018-03-19 08:41:56 -07:00
奶爸 493e94de50 [fix] Gogs signature calc 2018-03-19 16:16:01 +08:00
奶爸 fc20b2a250 ignore IDEA 2018-03-19 14:26:32 +08:00
奶爸 1c3914ef16 edit import 2018-03-19 14:25:52 +08:00
奶爸 2aa5fdc243 add gogs support 2018-03-19 14:03:56 +08:00
kuiros ea44f6921c Add RequestedReviewers to PullRequestPayload 2018-03-10 15:33:16 -08:00
Dean Karn b6e930d373 Update README.md 2018-02-23 05:13:07 -08:00
Dean Karn c271ec3e32 Merge pull request #25 from lukepatrick/v3
Update bitbucket uuid check to allow a non-specified uuid, similar to…
2018-02-23 05:10:58 -08:00
lukepatrick 0c4911f7f5 Update bitbucket uuid check to allow a non-specified uuid, similar to gitlab empty secret. 2018-02-22 15:27:54 -07:00
Dean Karn 3667088d60 Merge pull request #24 from lukepatrick/v3
update MergeRequestEvent payload with Project, Repo objects from the API
2018-02-15 07:22:55 -08:00
lukepatrick 9cafa895ff update MergeRequestEvent payload with Project, Repo objects from the API 2018-02-14 12:45:52 -07:00
Dean Karn 9494e434fc Update README.md 2018-01-19 08:54:08 -08:00
Dean Karn 97dd8f3564 Merge pull request #23 from PombeirP/add-installation-and-ping
Add installation and ping
2018-01-19 08:46:12 -08:00
Pedro Pombeiro 8f6fada23d Add support for ping events 2018-01-16 10:15:54 +01:00
Pedro Pombeiro 94f9d6694d Add support for installation and integration_installation events 2018-01-16 10:15:29 +01:00
Dean Karn ad5392160c Update README.md 2017-12-17 22:05:38 -08:00
Dean Karn 19cab958b6 Merge pull request #21 from Mingan/master
[GitLab] Parse label changes on issue and MR events
2017-12-17 22:05:13 -08:00
Štěpán Pilař 78ce03b046 [GitLab] Parse label changes on issue and MR events 2017-12-17 17:50:34 +01:00
Dean Karn ced2e979bc Merge pull request #19 from kairen/add-author-association
Add parse author association for GitHub comment
2017-10-22 09:17:54 -07:00
kairen d60a03e52a Add parse author association for GitHub comment 2017-10-20 16:14:26 +08:00
Dean Karn f553bfaa59 Update README.md 2017-10-01 19:29:18 -07:00
Dean Karn 903279e458 add test for confidential issues gitlab 2017-10-01 19:24:09 -07:00
Dean Karn 5462959f1e Merge pull request #18 from tulir/patch-2
[GitLab] Add support for confidential issues
2017-10-01 19:17:33 -07:00
Dean Karn 4964805803 Merge pull request #17 from tulir/patch-1
[GitLab] Fix type of SourceProjectID in MergeRequest struct
2017-10-01 19:16:55 -07:00
Tulir Asokan 13e6611c00 Add separate payload type for confidential issues 2017-10-01 23:13:19 +03:00
Tulir Asokan b9424ab72e Add support for confidential GitLab issues 2017-10-01 13:56:19 +03:00
Tulir Asokan 203bf4218b Fix type of SourceProjectID in MergeRequest struct
It should be an int64, but was a string.
https://docs.gitlab.com/ce/user/project/integrations/webhooks.html#comment-on-merge-request

The incorrect type caused the MergeRequest field in comment event payloads to be empty.
2017-09-29 19:54:03 +00:00
Dean Karn 5e4be82c0b Update README.md 2017-08-17 08:39:34 -07:00
Dean Karn cd89a10b64 Merge pull request #16 from samuelkarp/pr-label
payload: add Label to PullRequestPayload
2017-08-17 08:34:59 -07:00
Samuel Karp e120e3b3ba payload: add Label to PullRequestPayload 2017-08-12 17:24:29 -07:00
Dean Karn a5141d656b Add customizable Logger interface + info,error and debugs (#14)
* Add customizable Logger interface + info,error and debugs
* update travis.yml to atest golang versions
2017-07-15 12:12:11 -07:00
Dean Karn 9a8b92d028 Update README 2017-05-04 15:04:26 -04:00
Dean Karn 248dae5b83 Merge branch 'rakeshbala-fix/githubPushPayload' into v3 2017-05-04 15:02:51 -04:00
Rakesh Balasubramanian cc075dfe29 fix(github): adds sha to commits in push payload 2017-05-02 11:25:35 -04:00
Dean Karn c93876b3e9 Merge pull request #10 from go-playground/add-handler-support
Add handler support
2017-04-27 19:24:15 -04:00
Dean Karn 0926003ddf .travis.yml tweak for gopkg.in 2017-04-27 19:19:51 -04:00
Dean Karn 58dd13d367 Add Handler function
Handler(...) return an http.Handler of the webhook for use within your own Mux
2017-04-27 17:57:51 -04:00
Dean Karn 4fa39fdfab Add .travis.yml config 2017-04-27 17:40:55 -04:00
Dean Karn fccbba5986 Update README example typo 2017-04-22 12:47:22 -04:00
Dean Karn 0d7e42cf96 correct some spelling 2017-04-21 22:13:16 -04:00
Dean Karn c9ac93f3b3 Update README 2017-04-21 22:06:42 -04:00
Dean Karn 2d256610b0 Update BitBucket + GitLab Payloads 2017-04-21 22:03:45 -04:00
Dean Karn 05a2f7cd8d refine payload interface{} to types 2017-04-21 20:40:02 -04:00
Dean Karn 5ed22cdd66 Initial GitHub Webhook revamp 2017-04-21 19:45:07 -04:00
Dean Karn 2e471dc89c Update MergerRequestEvents to MergeRequestEvents 2017-04-21 16:11:04 -04:00
Dean Karn 64819086ff Update README.md 2017-04-08 11:48:29 -04:00
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
19 changed files with 10686 additions and 1900 deletions
+1
View File
@@ -6,6 +6,7 @@
# Folders
_obj
_test
.idea
# Architecture specific extensions/prefixes
*.[568vq]
+39
View File
@@ -0,0 +1,39 @@
language: go
go:
- 1.10.2
- tip
matrix:
allow_failures:
- go: tip
notifications:
email:
recipients: dean.karn@gmail.com
on_success: change
on_failure: always
before_install:
- go get -u github.com/go-playground/overalls
- go get -u github.com/mattn/goveralls
- go get -u golang.org/x/tools/cmd/cover
- go get -u github.com/golang/lint/golint
- go get -u github.com/gordonklaus/ineffassign
- mkdir -p $GOPATH/src/gopkg.in
- ln -s $GOPATH/src/github.com/$TRAVIS_REPO_SLUG $GOPATH/src/gopkg.in/webhooks.v2
- ln -s $GOPATH/src/github.com/$TRAVIS_REPO_SLUG $GOPATH/src/gopkg.in/webhooks.v3
- ln -s $GOPATH/src/github.com/$TRAVIS_REPO_SLUG $GOPATH/src/gopkg.in/webhooks.v4
before_script:
- go vet ./...
script:
- gofmt -d -s .
- golint ./...
- ineffassign ./
- go test -v ./...
- go test -race
after_success: |
[ $TRAVIS_GO_VERSION = 1.10.2 ] &&
overalls -project="github.com/go-playground/webhooks" -covermode=count -ignore=.git,examples -debug &&
goveralls -coverprofile=overalls.coverprofile -service travis-ci -repotoken $COVERALLS_TOKEN
+25 -31
View File
@@ -1,14 +1,13 @@
Library webhooks
================
<img align="right" src="https://raw.githubusercontent.com/go-playground/webhooks/v1/logo.png">
![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)
[![Coverage Status](https://coveralls.io/repos/go-playground/webhooks/badge.svg?branch=v1&service=github)](https://coveralls.io/github/go-playground/webhooks?branch=v1)
<img align="right" src="https://raw.githubusercontent.com/go-playground/webhooks/v3/logo.png">![Project status](https://img.shields.io/badge/version-4.1.1-green.svg)
[![Build Status](https://travis-ci.org/go-playground/webhooks.svg?branch=v4)](https://travis-ci.org/go-playground/webhooks)
[![Coverage Status](https://coveralls.io/repos/go-playground/webhooks/badge.svg?branch=v4&service=github)](https://coveralls.io/github/go-playground/webhooks?branch=v3)
[![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.v4?status.svg)](https://godoc.org/gopkg.in/go-playground/webhooks.v4)
![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 receiving and parsing of GitHub, Bitbucket and GitLab Webhook Events
Features:
@@ -17,27 +16,25 @@ Features:
Notes:
* Github - Currently only accepting json payloads.
* Currently only accepting json payloads.
Installation
------------
Use go get.
go get gopkg.in/go-playground/webhooks.v1
```shell
go get -u gopkg.in/go-playground/webhooks.v4
```
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.v4"
Then import the validator package into your own code.
import "gopkg.in/go-playground/webhooks.v1"
Usage and documentation
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.v4 for detailed usage docs.
##### Examples:
@@ -49,8 +46,8 @@ import (
"fmt"
"strconv"
"gopkg.in/go-playground/webhooks.v1"
"gopkg.in/go-playground/webhooks.v1/github"
"gopkg.in/go-playground/webhooks.v4"
"gopkg.in/go-playground/webhooks.v4/github"
)
const (
@@ -59,6 +56,7 @@ const (
)
func main() {
hook := github.New(&github.Config{Secret: "MyGitHubSuperSecretSecrect...?"})
hook.RegisterEvents(HandleRelease, github.ReleaseEvent)
hook.RegisterEvents(HandlePullRequest, github.PullRequestEvent)
@@ -70,14 +68,14 @@ func main() {
}
// HandleRelease handles GitHub release events
func HandleRelease(payload interface{}) {
func HandleRelease(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Release")
pl := payload.(github.ReleasePayload)
// only want to compile on full releases
if pl.Release.Draft || pl.Release.Prelelease || pl.Release.TargetCommitish != "master" {
if pl.Release.Draft || pl.Release.Prerelease || pl.Release.TargetCommitish != "master" {
return
}
@@ -86,7 +84,7 @@ func HandleRelease(payload interface{}) {
}
// HandlePullRequest handles GitHub pull_request events
func HandlePullRequest(payload interface{}) {
func HandlePullRequest(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Pull Request")
@@ -105,8 +103,8 @@ import (
"fmt"
"strconv"
"gopkg.in/go-playground/webhooks.v1"
"gopkg.in/go-playground/webhooks.v1/github"
"gopkg.in/go-playground/webhooks.v4"
"gopkg.in/go-playground/webhooks.v4/github"
)
const (
@@ -115,6 +113,7 @@ const (
)
func main() {
hook := github.New(&github.Config{Secret: "MyGitHubSuperSecretSecrect...?"})
hook.RegisterEvents(HandleMultiple, github.ReleaseEvent, github.PullRequestEvent) // Add as many as you want
@@ -125,7 +124,7 @@ func main() {
}
// HandleMultiple handles multiple GitHub events
func HandleMultiple(payload interface{}) {
func HandleMultiple(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Payload..")
@@ -147,14 +146,9 @@ func HandleMultiple(payload interface{}) {
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,
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.
If the changes being proposed or requested are breaking changes, please create an issue for discussion.
License
------
+65 -45
View File
@@ -2,10 +2,11 @@ package bitbucket
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"gopkg.in/go-playground/webhooks.v1"
"gopkg.in/go-playground/webhooks.v4"
)
// Webhook instance contains all methods needed to process events
@@ -25,23 +26,24 @@ type Event string
// Bitbucket hook types
const (
RepoPushEvent Event = "repo:push"
RepoForkEvent Event = "repo:fork"
RepoCommitCommentCreatedEvent Event = "repo:commit_comment_created"
RepoCommitStatusCreatedEvent Event = "repo:commit_status_created"
RepoCommitStatusUpdatedEvent Event = "repo:commit_status_updated"
IssueCreatedEvent Event = "issue:created"
IssueUpdatedEvent Event = "issue:updated"
IssueCommentCreatedEvent Event = "issue:comment_created"
PullRequestCreatedEvent Event = "pullrequest:created"
PullRequestUpdatedEvent Event = "pullrequest:updated"
PullRequestApprovedEvent Event = "pullrequest:approved"
PullRequestApprovalRemovedEvent Event = "pullrequest:unapproved"
PullRequestMergedEvent Event = "pullrequest:fulfilled"
PullRequestDeclinedEvent Event = "pullrequest:rejected"
PullRequestCommentCreatedEvent Event = "pullrequest:comment_created"
PullRequestCommentUpdatedEvent Event = "pullrequest:comment_updated"
PullRequestCommentDeletedEvent Event = "pull_request:comment_deleted"
RepoPushEvent Event = "repo:push"
RepoForkEvent Event = "repo:fork"
RepoUpdatedEvent Event = "repo:updated"
RepoCommitCommentCreatedEvent Event = "repo:commit_comment_created"
RepoCommitStatusCreatedEvent Event = "repo:commit_status_created"
RepoCommitStatusUpdatedEvent Event = "repo:commit_status_updated"
IssueCreatedEvent Event = "issue:created"
IssueUpdatedEvent Event = "issue:updated"
IssueCommentCreatedEvent Event = "issue:comment_created"
PullRequestCreatedEvent Event = "pullrequest:created"
PullRequestUpdatedEvent Event = "pullrequest:updated"
PullRequestApprovedEvent Event = "pullrequest:approved"
PullRequestUnapprovedEvent Event = "pullrequest:unapproved"
PullRequestMergedEvent Event = "pullrequest:fulfilled"
PullRequestDeclinedEvent Event = "pullrequest:rejected"
PullRequestCommentCreatedEvent Event = "pullrequest:comment_created"
PullRequestCommentUpdatedEvent Event = "pullrequest:comment_updated"
PullRequestCommentDeletedEvent Event = "pullrequest:comment_deleted"
)
// New creates and returns a WebHook instance denoted by the Provider type
@@ -68,112 +70,130 @@ func (hook Webhook) RegisterEvents(fn webhooks.ProcessPayloadFunc, events ...Eve
// 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) {
webhooks.DefaultLog.Info("Parsing Payload...")
uuid := r.Header.Get("X-Hook-UUID")
if uuid == "" {
webhooks.DefaultLog.Error("Missing X-Hook-UUID Header")
http.Error(w, "400 Bad Request - Missing X-Hook-UUID Header", http.StatusBadRequest)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("X-Hook-UUID:%s", uuid))
if uuid != hook.uuid {
http.Error(w, "403 Forbidden - Missing X-Hook-UUID does not match", http.StatusForbidden)
return
if len(hook.uuid) > 0 {
if uuid != hook.uuid {
webhooks.DefaultLog.Error(fmt.Sprintf("X-Hook-UUID %s does not match configured uuid of %s", uuid, hook.uuid))
http.Error(w, "403 Forbidden - X-Hook-UUID does not match", http.StatusForbidden)
return
}
} else {
webhooks.DefaultLog.Debug("hook uuid not defined - recommend setting for improved security")
}
event := r.Header.Get("X-Event-Key")
if event == "" {
webhooks.DefaultLog.Error("Missing X-Event-Key Header")
http.Error(w, "400 Bad Request - Missing X-Event-Key Header", http.StatusBadRequest)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("X-Event-Key:%s", event))
bitbucketEvent := Event(event)
fn, ok := hook.eventFuncs[bitbucketEvent]
// if no event registered
if !ok {
webhooks.DefaultLog.Info(fmt.Sprintf("Webhook Event %s not registered, it is recommended to setup only events in bitbucket that will be registered in the webhook to avoid unnecessary traffic and reduce potential attack vectors.", event))
return
}
payload, err := ioutil.ReadAll(r.Body)
if err != nil || len(payload) == 0 {
http.Error(w, "Error reading Body", http.StatusInternalServerError)
webhooks.DefaultLog.Error("Issue reading Payload")
http.Error(w, "Issue reading Payload", http.StatusInternalServerError)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("Payload:%s", string(payload)))
hd := webhooks.Header(r.Header)
switch bitbucketEvent {
case RepoPushEvent:
var pl RepoPushPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case RepoForkEvent:
var pl RepoForkPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case RepoUpdatedEvent:
var pl RepoUpdatedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case RepoCommitCommentCreatedEvent:
var pl RepoCommitCommentCreatedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case RepoCommitStatusCreatedEvent:
var pl RepoCommitStatusCreatedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case RepoCommitStatusUpdatedEvent:
var pl RepoCommitStatusUpdatedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case IssueCreatedEvent:
var pl IssueCreatedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case IssueUpdatedEvent:
var pl IssueUpdatedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case IssueCommentCreatedEvent:
var pl IssueCommentCreatedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestCreatedEvent:
var pl PullRequestCreatedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestUpdatedEvent:
var pl PullRequestUpdatedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestApprovedEvent:
var pl PullRequestApprovedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
case PullRequestApprovalRemovedEvent:
var pl PullRequestApprovalRemovedPayload
hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestUnapprovedEvent:
var pl PullRequestUnapprovedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestMergedEvent:
var pl PullRequestMergedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestDeclinedEvent:
var pl PullRequestDeclinedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestCommentCreatedEvent:
var pl PullRequestCommentCreatedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestCommentUpdatedEvent:
var pl PullRequestCommentUpdatedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
case PullRequestCommentDeletedEvent:
var pl PullRequestCommentDeletedPayload
json.Unmarshal([]byte(payload), &pl)
hook.runProcessPayloadFunc(fn, pl)
hook.runProcessPayloadFunc(fn, pl, hd)
}
}
func (hook Webhook) runProcessPayloadFunc(fn webhooks.ProcessPayloadFunc, results interface{}) {
go func(fn webhooks.ProcessPayloadFunc, results interface{}) {
fn(results)
}(fn, results)
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)
}
+183 -27
View File
@@ -9,7 +9,7 @@ import (
"time"
. "gopkg.in/go-playground/assert.v1"
"gopkg.in/go-playground/webhooks.v1"
"gopkg.in/go-playground/webhooks.v4"
)
// NOTES:
@@ -24,12 +24,12 @@ import (
//
//
const (
port = 3010
port = 3009
path = "/webhooks"
)
// HandlePayload handles GitHub event(s)
func HandlePayload(payload interface{}) {
func HandlePayload(payload interface{}, header webhooks.Header) {
}
@@ -39,10 +39,30 @@ func TestMain(m *testing.M) {
// setup
hook = New(&Config{UUID: "MY_UUID"})
hook.RegisterEvents(HandlePayload, RepoPushEvent, RepoForkEvent, RepoCommitCommentCreatedEvent, RepoCommitStatusCreatedEvent, RepoCommitStatusUpdatedEvent, IssueCreatedEvent, IssueUpdatedEvent, IssueCommentCreatedEvent, PullRequestCreatedEvent, PullRequestUpdatedEvent, PullRequestApprovedEvent, PullRequestApprovalRemovedEvent, PullRequestMergedEvent, PullRequestDeclinedEvent, PullRequestCommentCreatedEvent, PullRequestCommentUpdatedEvent, PullRequestCommentDeletedEvent)
hook.RegisterEvents(
HandlePayload,
RepoPushEvent,
RepoForkEvent,
RepoUpdatedEvent,
RepoCommitCommentCreatedEvent,
RepoCommitStatusCreatedEvent,
RepoCommitStatusUpdatedEvent,
IssueCreatedEvent,
IssueUpdatedEvent,
IssueCommentCreatedEvent,
PullRequestCreatedEvent,
PullRequestUpdatedEvent,
PullRequestApprovedEvent,
PullRequestUnapprovedEvent,
PullRequestMergedEvent,
PullRequestDeclinedEvent,
PullRequestCommentCreatedEvent,
PullRequestCommentUpdatedEvent,
PullRequestCommentDeletedEvent,
)
go webhooks.Run(hook, "127.0.0.1:"+strconv.Itoa(port), path)
time.Sleep(5000)
time.Sleep(time.Millisecond * 500)
os.Exit(m.Run())
@@ -56,7 +76,7 @@ func TestProvider(t *testing.T) {
func TestUUIDMissingEvent(t *testing.T) {
payload := "{}"
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Event-Key", "noneexistant_event")
@@ -74,7 +94,7 @@ func TestUUIDMissingEvent(t *testing.T) {
func TestUUIDDoesNotMatchEvent(t *testing.T) {
payload := "{}"
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "THIS_DOES_NOT_MATCH")
@@ -92,7 +112,7 @@ func TestUUIDDoesNotMatchEvent(t *testing.T) {
func TestBadNoEventHeader(t *testing.T) {
payload := "{}"
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
@@ -110,7 +130,7 @@ func TestBadNoEventHeader(t *testing.T) {
func TestUnsubscribedEvent(t *testing.T) {
payload := "{}"
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "noneexistant_event")
@@ -129,7 +149,7 @@ func TestUnsubscribedEvent(t *testing.T) {
func TestBadBody(t *testing.T) {
payload := ""
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "repo:push")
@@ -355,7 +375,7 @@ func TestRepoPush(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "repo:push")
@@ -429,7 +449,7 @@ func TestRepoFork(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "repo:fork")
@@ -445,6 +465,142 @@ func TestRepoFork(t *testing.T) {
Equal(t, resp.StatusCode, http.StatusOK)
}
func TestRepoUpdated(t *testing.T) {
payload := `{
"actor": {
"type": "user",
"username": "emmap1",
"display_name": "Emma",
"uuid": "{a54f16da-24e9-4d7f-a3a7-b1ba2cd98aa3}",
"links": {
"self": {
"href": "https://api.bitbucket.org/api/2.0/users/emmap1"
},
"html": {
"href": "https://api.bitbucket.org/emmap1"
},
"avatar": {
"href": "https://bitbucket-api-assetroot.s3.amazonaws.com/c/photos/2015/Feb/26/3613917261-0-emmap1-avatar_avatar.png"
}
}
},
"repository": {
"type": "repository",
"links": {
"self": {
"href": "https://api.bitbucket.org/api/2.0/repositories/bitbucket/bitbucket"
},
"html": {
"href": "https://api.bitbucket.org/bitbucket/bitbucket"
},
"avatar": {
"href": "https://api-staging-assetroot.s3.amazonaws.com/c/photos/2014/Aug/01/bitbucket-logo-2629490769-3_avatar.png"
}
},
"uuid": "{673a6070-3421-46c9-9d48-90745f7bfe8e}",
"project": {
"type": "project",
"project": "Untitled project",
"uuid": "{3b7898dc-6891-4225-ae60-24613bb83080}",
"links": {
"html": {
"href": "https://bitbucket.org/account/user/teamawesome/projects/proj"
},
"avatar": {
"href": "https://bitbucket.org/account/user/teamawesome/projects/proj/avatar/32"
}
},
"key": "proj"
},
"full_name": "team_name/repo_name",
"name": "repo_name",
"website": "https://mywebsite.com/",
"owner": {
"type": "user",
"username": "emmap1",
"display_name": "Emma",
"uuid": "{a54f16da-24e9-4d7f-a3a7-b1ba2cd98aa3}",
"links": {
"self": {
"href": "https://api.bitbucket.org/api/2.0/users/emmap1"
},
"html": {
"href": "https://api.bitbucket.org/emmap1"
},
"avatar": {
"href": "https://bitbucket-api-assetroot.s3.amazonaws.com/c/photos/2015/Feb/26/3613917261-0-emmap1-avatar_avatar.png"
}
}
},
"scm": "git",
"is_private": true
},
"changes": {
"name": {
"new": "repository",
"old": "repository_name"
},
"website": {
"new": "http://www.example.com/",
"old": ""
},
"language": {
"new": "java",
"old": ""
},
"links": {
"new": {
"avatar": {
"href": "https://bitbucket.org/teamawesome/repository/avatar/32/"
},
"self": {
"href": "https://api.bitbucket.org/2.0/repositories/teamawesome/repository"
},
"html": {
"href": "https://bitbucket.org/teamawesome/repository"
}
},
"old": {
"avatar": {
"href": "https://bitbucket.org/teamawesome/repository_name/avatar/32/"
},
"self": {
"href": "https://api.bitbucket.org/2.0/repositories/teamawesome/repository_name"
},
"html": {
"href": "https://bitbucket.org/teamawesome/repository_name"
}
}
},
"description": {
"new": "This is a better description.",
"old": "This is a description."
},
"full_name": {
"new": "teamawesome/repository",
"old": "teamawesome/repository_name"
}
}
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "repo:updated")
Equal(t, err, nil)
client := &http.Client{}
resp, err := client.Do(req)
Equal(t, err, nil)
defer resp.Body.Close()
Equal(t, resp.StatusCode, http.StatusOK)
}
func TestRepoCommitCommentCreated(t *testing.T) {
payload := `{
@@ -514,7 +670,7 @@ func TestRepoCommitCommentCreated(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "repo:commit_comment_created")
@@ -588,7 +744,7 @@ func TestRepoCommitStatusCreated(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "repo:commit_status_created")
@@ -662,7 +818,7 @@ func TestRepoCommitStatusUpdated(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "repo:commit_status_updated")
@@ -747,7 +903,7 @@ func TestIssueCreated(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "issue:created")
@@ -864,7 +1020,7 @@ func TestIssueUpdated(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "issue:updated")
@@ -975,7 +1131,7 @@ func TestIssueCommentCreated(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "issue:comment_created")
@@ -1172,7 +1328,7 @@ func TestPullRequestCreated(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "pullrequest:created")
@@ -1369,7 +1525,7 @@ func TestPullRequestUpdated(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "pullrequest:updated")
@@ -1585,7 +1741,7 @@ func TestPullRequestApproved(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "pullrequest:approved")
@@ -1801,7 +1957,7 @@ func TestPullRequestApprovalRemoved(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "pullrequest:unapproved")
@@ -1998,7 +2154,7 @@ func TestPullRequestMerged(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "pullrequest:fulfilled")
@@ -2195,7 +2351,7 @@ func TestPullRequestDeclined(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "pullrequest:rejected")
@@ -2418,7 +2574,7 @@ func TestPullRequestCommentCreated(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "pullrequest:comment_created")
@@ -2641,7 +2797,7 @@ func TestPullRequestCommentUpdated(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "pullrequest:comment_updated")
@@ -2864,7 +3020,7 @@ func TestPullRequestCommentDeleted(t *testing.T) {
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload)))
req, err := http.NewRequest("POST", "http://127.0.0.1:3009/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Hook-UUID", "MY_UUID")
req.Header.Set("X-Event-Key", "pull_request:comment_deleted")
+457 -337
View File
@@ -2,388 +2,508 @@ package bitbucket
import "time"
// PullRequestCommentDeletedPayload is the Bitbucket pull_request:comment_deleted payload
type PullRequestCommentDeletedPayload struct {
Actor User `json:"actor"`
Repository Repository `json:"repository"`
PullRequest PullRequest `json:"pullrequest"`
Comment Comment `json:"comment"`
}
// PullRequestCommentUpdatedPayload is the Bitbucket pullrequest:comment_updated payload
type PullRequestCommentUpdatedPayload struct {
Actor User `json:"actor"`
Repository Repository `json:"repository"`
PullRequest PullRequest `json:"pullrequest"`
Comment Comment `json:"comment"`
}
// PullRequestCommentCreatedPayload is the Bitbucket pullrequest:comment_created payload
type PullRequestCommentCreatedPayload struct {
Actor User `json:"actor"`
Repository Repository `json:"repository"`
PullRequest PullRequest `json:"pullrequest"`
Comment Comment `json:"comment"`
}
// PullRequestDeclinedPayload is the Bitbucket pullrequest:rejected payload
type PullRequestDeclinedPayload struct {
Actor User `json:"actor"`
PullRequest PullRequest `json:"pullrequest"`
Repository Repository `json:"repository"`
}
// PullRequestMergedPayload is the Bitbucket pullrequest:fulfilled payload
type PullRequestMergedPayload struct {
Actor User `json:"actor"`
PullRequest PullRequest `json:"pullrequest"`
Repository Repository `json:"repository"`
}
// PullRequestApprovalRemovedPayload is the Bitbucket pullrequest:unapproved payload
type PullRequestApprovalRemovedPayload struct {
Actor User `json:"actor"`
PullRequest PullRequest `json:"pullrequest"`
Repository Repository `json:"repository"`
Approval Approval `json:"approval"`
}
// PullRequestApprovedPayload is the Bitbucket pullrequest:approved payload
type PullRequestApprovedPayload struct {
Actor User `json:"actor"`
PullRequest PullRequest `json:"pullrequest"`
Repository Repository `json:"repository"`
Approval Approval `json:"approval"`
}
// PullRequestUpdatedPayload is the Bitbucket pullrequest:updated payload
type PullRequestUpdatedPayload struct {
Actor User `json:"actor"`
PullRequest PullRequest `json:"pullrequest"`
Repository Repository `json:"repository"`
}
// PullRequestCreatedPayload is the Bitbucket pullrequest:created payload
type PullRequestCreatedPayload struct {
Actor User `json:"actor"`
PullRequest PullRequest `json:"pullrequest"`
Repository Repository `json:"repository"`
}
// IssueCommentCreatedPayload is the Bitbucket issue:comment_created payload
type IssueCommentCreatedPayload struct {
Actor User `json:"actor"`
// RepoPushPayload is the Bitbucket repo:push payload
type RepoPushPayload struct {
Actor Owner `json:"actor"`
Repository Repository `json:"repository"`
Issue Issue `json:"issue"`
Comment Comment `json:"comment"`
}
// IssueUpdatedPayload is the Bitbucket issue:updated payload
type IssueUpdatedPayload struct {
Actor User `json:"actor"`
Issue Issue `json:"issue"`
Repository Repository `json:"repository"`
Comment Comment `json:"comment"`
Changes IssueChanges `json:"changes"`
}
// IssueCreatedPayload is the Bitbucket issue:created payload
type IssueCreatedPayload struct {
Actor User `json:"actor"`
Issue Issue `json:"issue"`
Repository Repository `json:"repository"`
}
// RepoCommitStatusUpdatedPayload is the Bitbucket repo:commit_status_updated payload
type RepoCommitStatusUpdatedPayload struct {
Actor User `json:"actor"`
Repository Repository `json:"repository"`
CommitStatus CommitStatus `json:"commit_status"`
}
// RepoCommitStatusCreatedPayload is the Bitbucket repo:commit_status_created payload
type RepoCommitStatusCreatedPayload struct {
Actor User `json:"actor"`
Repository Repository `json:"repository"`
CommitStatus CommitStatus `json:"commit_status"`
}
// RepoCommitCommentCreatedPayload is the Bitbucket repo:commit_comment_created payload
type RepoCommitCommentCreatedPayload struct {
Actor User `json:"actor"`
Comment Comment `json:"comment"`
Repository Repository `json:"repository"`
Commit CommitHash `json:"commit"`
Push struct {
Changes []struct {
New struct {
Type string `json:"type"`
Name string `json:"name"`
Target struct {
Type string `json:"type"`
Hash string `json:"hash"`
Author Owner `json:"author"`
Message string `json:"message"`
Date time.Time `json:"date"`
Parents []struct {
Type string `json:"type"`
Hash string `json:"hash"`
Links struct {
Self struct {
Href string `json:"href"`
} `json:"self"`
HTML struct {
Href string `json:"href"`
} `json:"html"`
} `json:"links"`
} `json:"parents"`
Links struct {
Self struct {
Href string `json:"href"`
} `json:"self"`
HTML struct {
Href string `json:"href"`
} `json:"html"`
} `json:"links"`
} `json:"target"`
Links struct {
Self struct {
Href string `json:"href"`
} `json:"self"`
Commits struct {
Href string `json:"href"`
} `json:"commits"`
HTML struct {
Href string `json:"href"`
} `json:"html"`
} `json:"links"`
} `json:"new"`
Old struct {
Type string `json:"type"`
Name string `json:"name"`
Target struct {
Type string `json:"type"`
Hash string `json:"hash"`
Author Owner `json:"author"`
Message string `json:"message"`
Date time.Time `json:"date"`
Parents []struct {
Type string `json:"type"`
Hash string `json:"hash"`
Links struct {
Self struct {
Href string `json:"href"`
} `json:"self"`
HTML struct {
Href string `json:"href"`
} `json:"html"`
} `json:"links"`
} `json:"parents"`
Links struct {
Self struct {
Href string `json:"href"`
} `json:"self"`
HTML struct {
Href string `json:"href"`
} `json:"html"`
} `json:"links"`
} `json:"target"`
Links struct {
Self struct {
Href string `json:"href"`
} `json:"self"`
Commits struct {
Href string `json:"href"`
} `json:"commits"`
HTML struct {
Href string `json:"href"`
} `json:"html"`
} `json:"links"`
} `json:"old"`
Links struct {
HTML struct {
Href string `json:"href"`
} `json:"html"`
Diff struct {
Href string `json:"href"`
} `json:"diff"`
Commits struct {
Href string `json:"href"`
} `json:"commits"`
} `json:"links"`
Created bool `json:"created"`
Forced bool `json:"forced"`
Closed bool `json:"closed"`
Commits []struct {
Hash string `json:"hash"`
Type string `json:"type"`
Message string `json:"message"`
Author Owner `json:"author"`
Links struct {
Self struct {
Href string `json:"href"`
} `json:"self"`
HTML struct {
Href string `json:"href"`
} `json:"html"`
} `json:"links"`
} `json:"commits"`
Truncated bool `json:"truncated"`
} `json:"changes"`
} `json:"push"`
}
// RepoForkPayload is the Bitbucket repo:fork payload
type RepoForkPayload struct {
Actor User `json:"actor"`
Actor Owner `json:"actor"`
Repository Repository `json:"repository"`
Fork Repository `json:"fork"`
}
// RepoPushPayload is the Bitbucket repo:push payload
type RepoPushPayload struct {
Actor User `json:"actor"`
// RepoUpdatedPayload is the Bitbucket repo:updated payload
type RepoUpdatedPayload struct {
Actor Owner `json:"actor"`
Repository Repository `json:"repository"`
Push Push `json:"push"`
Changes struct {
Name struct {
New string `json:"new"`
Old string `json:"old"`
} `json:"name"`
Website struct {
New string `json:"new"`
Old string `json:"old"`
} `json:"website"`
Language struct {
New string `json:"new"`
Old string `json:"old"`
} `json:"language"`
Links struct {
New struct {
Avatar struct {
Href string `json:"href"`
} `json:"avatar"`
Self struct {
Href string `json:"href"`
} `json:"self"`
HTML struct {
Href string `json:"href"`
} `json:"html"`
} `json:"new"`
Old struct {
Avatar struct {
Href string `json:"href"`
} `json:"avatar"`
Self struct {
Href string `json:"href"`
} `json:"self"`
HTML struct {
Href string `json:"href"`
} `json:"html"`
} `json:"old"`
} `json:"links"`
Description struct {
New string `json:"new"`
Old string `json:"old"`
} `json:"description"`
FullName struct {
New string `json:"new"`
Old string `json:"old"`
} `json:"full_name"`
} `json:"changes"`
}
// Approval is the common Bitbucket Issue Approval Sub Entity
type Approval struct {
Date time.Time `json:"date"`
User User `json:"user"`
// RepoCommitCommentCreatedPayload is the Bitbucket repo:commit_comment_created payload
type RepoCommitCommentCreatedPayload struct {
Actor Owner `json:"actor"`
Comment Comment `json:"comment"`
Repository Repository `json:"repository"`
Commit struct {
Hash string `json:"hash"`
} `json:"commit"`
}
// IssueChanges is the common Bitbucket Issue Changes Sub Entity
type IssueChanges struct {
Status IssueChangeStatus `json:"status"`
// RepoCommitStatusCreatedPayload is the Bitbucket repo:commit_status_created payload
type RepoCommitStatusCreatedPayload struct {
Actor Owner `json:"actor"`
Repository Repository `json:"repository"`
CommitStatus struct {
Name string `json:"name"`
Description string `json:"description"`
State string `json:"state"`
Key string `json:"key"`
URL string `json:"url"`
Type string `json:"type"`
CreatedOn time.Time `json:"created_on"`
UpdatedOn time.Time `json:"updated_on"`
Links struct {
Commit struct {
Href string `json:"href"`
} `json:"commit"`
Self struct {
Href string `json:"href"`
} `json:"self"`
} `json:"links"`
} `json:"commit_status"`
}
// IssueChangeStatus is the common Bitbucket Issue Change Status Sub Entity
type IssueChangeStatus struct {
Old string `json:"old"`
New string `json:"new"`
// RepoCommitStatusUpdatedPayload is the Bitbucket repo:commit_status_updated payload
type RepoCommitStatusUpdatedPayload struct {
Actor Owner `json:"actor"`
Repository Repository `json:"repository"`
CommitStatus struct {
Name string `json:"name"`
Description string `json:"description"`
State string `json:"state"`
Key string `json:"key"`
URL string `json:"url"`
Type string `json:"type"`
CreatedOn time.Time `json:"created_on"`
UpdatedOn time.Time `json:"updated_on"`
Links struct {
Commit struct {
Href string `json:"href"`
} `json:"commit"`
Self struct {
Href string `json:"href"`
} `json:"self"`
} `json:"links"`
} `json:"commit_status"`
}
// CommitStatus is the common Bitbucket CommitStatus Sub Entity
type CommitStatus struct {
Name string `json:"name"`
Description string `json:"description"`
State string `json:"state"`
Key string `json:"key"`
URL string `json:"url"`
Type string `json:"type"`
CreatedOn time.Time `json:"created_on"`
UpdatedOn time.Time `json:"updated_on"`
Links LinksSelfCommit `json:"links"`
// IssueCreatedPayload is the Bitbucket issue:created payload
type IssueCreatedPayload struct {
Actor Owner `json:"actor"`
Issue Issue `json:"issue"`
Repository Repository `json:"repository"`
}
// Push is the common Bitbucket Push Sub Entity
type Push struct {
Changes []Change `json:"changes"`
// IssueUpdatedPayload is the Bitbucket issue:updated payload
type IssueUpdatedPayload struct {
Actor Owner `json:"actor"`
Issue Issue `json:"issue"`
Repository Repository `json:"repository"`
Comment Comment `json:"comment"`
Changes struct {
Status struct {
Old string `json:"old"`
New string `json:"new"`
} `json:"status"`
} `json:"changes"`
}
// Change is the common Bitbucket Change Sub Entity
type Change struct {
New ChangeData `json:"new"`
Old ChangeData `json:"old"`
Links LinksHTMLDiffCommits `json:"links"`
Created bool `json:"created"`
Forced bool `json:"forced"`
Closed bool `json:"closed"`
Commits []Commit `json:"commits"`
Truncated bool `json:"truncated"`
// IssueCommentCreatedPayload is the Bitbucket pullrequest:created payload
type IssueCommentCreatedPayload struct {
Actor Owner `json:"actor"`
Repository Repository `json:"repository"`
Issue Issue `json:"issue"`
Comment Comment `json:"comment"`
}
// ChangeData is the common Bitbucket ChangeData Sub Entity
type ChangeData struct {
Type string `json:"type"`
Name string `json:"name"`
Target Target `json:"target"`
Links LinksHTMLSelfCommits `json:"links"`
// PullRequestCreatedPayload is the Bitbucket pullrequest:created payload
type PullRequestCreatedPayload struct {
Actor Owner `json:"actor"`
PullRequest PullRequest `json:"pullrequest"`
Repository Repository `json:"repository"`
}
// Target is the common Bitbucket Target Sub Entity
type Target struct {
Type string `json:"type"`
Hash string `json:"hash"`
Author User `json:"author"`
Message string `json:"message"`
Date time.Time `json:"date"`
Parents []Parent `json:"parents"`
Links LinksHTMLSelf `json:"links"`
// PullRequestUpdatedPayload is the Bitbucket pullrequest:updated payload
type PullRequestUpdatedPayload struct {
Actor Owner `json:"actor"`
PullRequest PullRequest `json:"pullrequest"`
Repository Repository `json:"repository"`
}
// Parent is the common Bitbucket Parent Sub Entity
type Parent struct {
Type string `json:"type"`
Hash string `json:"hash"`
Links LinksHTMLSelf `json:"links"`
// PullRequestApprovedPayload is the Bitbucket pullrequest:approved payload
type PullRequestApprovedPayload struct {
Actor Owner `json:"actor"`
PullRequest PullRequest `json:"pullrequest"`
Repository Repository `json:"repository"`
Approval struct {
Date time.Time `json:"date"`
User Owner `json:"user"`
} `json:"approval"`
}
// Commit is the common Bitbucket Commit Sub Entity
type Commit struct {
Hash string `json:"hash"`
Type string `json:"type"`
Message string `json:"message"`
Author User `json:"author"`
Links LinksHTMLSelf `json:"links"`
// PullRequestUnapprovedPayload is the Bitbucket pullrequest:unapproved payload
type PullRequestUnapprovedPayload struct {
Actor Owner `json:"actor"`
PullRequest PullRequest `json:"pullrequest"`
Repository Repository `json:"repository"`
Approval struct {
Date time.Time `json:"date"`
User Owner `json:"user"`
} `json:"approval"`
}
// User is the common Bitbucket User Entity
type User struct {
// PullRequestMergedPayload is the Bitbucket pullrequest:fulfilled payload
type PullRequestMergedPayload struct {
Actor Owner `json:"actor"`
PullRequest PullRequest `json:"pullrequest"`
Repository Repository `json:"repository"`
}
// PullRequestDeclinedPayload is the Bitbucket pullrequest:rejected payload
type PullRequestDeclinedPayload struct {
Actor Owner `json:"actor"`
PullRequest PullRequest `json:"pullrequest"`
Repository Repository `json:"repository"`
}
// PullRequestCommentCreatedPayload is the Bitbucket pullrequest:comment_updated payload
type PullRequestCommentCreatedPayload struct {
Actor Owner `json:"actor"`
Repository Repository `json:"repository"`
PullRequest PullRequest `json:"pullrequest"`
Comment Comment `json:"comment"`
}
// PullRequestCommentUpdatedPayload is the Bitbucket pullrequest:comment_created payload
type PullRequestCommentUpdatedPayload struct {
Actor Owner `json:"actor"`
Repository Repository `json:"repository"`
PullRequest PullRequest `json:"pullrequest"`
Comment Comment `json:"comment"`
}
// PullRequestCommentDeletedPayload is the Bitbucket pullrequest:comment_deleted payload
type PullRequestCommentDeletedPayload struct {
Actor Owner `json:"actor"`
Repository Repository `json:"repository"`
PullRequest PullRequest `json:"pullrequest"`
Comment Comment `json:"comment"`
}
// Owner is the common Bitbucket Owner Sub Entity
type Owner struct {
Type string `json:"type"`
Username string `json:"username"`
DisplayName string `json:"display_name"`
UUID string `json:"uuid"`
Links Links `json:"links"`
Links struct {
Self struct {
Href string `json:"href"`
} `json:"self"`
HTML struct {
Href string `json:"href"`
} `json:"html"`
Avatar struct {
Href string `json:"href"`
} `json:"avatar"`
} `json:"links"`
}
// Repository is the common Bitbucket Repository Entity
// Repository is the common Bitbucket Repository Sub Entity
type Repository struct {
Links Links `json:"links"`
UUID string `json:"uuid"`
FullName string `json:"full_name"`
Name string `json:"name"`
Scm string `json:"scm"`
IsPrivate bool `json:"is_private"`
Type string `json:"type"`
Links struct {
Self struct {
Href string `json:"href"`
} `json:"self"`
HTML struct {
Href string `json:"href"`
} `json:"html"`
Avatar struct {
Href string `json:"href"`
} `json:"avatar"`
} `json:"links"`
UUID string `json:"uuid"`
Project Project `json:"project"`
FullName string `json:"full_name"`
Name string `json:"name"`
Website string `json:"website"`
Owner Owner `json:"owner"`
Scm string `json:"scm"`
IsPrivate bool `json:"is_private"`
}
// Issue is the common Bitbucket Issue Entity
// Project is the common Bitbucket Project Sub Entity
type Project struct {
Type string `json:"type"`
Project string `json:"project"`
UUID string `json:"uuid"`
Links struct {
HTML struct {
Href string `json:"href"`
} `json:"html"`
Avatar struct {
Href string `json:"href"`
} `json:"avatar"`
} `json:"links"`
Key string `json:"key"`
}
// Issue is the common Bitbucket Issue Sub Entity
type Issue struct {
ID int64 `json:"id"`
Component string `json:"component"`
Title string `json:"title"`
Content Content `json:"content"`
Priority string `json:"priority"`
State string `json:"state"`
Type string `json:"type"`
Milestone Milestone `json:"milestone"`
Version Version `json:"version"`
CreatedOn time.Time `json:"created_on"`
UpdatedOn time.Time `json:"updated_on"`
Links LinksHTMLSelf `json:"links"`
ID int64 `json:"id"`
Component string `json:"component"`
Title string `json:"title"`
Content struct {
Raw string `json:"raw"`
HTML string `json:"html"`
Markup string `json:"markup"`
} `json:"content"`
Priority string `json:"priority"`
State string `json:"state"`
Type string `json:"type"`
Milestone struct {
Name string `json:"name"`
} `json:"milestone"`
Version struct {
Name string `json:"name"`
} `json:"version"`
CreatedOn time.Time `json:"created_on"`
UpdatedOn time.Time `json:"updated_on"`
Links struct {
Self struct {
Href string `json:"href"`
} `json:"self"`
HTML struct {
Href string `json:"href"`
} `json:"html"`
} `json:"links"`
}
// Comment is the common Bitbucket Comment Entity
// Comment is the common Bitbucket Comment Sub Entity
type Comment struct {
ID int64 `json:"id"`
Parent ParentID `json:"parent"`
Content Content `json:"content"`
Inline Inline `json:"inline"`
CreatedOn time.Time `json:"created_on"`
UpdatedOn time.Time `json:"updated_on"`
Links LinksHTMLSelf `json:"links"`
ID int64 `json:"id"`
Parent struct {
ID int64 `json:"id"`
} `json:"parent"`
Content struct {
Raw string `json:"raw"`
HTML string `json:"html"`
Markup string `json:"markup"`
} `json:"content"`
Inline struct {
Path string `json:"path"`
From *int64 `json:"from"`
To int64 `json:"to"`
} `json:"inline"`
CreatedOn time.Time `json:"created_on"`
UpdatedOn time.Time `json:"updated_on"`
Links struct {
Self struct {
Href string `json:"href"`
} `json:"self"`
HTML struct {
Href string `json:"href"`
} `json:"html"`
} `json:"links"`
}
// PullRequest is the common Bitbucket PullRequest Entity
// PullRequest is the common Bitbucket Pull Request Sub Entity
type PullRequest struct {
ID int64 `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
State string `json:"state"`
Author User `json:"author"`
Source Source `json:"source"`
Destination Destination `json:"destination"`
MergeCommit CommitHash `json:"merge_commit"`
Participants []User `json:"participants"`
Reviewers []User `json:"reviewers"`
CloseSourceBranch bool `json:"close_source_branch"`
ClosedBy User `json:"closed_by"`
Reason string `json:"reason"`
CreatedOn time.Time `json:"created_on"`
UpdatedOn time.Time `json:"updated_on"`
Links LinksHTMLSelf `json:"links"`
}
// Destination is the common Bitbucket Destination Sub Entity
type Destination struct {
Branch Branch `json:"branch"`
Commit CommitHash `json:"commit"`
Repository Repository `json:"repository"`
}
// Source is the common Bitbucket Source Sub Entity
type Source struct {
Branch Branch `json:"branch"`
Commit CommitHash `json:"commit"`
Repository Repository `json:"repository"`
}
// Branch is the common Bitbucket Branch Sub Entity
type Branch struct {
Name string `json:"name"`
}
// CommitHash is the common Bitbucket CommitHash Sub Entity
type CommitHash struct {
Hash string `json:"hash"`
}
// Inline is the common Bitbucket Inline Sub Entity
type Inline struct {
Path string `json:"path"`
From *int64 `json:"from"`
To int64 `json:"to"`
}
// ParentID is the common Bitbucket ParentID Sub Entity
type ParentID struct {
ID int64 `json:"id"`
}
// Avatar is the common Bitbucket Avatar Sub Entity
type Avatar struct {
HREF string `json:"href"`
}
// HTML is the common Bitbucket HTML Sub Entity
type HTML struct {
HREF string `json:"href"`
}
// Self is the common Bitbucket Self Sub Entity
type Self struct {
HREF string `json:"href"`
}
// Diff is the common Bitbucket Diff Sub Entity
type Diff struct {
HREF string `json:"href"`
}
// Commits is the common Bitbucket Commits Sub Entity
type Commits struct {
HREF string `json:"href"`
}
// LinksSelfCommit is the common Bitbucket LinksSelfCommit Sub Entity
type LinksSelfCommit struct {
Self Self `json:"self"`
Commit Commits `json:"commit"`
}
// LinksHTMLSelfCommits is the common Bitbucket LinksHTMLSelfCommits Sub Entity
type LinksHTMLSelfCommits struct {
Self Self `json:"self"`
Commits Commits `json:"commits"`
HTML HTML `json:"html"`
}
// LinksHTMLDiffCommits is the common Bitbucket LinksHTMLDiffCommits Sub Entity
type LinksHTMLDiffCommits struct {
HTML HTML `json:"html"`
Diff Diff `json:"diff"`
Commits Commits `json:"commits"`
}
// Links is the common Bitbucket Links Sub Entity
type Links struct {
Avatar Avatar `json:"avatar"`
HTML HTML `json:"html"`
Self Self `json:"self"`
}
// LinksHTMLSelf is the common Bitbucket LinksHTMLSelf Sub Entity
type LinksHTMLSelf struct {
HTML HTML `json:"html"`
Self Self `json:"self"`
}
// Content is the common Bitbucket Content Sub Entity
type Content struct {
HTML string `json:"html"`
Markup string `json:"markup"`
Raw string `json:"raw"`
}
// Milestone is the common Bitbucket Milestone Sub Entity
type Milestone struct {
Name string `json:"name"`
}
// Version is the common Bitbucket Version Sub Entity
type Version struct {
Name string `json:"name"`
ID int64 `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
State string `json:"state"`
Author Owner `json:"author"`
Source struct {
Branch struct {
Name string `json:"name"`
} `json:"branch"`
Commit struct {
Hash string `json:"hash"`
} `json:"commit"`
Repository Repository `json:"repository"`
} `json:"source"`
Destination struct {
Branch struct {
Name string `json:"name"`
} `json:"branch"`
Commit struct {
Hash string `json:"hash"`
} `json:"commit"`
Repository Repository `json:"repository"`
} `json:"destination"`
MergeCommit struct {
Hash string `json:"hash"`
} `json:"merge_commit"`
Participants []Owner `json:"participants"`
Reviewers []Owner `json:"reviewers"`
CloseSourceBranch bool `json:"close_source_branch"`
ClosedBy Owner `json:"closed_by"`
Reason string `json:"reason"`
CreatedOn time.Time `json:"created_on"`
UpdatedOn time.Time `json:"updated_on"`
Links struct {
Self struct {
Href string `json:"href"`
} `json:"self"`
HTML struct {
Href string `json:"href"`
} `json:"html"`
} `json:"links"`
}
+67
View File
@@ -0,0 +1,67 @@
package main
import (
"fmt"
"log"
"strconv"
"gopkg.in/go-playground/webhooks.v4"
"gopkg.in/go-playground/webhooks.v4/github"
)
const (
path = "/webhooks"
port = 3016
)
type myLogger struct {
PrintDebugs bool
}
func (l *myLogger) Info(msg ...interface{}) {
log.Println(msg)
}
func (l *myLogger) Error(msg ...interface{}) {
log.Println(msg)
}
func (l *myLogger) Debug(msg ...interface{}) {
if !l.PrintDebugs {
return
}
log.Println(msg)
}
func main() {
// webhooks.DefaultLog=webhooks.NewLogger(true)
//
// or override with your own
webhooks.DefaultLog = &myLogger{PrintDebugs: true}
hook := github.New(&github.Config{Secret: "MyGitHubSuperSecretSecrect...?"})
hook.RegisterEvents(HandleMultiple, github.ReleaseEvent, github.PullRequestEvent) // Add as many as you want
err := webhooks.Run(hook, ":"+strconv.Itoa(port), path)
if err != nil {
fmt.Println(err)
}
}
// HandleMultiple handles multiple GitHub events
func HandleMultiple(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Payload..")
switch payload.(type) {
case github.ReleasePayload:
release := payload.(github.ReleasePayload)
// Do whatever you want from here...
fmt.Printf("%+v", release)
case github.PullRequestPayload:
pullRequest := payload.(github.PullRequestPayload)
// Do whatever you want from here...
fmt.Printf("%+v", pullRequest)
}
}
+5 -6
View File
@@ -4,8 +4,8 @@ import (
"fmt"
"strconv"
"gopkg.in/go-playground/webhooks.v1"
"gopkg.in/go-playground/webhooks.v1/github"
"gopkg.in/go-playground/webhooks.v4"
"gopkg.in/go-playground/webhooks.v4/github"
)
const (
@@ -25,14 +25,13 @@ func main() {
}
// HandleRelease handles GitHub release events
func HandleRelease(payload interface{}) {
func HandleRelease(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Release")
pl := payload.(github.ReleasePayload)
// only want to compile on full releases
if pl.Release.Draft || pl.Release.Prelelease || pl.Release.TargetCommitish != "master" {
if pl.Release.Draft || pl.Release.Prerelease || pl.Release.TargetCommitish != "master" {
return
}
@@ -41,7 +40,7 @@ func HandleRelease(payload interface{}) {
}
// HandlePullRequest handles GitHub pull_request events
func HandlePullRequest(payload interface{}) {
func HandlePullRequest(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Pull Request")
+3 -4
View File
@@ -4,8 +4,8 @@ import (
"fmt"
"strconv"
"gopkg.in/go-playground/webhooks.v1"
"gopkg.in/go-playground/webhooks.v1/github"
"gopkg.in/go-playground/webhooks.v4"
"gopkg.in/go-playground/webhooks.v4/github"
)
const (
@@ -24,8 +24,7 @@ func main() {
}
// HandleMultiple handles multiple GitHub events
func HandleMultiple(payload interface{}) {
func HandleMultiple(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Payload..")
switch payload.(type) {
+105 -37
View File
@@ -5,10 +5,11 @@ import (
"crypto/sha1"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"gopkg.in/go-playground/webhooks.v1"
"gopkg.in/go-playground/webhooks.v4"
)
// Webhook instance contains all methods needed to process events
@@ -35,18 +36,30 @@ const (
DeploymentStatusEvent Event = "deployment_status"
ForkEvent Event = "fork"
GollumEvent Event = "gollum"
InstallationEvent Event = "installation"
IntegrationInstallationEvent Event = "integration_installation"
IssueCommentEvent Event = "issue_comment"
IssuesEvent Event = "issues"
LabelEvent Event = "label"
MemberEvent Event = "member"
MembershipEvent Event = "membership"
MilestoneEvent Event = "milestone"
OrganizationEvent Event = "organization"
OrgBlockEvent Event = "org_block"
PageBuildEvent Event = "page_build"
PingEvent Event = "ping"
ProjectCardEvent Event = "project_card"
ProjectColumnEvent Event = "project_column"
ProjectEvent Event = "project"
PublicEvent Event = "public"
PullRequestReviewCommentEvent Event = "pull_request_review_comment"
PullRequestEvent Event = "pull_request"
PullRequestReviewEvent Event = "pull_request_review"
PullRequestReviewCommentEvent Event = "pull_request_review_comment"
PushEvent Event = "push"
RepositoryEvent Event = "repository"
ReleaseEvent Event = "release"
RepositoryEvent Event = "repository"
StatusEvent Event = "status"
TeamEvent Event = "team"
TeamAddEvent Event = "team_add"
WatchEvent Event = "watch"
)
@@ -87,36 +100,43 @@ func (hook Webhook) RegisterEvents(fn webhooks.ProcessPayloadFunc, events ...Eve
// 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) {
webhooks.DefaultLog.Info("Parsing Payload...")
event := r.Header.Get("X-GitHub-Event")
if len(event) == 0 {
webhooks.DefaultLog.Error("Missing X-GitHub-Event Header")
http.Error(w, "400 Bad Request - Missing X-GitHub-Event Header", http.StatusBadRequest)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("X-GitHub-Event:%s", event))
gitHubEvent := Event(event)
fn, ok := hook.eventFuncs[gitHubEvent]
// if no event registered
if !ok {
webhooks.DefaultLog.Info(fmt.Sprintf("Webhook Event %s not registered, it is recommended to setup only events in github that will be registered in the webhook to avoid unnecessary traffic and reduce potential attack vectors.", event))
return
}
payload, err := ioutil.ReadAll(r.Body)
if err != nil || len(payload) == 0 {
http.Error(w, "Error reading Body", http.StatusInternalServerError)
webhooks.DefaultLog.Error("Issue reading Payload")
http.Error(w, "Issue reading Payload", http.StatusInternalServerError)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("Payload:%s", string(payload)))
// If we have a Secret set, we should check the MAC
if len(hook.secret) > 0 {
webhooks.DefaultLog.Info("Checking secret")
signature := r.Header.Get("X-Hub-Signature")
if len(signature) == 0 {
webhooks.DefaultLog.Error("Missing X-Hub-Signature required for HMAC verification")
http.Error(w, "403 Forbidden - Missing X-Hub-Signature required for HMAC verification", http.StatusForbidden)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("X-Hub-Signature:%s", signature))
mac := hmac.New(sha1.New, []byte(hook.secret))
mac.Write(payload)
@@ -124,101 +144,149 @@ func (hook Webhook) ParsePayload(w http.ResponseWriter, r *http.Request) {
expectedMAC := hex.EncodeToString(mac.Sum(nil))
if !hmac.Equal([]byte(signature[5:]), []byte(expectedMAC)) {
webhooks.DefaultLog.Error("HMAC verification failed")
http.Error(w, "403 Forbidden - HMAC verification failed", http.StatusForbidden)
return
}
}
// Make headers available to ProcessPayloadFunc as a webhooks type
hd := webhooks.Header(r.Header)
switch gitHubEvent {
case CommitCommentEvent:
var cc CommitCommentPayload
json.Unmarshal([]byte(payload), &cc)
hook.runProcessPayloadFunc(fn, cc)
hook.runProcessPayloadFunc(fn, cc, hd)
case CreateEvent:
var c CreatePayload
json.Unmarshal([]byte(payload), &c)
hook.runProcessPayloadFunc(fn, c)
hook.runProcessPayloadFunc(fn, c, hd)
case DeleteEvent:
var d DeletePayload
json.Unmarshal([]byte(payload), &d)
hook.runProcessPayloadFunc(fn, d)
hook.runProcessPayloadFunc(fn, d, hd)
case DeploymentEvent:
var d DeploymentPayload
json.Unmarshal([]byte(payload), &d)
hook.runProcessPayloadFunc(fn, d)
hook.runProcessPayloadFunc(fn, d, hd)
case DeploymentStatusEvent:
var d DeploymentStatusPayload
json.Unmarshal([]byte(payload), &d)
hook.runProcessPayloadFunc(fn, d)
hook.runProcessPayloadFunc(fn, d, hd)
case ForkEvent:
var f ForkPayload
json.Unmarshal([]byte(payload), &f)
hook.runProcessPayloadFunc(fn, f)
hook.runProcessPayloadFunc(fn, f, hd)
case GollumEvent:
var g GollumPayload
json.Unmarshal([]byte(payload), &g)
hook.runProcessPayloadFunc(fn, g)
hook.runProcessPayloadFunc(fn, g, hd)
case InstallationEvent, IntegrationInstallationEvent:
var i InstallationPayload
json.Unmarshal([]byte(payload), &i)
hook.runProcessPayloadFunc(fn, i, hd)
case IssueCommentEvent:
var i IssueCommentPayload
json.Unmarshal([]byte(payload), &i)
hook.runProcessPayloadFunc(fn, i)
hook.runProcessPayloadFunc(fn, i, hd)
case IssuesEvent:
var i IssuesPayload
json.Unmarshal([]byte(payload), &i)
hook.runProcessPayloadFunc(fn, i)
hook.runProcessPayloadFunc(fn, i, hd)
case LabelEvent:
var l LabelPayload
json.Unmarshal([]byte(payload), &l)
hook.runProcessPayloadFunc(fn, l, hd)
case MemberEvent:
var m MemberPayload
json.Unmarshal([]byte(payload), &m)
hook.runProcessPayloadFunc(fn, m)
hook.runProcessPayloadFunc(fn, m, hd)
case MembershipEvent:
var m MembershipPayload
json.Unmarshal([]byte(payload), &m)
hook.runProcessPayloadFunc(fn, m)
hook.runProcessPayloadFunc(fn, m, hd)
case MilestoneEvent:
var m MilestonePayload
json.Unmarshal([]byte(payload), &m)
hook.runProcessPayloadFunc(fn, m, hd)
case OrganizationEvent:
var o OrganizationPayload
json.Unmarshal([]byte(payload), &o)
hook.runProcessPayloadFunc(fn, o, hd)
case OrgBlockEvent:
var o OrgBlockPayload
json.Unmarshal([]byte(payload), &o)
hook.runProcessPayloadFunc(fn, o, hd)
case PageBuildEvent:
var p PageBuildPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p)
hook.runProcessPayloadFunc(fn, p, hd)
case PingEvent:
var p PingPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p, hd)
case ProjectCardEvent:
var p ProjectCardPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p, hd)
case ProjectColumnEvent:
var p ProjectColumnPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p, hd)
case ProjectEvent:
var p ProjectPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p, hd)
case PublicEvent:
var p PublicPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p)
case PullRequestReviewCommentEvent:
var p PullRequestReviewCommentPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p)
hook.runProcessPayloadFunc(fn, p, hd)
case PullRequestEvent:
var p PullRequestPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p)
hook.runProcessPayloadFunc(fn, p, hd)
case PullRequestReviewEvent:
var p PullRequestReviewPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p, hd)
case PullRequestReviewCommentEvent:
var p PullRequestReviewCommentPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p, hd)
case PushEvent:
var p PushPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p)
case RepositoryEvent:
var r RepositoryPayload
json.Unmarshal([]byte(payload), &r)
hook.runProcessPayloadFunc(fn, r)
hook.runProcessPayloadFunc(fn, p, hd)
case ReleaseEvent:
var r ReleasePayload
json.Unmarshal([]byte(payload), &r)
hook.runProcessPayloadFunc(fn, r)
hook.runProcessPayloadFunc(fn, r, hd)
case RepositoryEvent:
var r RepositoryPayload
json.Unmarshal([]byte(payload), &r)
hook.runProcessPayloadFunc(fn, r, hd)
case StatusEvent:
var s StatusPayload
json.Unmarshal([]byte(payload), &s)
hook.runProcessPayloadFunc(fn, s)
hook.runProcessPayloadFunc(fn, s, hd)
case TeamEvent:
var t TeamPayload
json.Unmarshal([]byte(payload), &t)
hook.runProcessPayloadFunc(fn, t, hd)
case TeamAddEvent:
var t TeamAddPayload
json.Unmarshal([]byte(payload), &t)
hook.runProcessPayloadFunc(fn, t)
hook.runProcessPayloadFunc(fn, t, hd)
case WatchEvent:
var w WatchPayload
json.Unmarshal([]byte(payload), &w)
hook.runProcessPayloadFunc(fn, w)
hook.runProcessPayloadFunc(fn, w, hd)
}
}
func (hook Webhook) runProcessPayloadFunc(fn webhooks.ProcessPayloadFunc, results interface{}) {
go func(fn webhooks.ProcessPayloadFunc, results interface{}) {
fn(results)
}(fn, results)
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)
}
+2517 -733
View File
File diff suppressed because it is too large Load Diff
+5062 -661
View File
File diff suppressed because it is too large Load Diff
+157
View File
@@ -0,0 +1,157 @@
package gitlab
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"gopkg.in/go-playground/webhooks.v4"
)
// 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"
ConfidentialIssuesEvents Event = "Confidential Issue Hook"
CommentEvents Event = "Note Hook"
MergeRequestEvents 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) {
webhooks.DefaultLog.Info("Parsing Payload...")
event := r.Header.Get("X-Gitlab-Event")
if len(event) == 0 {
webhooks.DefaultLog.Error("Missing X-Gitlab-Event Header")
http.Error(w, "400 Bad Request - Missing X-Gitlab-Event Header", http.StatusBadRequest)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("X-Gitlab-Event:%s", event))
gitLabEvent := Event(event)
fn, ok := hook.eventFuncs[gitLabEvent]
// if no event registered
if !ok {
webhooks.DefaultLog.Info(fmt.Sprintf("Webhook Event %s not registered, it is recommended to setup only events in gitlab that will be registered in the webhook to avoid unnecessary traffic and reduce potential attack vectors.", event))
return
}
payload, err := ioutil.ReadAll(r.Body)
if err != nil || len(payload) == 0 {
webhooks.DefaultLog.Error("Issue reading Payload")
http.Error(w, "Error reading Payload", http.StatusInternalServerError)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("Payload:%s", string(payload)))
// If we have a Secret set, we should check the MAC
if len(hook.secret) > 0 {
webhooks.DefaultLog.Info("Checking secret")
signature := r.Header.Get("X-Gitlab-Token")
if signature != hook.secret {
webhooks.DefaultLog.Error(fmt.Sprintf("Invalid X-Gitlab-Token of '%s'", signature))
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 ConfidentialIssuesEvents:
var cie ConfidentialIssueEventPayload
json.Unmarshal([]byte(payload), &cie)
hook.runProcessPayloadFunc(fn, cie, 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 MergeRequestEvents:
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
+440
View File
@@ -0,0 +1,440 @@
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"`
Changes Changes `json:"changes"`
}
// ConfidentialIssueEventPayload contains the information for GitLab's confidential issue event
type ConfidentialIssueEventPayload struct {
// The data for confidential issues is currently the same as normal issues,
// so we can just embed the normal issue payload type here.
IssueEventPayload
}
// 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"`
Changes Changes `json:"changes"`
Project Project `json:"project"`
Repository Repository `json:"repository"`
}
// 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 int64 `json:"user_id"`
UserName string `json:"user_name"`
UserEmail string `json:"user_email"`
UserAvatar string `json:"user_avatar"`
ProjectID int64 `json:"project_id"`
Project Project `json:"Project"`
Repository Repository `json:"repository"`
Commits []Commit `json:"commits"`
TotalCommitsCount int64 `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 int64 `json:"user_id"`
UserName string `json:"user_name"`
UserAvatar string `json:"user_avatar"`
ProjectID int64 `json:"project_id"`
Project Project `json:"Project"`
Repository Repository `json:"repository"`
Commits []Commit `json:"commits"`
TotalCommitsCount int64 `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 int64 `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 int64 `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 int64 `json:"build_duration"`
BuildAllowFailure bool `json:"build_allow_failure"`
ProjectID int64 `json:"project_id"`
ProjectName string `json:"project_name"`
User User `json:"user"`
Commit BuildCommit `json:"commit"`
Repository Repository `json:"repository"`
}
// Issue contains all of the GitLab issue information
type Issue struct {
ID int64 `json:"id"`
Title string `json:"title"`
AssigneeID int64 `json:"assignee_id"`
AuthorID int64 `json:"author_id"`
ProjectID int64 `json:"project_id"`
CreatedAt customTime `json:"created_at"`
UpdatedAt customTime `json:"updated_at"`
Position int64 `json:"position"`
BranchName string `json:"branch_name"`
Description string `json:"description"`
MilestoneID int64 `json:"milestone_id"`
State string `json:"state"`
IID int64 `json:"iid"`
}
// Build contains all of the GitLab build information
type Build struct {
ID int64 `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 contains all of the GitLab artifact information
type ArtifactsFile struct {
Filename string `json:"filename"`
Size string `json:"size"`
}
// Wiki contains 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 contains 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 contains all of the GitLab build commit information
type BuildCommit struct {
ID int64 `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 int64 `json:"duration"`
StartedAt customTime `json:"started_at"`
FinishedAt customTime `json:"finished_at"`
}
// Snippet contains all of the GitLab snippet information
type Snippet struct {
ID int64 `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
AuthorID int64 `json:"author_id"`
ProjectID int64 `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 int64 `json:"visibility_level"`
}
// User contains all of the GitLab user information
type User struct {
Name string `json:"name"`
UserName string `json:"username"`
AvatarURL string `json:"avatar_url"`
}
// Project contains 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 int64 `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 contains 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 contains all of the GitLab object attributes information
type ObjectAttributes struct {
ID int64 `json:"id"`
Title string `json:"title"`
AssigneeID int64 `json:"assignee_id"`
AuthorID int64 `json:"author_id"`
ProjectID int64 `json:"project_id"`
CreatedAt customTime `json:"created_at"`
UpdatedAt customTime `json:"updated_at"`
Position int64 `json:"position"`
BranchName string `json:"branch_name"`
Description string `json:"description"`
MilestoneID int64 `json:"milestone_id"`
State string `json:"state"`
IID int64 `json:"iid"`
URL string `json:"url"`
Action string `json:"action"`
TargetBranch string `json:"target_branch"`
SourceBranch string `json:"source_branch"`
SourceProjectID int64 `json:"source_project_id"`
TargetProjectID int64 `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 int64 `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 int64 `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 contains all of the GitLab merge request information
type MergeRequest struct {
ID int64 `json:"id"`
TargetBranch string `json:"target_branch"`
SourceBranch string `json:"source_branch"`
SourceProjectID int64 `json:"source_project_id"`
AssigneeID int64 `json:"assignee_id"`
AuthorID int64 `json:"author_id"`
Title string `json:"title"`
CreatedAt customTime `json:"created_at"`
UpdatedAt customTime `json:"updated_at"`
MilestoneID int64 `json:"milestone_id"`
State string `json:"state"`
MergeStatus string `json:"merge_status"`
TargetProjectID int64 `json:"target_project_id"`
IID int64 `json:"iid"`
Description string `json:"description"`
Position int64 `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 contains all of the GitLab assignee information
type Assignee struct {
Name string `json:"name"`
Username string `json:"username"`
AvatarURL string `json:"avatar_url"`
}
// StDiff contains 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 contains 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 int64 `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 contains 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 int64 `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 contains 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 contains all of the GitLab author information
type Author struct {
Name string `json:"name"`
Email string `json:"email"`
}
// Changes contains all changes associated with a GitLab issue or MR
type Changes struct {
LabelChanges LabelChanges `json:"labels"`
}
// LabelChanges contains changes in labels assocatiated with a GitLab issue or MR
type LabelChanges struct {
Previous []Label `json:"previous"`
Current []Label `json:"current"`
}
// Label contains all of the GitLab label information
type Label struct {
Id int64 `json:"id"`
Title string `json:"title"`
Color string `json:"color"`
ProjectId int64 `json:"project_id"`
CreatedAt customTime `json:"created_at"`
UpdatedAt customTime `json:"updated_at"`
Template bool `json:"template"`
Description string `json:"description"`
Type string `json:"type"`
GroupId int64 `json:"group_id"`
}
+167
View File
@@ -0,0 +1,167 @@
package gogs
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
client "github.com/gogits/go-gogs-client"
"gopkg.in/go-playground/webhooks.v4"
)
// 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 Gogs Webhook instance
type Config struct {
Secret string
}
// Event defines a Gogs hook event type
type Event string
// Gogs hook types
const (
CreateEvent Event = "create"
DeleteEvent Event = "delete"
ForkEvent Event = "fork"
PushEvent Event = "push"
IssuesEvent Event = "issues"
IssueCommentEvent Event = "issue_comment"
PullRequestEvent Event = "pull_request"
ReleaseEvent Event = "release"
)
// New creates and returns a WebHook instance denoted by the Provider type
func New(config *Config) *Webhook {
return &Webhook{
provider: webhooks.Gogs,
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) {
webhooks.DefaultLog.Info("Parsing Payload...")
event := r.Header.Get("X-Gogs-Event")
if len(event) == 0 {
webhooks.DefaultLog.Error("Missing X-Gogs-Event Header")
http.Error(w, "400 Bad Request - Missing X-Gogs-Event Header", http.StatusBadRequest)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("X-Gogs-Event:%s", event))
gogsEvent := Event(event)
fn, ok := hook.eventFuncs[gogsEvent]
// if no event registered
if !ok {
webhooks.DefaultLog.Info(fmt.Sprintf("Webhook Event %s not registered, it is recommended to setup only events in gogs that will be registered in the webhook to avoid unnecessary traffic and reduce potential attack vectors.", event))
return
}
payload, err := ioutil.ReadAll(r.Body)
if err != nil || len(payload) == 0 {
webhooks.DefaultLog.Error("Issue reading Payload")
http.Error(w, "Issue reading Payload", http.StatusInternalServerError)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("Payload:%s", string(payload)))
// If we have a Secret set, we should check the MAC
if len(hook.secret) > 0 {
webhooks.DefaultLog.Info("Checking secret")
signature := r.Header.Get("X-Gogs-Signature")
if len(signature) == 0 {
webhooks.DefaultLog.Error("Missing X-Gogs-Signature required for HMAC verification")
http.Error(w, "403 Forbidden - Missing X-Gogs-Signature required for HMAC verification", http.StatusForbidden)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("X-Gogs-Signature:%s", signature))
mac := hmac.New(sha256.New, []byte(hook.secret))
mac.Write(payload)
expectedMAC := hex.EncodeToString(mac.Sum(nil))
if !hmac.Equal([]byte(signature), []byte(expectedMAC)) {
webhooks.DefaultLog.Debug(string(payload))
http.Error(w, "403 Forbidden - HMAC verification failed", http.StatusForbidden)
return
}
}
// Make headers available to ProcessPayloadFunc as a webhooks type
hd := webhooks.Header(r.Header)
switch gogsEvent {
case CreateEvent:
var pe client.CreatePayload
json.Unmarshal([]byte(payload), &pe)
hook.runProcessPayloadFunc(fn, pe, hd)
case ReleaseEvent:
var re client.ReleasePayload
json.Unmarshal([]byte(payload), &re)
hook.runProcessPayloadFunc(fn, re, hd)
case PushEvent:
var pe client.PushPayload
json.Unmarshal([]byte(payload), &pe)
hook.runProcessPayloadFunc(fn, pe, hd)
case DeleteEvent:
var de client.DeletePayload
json.Unmarshal([]byte(payload), &de)
hook.runProcessPayloadFunc(fn, de, hd)
case ForkEvent:
var fe client.ForkPayload
json.Unmarshal([]byte(payload), &fe)
hook.runProcessPayloadFunc(fn, fe, hd)
case IssuesEvent:
var ie client.IssuesPayload
json.Unmarshal([]byte(payload), &ie)
hook.runProcessPayloadFunc(fn, ie, hd)
case IssueCommentEvent:
var ice client.IssueCommentPayload
json.Unmarshal([]byte(payload), &ice)
hook.runProcessPayloadFunc(fn, ice, hd)
case PullRequestEvent:
var pre client.PullRequestPayload
json.Unmarshal([]byte(payload), &pre)
hook.runProcessPayloadFunc(fn, pre, 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)
}
+44
View File
@@ -0,0 +1,44 @@
package webhooks
import "log"
// DefaultLog contains the default logger for webhooks, and prints only info and error messages by default
// for debugs override DefaultLog or see NewLogger for creating one without debugs.
var DefaultLog Logger = new(logger)
// Logger allows for customizable logging
type Logger interface {
// Info prints basic information.
Info(...interface{})
// Error prints error information.
Error(...interface{})
// Debug prints information usefull for debugging.
Debug(...interface{})
}
// NewLogger returns a new logger for use.
func NewLogger(debug bool) Logger {
return &logger{PrintDebugs: debug}
}
type logger struct {
PrintDebugs bool
}
// Info prints basic information.
func (l *logger) Info(msg ...interface{}) {
log.Println("INFO:", msg)
}
// v prints error information.
func (l *logger) Error(msg ...interface{}) {
log.Println("ERROR:", msg)
}
// Debug prints information usefull for debugging.
func (l *logger) Debug(msg ...interface{}) {
if !l.PrintDebugs {
return
}
log.Println("DEBUG:", msg)
}
+48 -18
View File
@@ -1,6 +1,12 @@
package webhooks
import "net/http"
import (
"fmt"
"net/http"
)
// Header provides http.Header to minimize imports
type Header http.Header
// Provider defines the type of webhook
type Provider int
@@ -11,6 +17,10 @@ func (p Provider) String() string {
return "GitHub"
case Bitbucket:
return "Bitbucket"
case GitLab:
return "GitLab"
case Gogs:
return "Gogs"
default:
return "Unknown"
}
@@ -20,31 +30,42 @@ func (p Provider) String() string {
const (
GitHub Provider = iota
Bitbucket
GitLab
Gogs
)
// Webhook interface defines a webhook to recieve events
// Webhook interface defines a webhook to receive events
type Webhook interface {
Provider() Provider
ParsePayload(w http.ResponseWriter, r *http.Request)
}
type server struct {
hook Webhook
path string
hook Webhook
path string
includePathCheck bool
}
// ProcessPayloadFunc is a common function for payload return values
type ProcessPayloadFunc func(payload interface{})
type ProcessPayloadFunc func(payload interface{}, header Header)
// Handler returns the webhook http.Handler for use in your own Mux implementation
func Handler(hook Webhook) http.Handler {
return &server{
hook: hook,
}
}
// Run runs a server
func Run(hook Webhook, addr string, path string) error {
srv := &server{
hook: hook,
path: path,
hook: hook,
path: path,
includePathCheck: true,
}
s := &http.Server{Addr: addr, Handler: srv}
DefaultLog.Info(fmt.Sprintf("Listening on addr: %s path: %s", addr, path))
return s.ListenAndServe()
}
@@ -52,42 +73,51 @@ func Run(hook Webhook, addr string, path string) error {
func RunServer(s *http.Server, hook Webhook, path string) error {
srv := &server{
hook: hook,
path: path,
hook: hook,
path: path,
includePathCheck: true,
}
s.Handler = srv
DefaultLog.Info(fmt.Sprintf("Listening on addr: %s path: %s", s.Addr, path))
return s.ListenAndServe()
}
// RunTLSServer runs a custom server with TLS configuration.
// 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
// 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 {
srv := &server{
hook: hook,
path: path,
hook: hook,
path: path,
includePathCheck: true,
}
s.Handler = srv
DefaultLog.Info(fmt.Sprintf("Listening on addr: %s path: %s", s.Addr, path))
return s.ListenAndServeTLS("", "")
}
// ServeHTTP is the Handler for every posted WebHook Event
func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
DefaultLog.Info("Webhook received")
if r.Method != "POST" {
DefaultLog.Error(fmt.Sprintf("405 Method not allowed, attempt made using Method: %s", r.Method))
http.Error(w, "405 Method not allowed", http.StatusMethodNotAllowed)
return
}
if r.URL.Path != s.path {
http.Error(w, "404 Not found", http.StatusNotFound)
return
DefaultLog.Debug(fmt.Sprintf("Include path check: %t", s.includePathCheck))
if s.includePathCheck {
if r.URL.Path != s.path {
DefaultLog.Error(fmt.Sprintf("404 Not found, POST made using path: %s, but expected %s", r.URL.Path, s.path))
http.Error(w, "404 Not found", http.StatusNotFound)
return
}
}
s.hook.ParsePayload(w, r)
+41 -1
View File
@@ -8,6 +8,8 @@ import (
"testing"
"time"
"net/http/httptest"
. "gopkg.in/go-playground/assert.v1"
)
@@ -47,6 +49,43 @@ func TestMain(m *testing.M) {
// teardown
}
func TestHandler(t *testing.T) {
mux := http.NewServeMux()
mux.Handle("/webhooks", Handler(fakeHook))
s := httptest.NewServer(Handler(fakeHook))
defer s.Close()
payload := "{}"
req, err := http.NewRequest("POST", s.URL+"/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
Equal(t, err, nil)
client := &http.Client{}
resp, err := client.Do(req)
Equal(t, err, nil)
defer resp.Body.Close()
Equal(t, resp.StatusCode, http.StatusOK)
// Test BAD METHOD
req, err = http.NewRequest("GET", s.URL+"/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
Equal(t, err, nil)
resp, err = client.Do(req)
Equal(t, err, nil)
defer resp.Body.Close()
Equal(t, resp.StatusCode, http.StatusMethodNotAllowed)
}
func TestRun(t *testing.T) {
go Run(fakeHook, "127.0.0.1:3006", "/webhooks")
@@ -97,7 +136,7 @@ func TestRun(t *testing.T) {
}
func TestRunServer(t *testing.T) {
DefaultLog = NewLogger(true)
server := &http.Server{Addr: "127.0.0.1:3007", Handler: nil}
go RunServer(server, fakeHook, "/webhooks")
time.Sleep(5000)
@@ -236,5 +275,6 @@ func TestProviderString(t *testing.T) {
Equal(t, GitHub.String(), "GitHub")
Equal(t, Bitbucket.String(), "Bitbucket")
Equal(t, GitLab.String(), "GitLab")
Equal(t, Provider(999999).String(), "Unknown")
}