diff --git a/bitbucket/bitbucket.go b/bitbucket/bitbucket.go new file mode 100644 index 0000000..b43c154 --- /dev/null +++ b/bitbucket/bitbucket.go @@ -0,0 +1,179 @@ +package bitbucket + +import ( + "encoding/json" + "io/ioutil" + "net/http" + + "gopkg.in/go-playground/webhooks.v1" +) + +// Webhook instance contains all methods needed to process events +type Webhook struct { + provider webhooks.Provider + uuid string + eventFuncs map[Event]webhooks.ProcessPayloadFunc +} + +// Config defines the configuration to create a new Bitbucket Webhook instance +type Config struct { + UUID string +} + +// Event defines a Bitbucket hook event type +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" +) + +// New creates and returns a WebHook instance denoted by the Provider type +func New(config *Config) *Webhook { + return &Webhook{ + provider: webhooks.Bitbucket, + uuid: config.UUID, + 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) { + + uuid := r.Header.Get("X-Hook-UUID") + if uuid == "" { + http.Error(w, "400 Bad Request - Missing X-Hook-UUID Header", http.StatusBadRequest) + return + } + + if uuid != hook.uuid { + http.Error(w, "403 Forbidden - Missing X-Hook-UUID does not match", http.StatusForbidden) + return + } + + event := r.Header.Get("X-Event-Key") + if event == "" { + http.Error(w, "400 Bad Request - Missing X-Event-Key Header", http.StatusBadRequest) + return + } + + bitbucketEvent := Event(event) + + fn, ok := hook.eventFuncs[bitbucketEvent] + // if no event registered + if !ok { + return + } + + payload, err := ioutil.ReadAll(r.Body) + if err != nil || len(payload) == 0 { + http.Error(w, "Error reading Body", http.StatusInternalServerError) + return + } + + switch bitbucketEvent { + case RepoPushEvent: + var pl RepoPushPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case RepoForkEvent: + var pl RepoForkPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case RepoCommitCommentCreatedEvent: + var pl RepoCommitCommentCreatedPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case RepoCommitStatusCreatedEvent: + var pl RepoCommitStatusCreatedPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case RepoCommitStatusUpdatedEvent: + var pl RepoCommitStatusUpdatedPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case IssueCreatedEvent: + var pl IssueCreatedPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case IssueUpdatedEvent: + var pl IssueUpdatedPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case IssueCommentCreatedEvent: + var pl IssueCommentCreatedPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case PullRequestCreatedEvent: + var pl PullRequestCreatedPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case PullRequestUpdatedEvent: + var pl PullRequestUpdatedPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case PullRequestApprovedEvent: + var pl PullRequestApprovedPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case PullRequestApprovalRemovedEvent: + var pl PullRequestApprovalRemovedPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case PullRequestMergedEvent: + var pl PullRequestMergedPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case PullRequestDeclinedEvent: + var pl PullRequestDeclinedPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case PullRequestCommentCreatedEvent: + var pl PullRequestCommentCreatedPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case PullRequestCommentUpdatedEvent: + var pl PullRequestCommentUpdatedPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + case PullRequestCommentDeletedEvent: + var pl PullRequestCommentDeletedPayload + json.Unmarshal([]byte(payload), &pl) + hook.runProcessPayloadFunc(fn, pl) + } +} + +func (hook Webhook) runProcessPayloadFunc(fn webhooks.ProcessPayloadFunc, results interface{}) { + go func(fn webhooks.ProcessPayloadFunc, results interface{}) { + fn(results) + }(fn, results) +} diff --git a/bitbucket/bitbucket_test.go b/bitbucket/bitbucket_test.go new file mode 100644 index 0000000..602e084 --- /dev/null +++ b/bitbucket/bitbucket_test.go @@ -0,0 +1,2881 @@ +package bitbucket + +import ( + "bytes" + "net/http" + "os" + "strconv" + "testing" + "time" + + . "gopkg.in/go-playground/assert.v1" + "gopkg.in/go-playground/webhooks.v1" +) + +// NOTES: +// - Run "go test" to run tests +// - Run "gocov test | gocov report" to report on test converage by file +// - Run "gocov test | gocov annotate -" to report on all code and functions, those ,marked with "MISS" were never called +// +// or +// +// -- may be a good idea to change to output path to somewherelike /tmp +// go test -coverprofile cover.out && go tool cover -html=cover.out -o cover.html +// +// +const ( + port = 3010 + path = "/webhooks" +) + +// HandlePayload handles GitHub event(s) +func HandlePayload(payload interface{}) { + +} + +var hook *Webhook + +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) + + go webhooks.Run(hook, "127.0.0.1:"+strconv.Itoa(port), path) + time.Sleep(5000) + + os.Exit(m.Run()) + + // teardown +} + +func TestProvider(t *testing.T) { + Equal(t, hook.Provider(), webhooks.Bitbucket) +} + +func TestUUIDMissingEvent(t *testing.T) { + payload := "{}" + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload))) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("X-Event-Key", "noneexistant_event") + + 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.StatusBadRequest) +} + +func TestUUIDDoesNotMatchEvent(t *testing.T) { + payload := "{}" + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload))) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("X-Hook-UUID", "THIS_DOES_NOT_MATCH") + + 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.StatusForbidden) +} + +func TestBadNoEventHeader(t *testing.T) { + payload := "{}" + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload))) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("X-Hook-UUID", "MY_UUID") + + 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.StatusBadRequest) +} + +func TestUnsubscribedEvent(t *testing.T) { + payload := "{}" + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestBadBody(t *testing.T) { + payload := "" + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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.StatusInternalServerError) +} + +func TestRepoPush(t *testing.T) { + + payload := `{ + "actor":{ + "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":{ + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + }, + "push":{ + "changes":[ + { + "new":{ + "type":"branch", + "name":"name-of-branch", + "target":{ + "type":"commit", + "hash":"709d658dc5b6d6afcd46049c2f332ee3f515a67d", + "author":{ + "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" + } + } + }, + "message":"new commit message\n", + "date":"2015-06-09T03:34:49+00:00", + "parents":[ + { + "type":"commit", + "hash":"1e65c05c1d5171631d92438a13901ca7dae9618c", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/2.0/repositories/user_name/repo_name/commit/8cbbd65829c7ad834a97841e0defc965718036a0" + }, + "html":{ + "href":"https://bitbucket.org/user_name/repo_name/commits/8cbbd65829c7ad834a97841e0defc965718036a0" + } + } + } + ], + "links":{ + "self":{ + "href":"https://api.bitbucket.org/2.0/repositories/user_name/repo_name/commit/c4b2b7914156a878aa7c9da452a09fb50c2091f2" + }, + "html":{ + "href":"https://bitbucket.org/user_name/repo_name/commits/c4b2b7914156a878aa7c9da452a09fb50c2091f2" + } + } + }, + "links":{ + "self":{ + "href":"https://api.bitbucket.org/2.0/repositories/user_name/repo_name/refs/branches/master" + }, + "commits":{ + "href":"https://api.bitbucket.org/2.0/repositories/user_name/repo_name/commits/master" + }, + "html":{ + "href":"https://bitbucket.org/user_name/repo_name/branch/master" + } + } + }, + "old":{ + "type":"branch", + "name":"name-of-branch", + "target":{ + "type":"commit", + "hash":"1e65c05c1d5171631d92438a13901ca7dae9618c", + "author":{ + "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" + } + } + }, + "message":"old commit message\n", + "date":"2015-06-08T21:34:56+00:00", + "parents":[ + { + "type":"commit", + "hash":"e0d0c2041e09746be5ce4b55067d5a8e3098c843", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/2.0/repositories/user_name/repo_name/commit/9c4a3452da3bc4f37af5a6bb9c784246f44406f7" + }, + "html":{ + "href":"https://bitbucket.org/user_name/repo_name/commits/9c4a3452da3bc4f37af5a6bb9c784246f44406f7" + } + } + } + ], + "links":{ + "self":{ + "href":"https://api.bitbucket.org/2.0/repositories/user_name/repo_name/commit/b99ea6dad8f416e57c5ca78c1ccef590600d841b" + }, + "html":{ + "href":"https://bitbucket.org/user_name/repo_name/commits/b99ea6dad8f416e57c5ca78c1ccef590600d841b" + } + } + }, + "links":{ + "self":{ + "href":"https://api.bitbucket.org/2.0/repositories/user_name/repo_name/refs/branches/master" + }, + "commits":{ + "href":"https://api.bitbucket.org/2.0/repositories/user_name/repo_name/commits/master" + }, + "html":{ + "href":"https://bitbucket.org/user_name/repo_name/branch/master" + } + } + }, + "links":{ + "html":{ + "href":"https://bitbucket.org/user_name/repo_name/branches/compare/c4b2b7914156a878aa7c9da452a09fb50c2091f2..b99ea6dad8f416e57c5ca78c1ccef590600d841b" + }, + "diff":{ + "href":"https://api.bitbucket.org/2.0/repositories/user_name/repo_name/diff/c4b2b7914156a878aa7c9da452a09fb50c2091f2..b99ea6dad8f416e57c5ca78c1ccef590600d841b" + }, + "commits":{ + "href":"https://api.bitbucket.org/2.0/repositories/user_name/repo_name/commits?include=c4b2b7914156a878aa7c9da452a09fb50c2091f2&exclude=b99ea6dad8f416e57c5ca78c1ccef590600d841b" + } + }, + "created":false, + "forced":false, + "closed":false, + "commits":[ + { + "hash":"03f4a7270240708834de475bcf21532d6134777e", + "type":"commit", + "message":"commit message\n", + "author":{ + "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" + } + } + }, + "links":{ + "self":{ + "href":"https://api.bitbucket.org/2.0/repositories/user/repo/commit/03f4a7270240708834de475bcf21532d6134777e" + }, + "html":{ + "href":"https://bitbucket.org/user/repo/commits/03f4a7270240708834de475bcf21532d6134777e" + } + } + } + ], + "truncated":false + } + ] + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestRepoFork(t *testing.T) { + + payload := `{ + "actor":{ + "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":{ + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + }, + "fork":{ + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 := `{ + "actor":{ + "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" + } + } + }, + "comment":{ + "id":17, + "parent":{ + "id":16 + }, + "content":{ + "raw":"Comment text", + "html":"
Comment text
", + "markup":"markdown" + }, + "inline":{ + "path":"path/to/file", + "from":null, + "to":10 + }, + "created_on":"2015-04-06T16:52:29.982346+00:00", + "updated_on":"2015-04-06T16:52:29.983730+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/comments/comment_id" + }, + "html":{ + "href":"https://api.bitbucket.org/comment_id" + } + } + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + }, + "commit":{ + "hash":"d3022fc0ca3d65c7f6654eea129d6bf0cf0ee08e" + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestRepoCommitStatusCreated(t *testing.T) { + + payload := `{ + "actor":{ + "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":{ + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + }, + "commit_status":{ + "name":"Unit Tests (Python)", + "description":"Build started", + "state":"INPROGRESS", + "key":"mybuildtool", + "url":"https://my-build-tool.com/builds/MY-PROJECT/BUILD-777", + "type":"build", + "created_on":"2015-11-19T20:37:35.547563+00:00", + "updated_on":"2015-11-19T20:37:35.547563+00:00", + "links":{ + "commit":{ + "href":"http://api.bitbucket.org/2.0/repositories/tk/test/commit/9fec847784abb10b2fa567ee63b85bd238955d0e" + }, + "self":{ + "href":"http://api.bitbucket.org/2.0/repositories/tk/test/commit/9fec847784abb10b2fa567ee63b85bd238955d0e/statuses/build/mybuildtool" + } + } + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestRepoCommitStatusUpdated(t *testing.T) { + + payload := `{ + "actor":{ + "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":{ + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + }, + "commit_status":{ + "name":"Unit Tests (Python)", + "description":"All tests passed", + "state":"SUCCESSFUL", + "key":"mybuildtool", + "url":"https://my-build-tool.com/builds/MY-PROJECT/BUILD-792", + "type":"build", + "created_on":"2015-11-19T20:37:35.547563+00:00", + "updated_on":"2015-11-20T08:01:16.433108+00:00", + "links":{ + "commit":{ + "href":"http://api.bitbucket.org/2.0/repositories/tk/test/commit/9fec847784abb10b2fa567ee63b85bd238955d0e" + }, + "self":{ + "href":"http://api.bitbucket.org/2.0/repositories/tk/test/commit/9fec847784abb10b2fa567ee63b85bd238955d0e/statuses/build/mybuildtool" + } + } + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestIssueCreated(t *testing.T) { + + payload := `{ + "actor":{ + "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" + } + } + }, + "issue":{ + "id":1, + "component":"component", + "title":"Issue title", + "content":{ + "raw":"Issue description", + "html":"Issue description
", + "markup":"markdown" + }, + "priority":"trivial|minor|major|critical|blocker", + "state":"new|open|on hold|resolved|duplicate|invalid|wontfix|closed", + "type":"bug|enhancement|proposal|task", + "milestone":{ + "name":"milestone 1" + }, + "version":{ + "name":"version 1" + }, + "created_on":"2015-04-06T15:23:38.179678+00:00", + "updated_on":"2015-04-06T15:23:38.179678+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/issues/issue_id" + }, + "html":{ + "href":"https://api.bitbucket.org/issue_id" + } + } + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestIssueUpdated(t *testing.T) { + + payload := `{ + "actor":{ + "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" + } + } + }, + "issue":{ + "id":1, + "component":"component", + "title":"Issue title", + "content":{ + "raw":"Issue description", + "html":"Issue description
", + "markup":"markdown" + }, + "priority":"trivial|minor|major|critical|blocker", + "state":"new|open|on hold|resolved|duplicate|invalid|wontfix|closed", + "type":"bug|enhancement|proposal|task", + "milestone":{ + "name":"milestone 1" + }, + "version":{ + "name":"version 1" + }, + "created_on":"2015-04-06T15:23:38.179678+00:00", + "updated_on":"2015-04-06T15:23:38.179678+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/issues/issue_id" + }, + "html":{ + "href":"https://api.bitbucket.org/issue_id" + } + } + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + }, + "comment":{ + "id":17, + "parent":{ + "id":16 + }, + "content":{ + "raw":"Comment text", + "html":"Comment text
", + "markup":"markdown" + }, + "inline":{ + "path":"path/to/file", + "from":null, + "to":10 + }, + "created_on":"2015-04-06T16:52:29.982346+00:00", + "updated_on":"2015-04-06T16:52:29.983730+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/comments/comment_id" + }, + "html":{ + "href":"https://api.bitbucket.org/comment_id" + } + } + }, + "changes":{ + "status":{ + "old":"open", + "new":"on hold" + } + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestIssueCommentCreated(t *testing.T) { + + payload := `{ + "actor":{ + "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":{ + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + }, + "issue":{ + "id":1, + "component":"component", + "title":"Issue title", + "content":{ + "raw":"Issue description", + "html":"Issue description
", + "markup":"markdown" + }, + "priority":"trivial|minor|major|critical|blocker", + "state":"new|open|on hold|resolved|duplicate|invalid|wontfix|closed", + "type":"bug|enhancement|proposal|task", + "milestone":{ + "name":"milestone 1" + }, + "version":{ + "name":"version 1" + }, + "created_on":"2015-04-06T15:23:38.179678+00:00", + "updated_on":"2015-04-06T15:23:38.179678+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/issues/issue_id" + }, + "html":{ + "href":"https://api.bitbucket.org/issue_id" + } + } + }, + "comment":{ + "id":17, + "parent":{ + "id":16 + }, + "content":{ + "raw":"Comment text", + "html":"Comment text
", + "markup":"markdown" + }, + "inline":{ + "path":"path/to/file", + "from":null, + "to":10 + }, + "created_on":"2015-04-06T16:52:29.982346+00:00", + "updated_on":"2015-04-06T16:52:29.983730+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/comments/comment_id" + }, + "html":{ + "href":"https://api.bitbucket.org/comment_id" + } + } + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestPullRequestCreated(t *testing.T) { + + payload := `{ + "actor":{ + "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" + } + } + }, + "pullrequest":{ + "id":1, + "title":"Title of pull request", + "description":"Description of pull request", + "state":"OPEN|MERGED|DECLINED", + "author":{ + "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" + } + } + }, + "source":{ + "branch":{ + "name":"branch2" + }, + "commit":{ + "hash":"d3022fc0ca3d" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "destination":{ + "branch":{ + "name":"master" + }, + "commit":{ + "hash":"ce5965ddd289" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "merge_commit":{ + "hash":"764413d85e29" + }, + "participants":[ + { + "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" + } + } + } + ], + "reviewers":[ + { + "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" + } + } + } + ], + "close_source_branch":true, + "closed_by":{ + "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" + } + } + }, + "reason":"reason for declining the PR (if applicable)", + "created_on":"2015-04-06T15:23:38.179678+00:00", + "updated_on":"2015-04-06T15:23:38.205705+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/pullrequests/pullrequest_id" + }, + "html":{ + "href":"https://api.bitbucket.org/pullrequest_id" + } + } + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestPullRequestUpdated(t *testing.T) { + + payload := `{ + "actor":{ + "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" + } + } + }, + "pullrequest":{ + "id":1, + "title":"Title of pull request", + "description":"Description of pull request", + "state":"OPEN|MERGED|DECLINED", + "author":{ + "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" + } + } + }, + "source":{ + "branch":{ + "name":"branch2" + }, + "commit":{ + "hash":"d3022fc0ca3d" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "destination":{ + "branch":{ + "name":"master" + }, + "commit":{ + "hash":"ce5965ddd289" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "merge_commit":{ + "hash":"764413d85e29" + }, + "participants":[ + { + "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" + } + } + } + ], + "reviewers":[ + { + "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" + } + } + } + ], + "close_source_branch":true, + "closed_by":{ + "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" + } + } + }, + "reason":"reason for declining the PR (if applicable)", + "created_on":"2015-04-06T15:23:38.179678+00:00", + "updated_on":"2015-04-06T15:23:38.205705+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/pullrequests/pullrequest_id" + }, + "html":{ + "href":"https://api.bitbucket.org/pullrequest_id" + } + } + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestPullRequestApproved(t *testing.T) { + + payload := `{ + "actor":{ + "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" + } + } + }, + "pullrequest":{ + "id":1, + "title":"Title of pull request", + "description":"Description of pull request", + "state":"OPEN|MERGED|DECLINED", + "author":{ + "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" + } + } + }, + "source":{ + "branch":{ + "name":"branch2" + }, + "commit":{ + "hash":"d3022fc0ca3d" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "destination":{ + "branch":{ + "name":"master" + }, + "commit":{ + "hash":"ce5965ddd289" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "merge_commit":{ + "hash":"764413d85e29" + }, + "participants":[ + { + "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" + } + } + } + ], + "reviewers":[ + { + "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" + } + } + } + ], + "close_source_branch":true, + "closed_by":{ + "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" + } + } + }, + "reason":"reason for declining the PR (if applicable)", + "created_on":"2015-04-06T15:23:38.179678+00:00", + "updated_on":"2015-04-06T15:23:38.205705+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/pullrequests/pullrequest_id" + }, + "html":{ + "href":"https://api.bitbucket.org/pullrequest_id" + } + } + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + }, + "approval":{ + "date":"2015-04-06T16:34:59.195330+00:00", + "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" + } + } + } + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestPullRequestApprovalRemoved(t *testing.T) { + + payload := `{ + "actor":{ + "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" + } + } + }, + "pullrequest":{ + "id":1, + "title":"Title of pull request", + "description":"Description of pull request", + "state":"OPEN|MERGED|DECLINED", + "author":{ + "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" + } + } + }, + "source":{ + "branch":{ + "name":"branch2" + }, + "commit":{ + "hash":"d3022fc0ca3d" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "destination":{ + "branch":{ + "name":"master" + }, + "commit":{ + "hash":"ce5965ddd289" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "merge_commit":{ + "hash":"764413d85e29" + }, + "participants":[ + { + "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" + } + } + } + ], + "reviewers":[ + { + "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" + } + } + } + ], + "close_source_branch":true, + "closed_by":{ + "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" + } + } + }, + "reason":"reason for declining the PR (if applicable)", + "created_on":"2015-04-06T15:23:38.179678+00:00", + "updated_on":"2015-04-06T15:23:38.205705+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/pullrequests/pullrequest_id" + }, + "html":{ + "href":"https://api.bitbucket.org/pullrequest_id" + } + } + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + }, + "approval":{ + "date":"2015-04-06T16:34:59.195330+00:00", + "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" + } + } + } + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestPullRequestMerged(t *testing.T) { + + payload := `{ + "actor":{ + "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" + } + } + }, + "pullrequest":{ + "id":1, + "title":"Title of pull request", + "description":"Description of pull request", + "state":"OPEN|MERGED|DECLINED", + "author":{ + "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" + } + } + }, + "source":{ + "branch":{ + "name":"branch2" + }, + "commit":{ + "hash":"d3022fc0ca3d" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "destination":{ + "branch":{ + "name":"master" + }, + "commit":{ + "hash":"ce5965ddd289" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "merge_commit":{ + "hash":"764413d85e29" + }, + "participants":[ + { + "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" + } + } + } + ], + "reviewers":[ + { + "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" + } + } + } + ], + "close_source_branch":true, + "closed_by":{ + "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" + } + } + }, + "reason":"reason for declining the PR (if applicable)", + "created_on":"2015-04-06T15:23:38.179678+00:00", + "updated_on":"2015-04-06T15:23:38.205705+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/pullrequests/pullrequest_id" + }, + "html":{ + "href":"https://api.bitbucket.org/pullrequest_id" + } + } + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestPullRequestDeclined(t *testing.T) { + + payload := `{ + "actor":{ + "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" + } + } + }, + "pullrequest":{ + "id":1, + "title":"Title of pull request", + "description":"Description of pull request", + "state":"OPEN|MERGED|DECLINED", + "author":{ + "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" + } + } + }, + "source":{ + "branch":{ + "name":"branch2" + }, + "commit":{ + "hash":"d3022fc0ca3d" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "destination":{ + "branch":{ + "name":"master" + }, + "commit":{ + "hash":"ce5965ddd289" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "merge_commit":{ + "hash":"764413d85e29" + }, + "participants":[ + { + "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" + } + } + } + ], + "reviewers":[ + { + "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" + } + } + } + ], + "close_source_branch":true, + "closed_by":{ + "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" + } + } + }, + "reason":"reason for declining the PR (if applicable)", + "created_on":"2015-04-06T15:23:38.179678+00:00", + "updated_on":"2015-04-06T15:23:38.205705+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/pullrequests/pullrequest_id" + }, + "html":{ + "href":"https://api.bitbucket.org/pullrequest_id" + } + } + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestPullRequestCommentCreated(t *testing.T) { + + payload := `{ + "actor":{ + "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":{ + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + }, + "pullrequest":{ + "id":1, + "title":"Title of pull request", + "description":"Description of pull request", + "state":"OPEN|MERGED|DECLINED", + "author":{ + "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" + } + } + }, + "source":{ + "branch":{ + "name":"branch2" + }, + "commit":{ + "hash":"d3022fc0ca3d" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "destination":{ + "branch":{ + "name":"master" + }, + "commit":{ + "hash":"ce5965ddd289" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "merge_commit":{ + "hash":"764413d85e29" + }, + "participants":[ + { + "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" + } + } + } + ], + "reviewers":[ + { + "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" + } + } + } + ], + "close_source_branch":true, + "closed_by":{ + "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" + } + } + }, + "reason":"reason for declining the PR (if applicable)", + "created_on":"2015-04-06T15:23:38.179678+00:00", + "updated_on":"2015-04-06T15:23:38.205705+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/pullrequests/pullrequest_id" + }, + "html":{ + "href":"https://api.bitbucket.org/pullrequest_id" + } + } + }, + "comment":{ + "id":17, + "parent":{ + "id":16 + }, + "content":{ + "raw":"Comment text", + "html":"Comment text
", + "markup":"markdown" + }, + "inline":{ + "path":"path/to/file", + "from":null, + "to":10 + }, + "created_on":"2015-04-06T16:52:29.982346+00:00", + "updated_on":"2015-04-06T16:52:29.983730+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/comments/comment_id" + }, + "html":{ + "href":"https://api.bitbucket.org/comment_id" + } + } + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestPullRequestCommentUpdated(t *testing.T) { + + payload := `{ + "actor":{ + "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":{ + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + }, + "pullrequest":{ + "id":1, + "title":"Title of pull request", + "description":"Description of pull request", + "state":"OPEN|MERGED|DECLINED", + "author":{ + "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" + } + } + }, + "source":{ + "branch":{ + "name":"branch2" + }, + "commit":{ + "hash":"d3022fc0ca3d" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "destination":{ + "branch":{ + "name":"master" + }, + "commit":{ + "hash":"ce5965ddd289" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "merge_commit":{ + "hash":"764413d85e29" + }, + "participants":[ + { + "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" + } + } + } + ], + "reviewers":[ + { + "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" + } + } + } + ], + "close_source_branch":true, + "closed_by":{ + "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" + } + } + }, + "reason":"reason for declining the PR (if applicable)", + "created_on":"2015-04-06T15:23:38.179678+00:00", + "updated_on":"2015-04-06T15:23:38.205705+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/pullrequests/pullrequest_id" + }, + "html":{ + "href":"https://api.bitbucket.org/pullrequest_id" + } + } + }, + "comment":{ + "id":17, + "parent":{ + "id":16 + }, + "content":{ + "raw":"Comment text", + "html":"Comment text
", + "markup":"markdown" + }, + "inline":{ + "path":"path/to/file", + "from":null, + "to":10 + }, + "created_on":"2015-04-06T16:52:29.982346+00:00", + "updated_on":"2015-04-06T16:52:29.983730+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/comments/comment_id" + }, + "html":{ + "href":"https://api.bitbucket.org/comment_id" + } + } + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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 TestPullRequestCommentDeleted(t *testing.T) { + + payload := `{ + "actor":{ + "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":{ + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + }, + "pullrequest":{ + "id":1, + "title":"Title of pull request", + "description":"Description of pull request", + "state":"OPEN|MERGED|DECLINED", + "author":{ + "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" + } + } + }, + "source":{ + "branch":{ + "name":"branch2" + }, + "commit":{ + "hash":"d3022fc0ca3d" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "destination":{ + "branch":{ + "name":"master" + }, + "commit":{ + "hash":"ce5965ddd289" + }, + "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}", + "full_name":"team_name/repo_name", + "name":"repo_name", + "scm":"git", + "is_private":true + } + }, + "merge_commit":{ + "hash":"764413d85e29" + }, + "participants":[ + { + "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" + } + } + } + ], + "reviewers":[ + { + "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" + } + } + } + ], + "close_source_branch":true, + "closed_by":{ + "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" + } + } + }, + "reason":"reason for declining the PR (if applicable)", + "created_on":"2015-04-06T15:23:38.179678+00:00", + "updated_on":"2015-04-06T15:23:38.205705+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/pullrequests/pullrequest_id" + }, + "html":{ + "href":"https://api.bitbucket.org/pullrequest_id" + } + } + }, + "comment":{ + "id":17, + "parent":{ + "id":16 + }, + "content":{ + "raw":"Comment text", + "html":"Comment text
", + "markup":"markdown" + }, + "inline":{ + "path":"path/to/file", + "from":null, + "to":10 + }, + "created_on":"2015-04-06T16:52:29.982346+00:00", + "updated_on":"2015-04-06T16:52:29.983730+00:00", + "links":{ + "self":{ + "href":"https://api.bitbucket.org/api/2.0/comments/comment_id" + }, + "html":{ + "href":"https://api.bitbucket.org/comment_id" + } + } + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/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") + + 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) +} diff --git a/bitbucket/payload.go b/bitbucket/payload.go new file mode 100644 index 0000000..aac6a8a --- /dev/null +++ b/bitbucket/payload.go @@ -0,0 +1,389 @@ +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"` + 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"` +} + +// RepoForkPayload is the Bitbucket repo:fork payload +type RepoForkPayload struct { + Actor User `json:"actor"` + Repository Repository `json:"repository"` + Fork Repository `json:"fork"` +} + +// RepoPushPayload is the Bitbucket repo:push payload +type RepoPushPayload struct { + Actor User `json:"actor"` + Repository Repository `json:"repository"` + Push Push `json:"push"` +} + +// Approval is the common Bitbucket Issue Approval Sub Entity +type Approval struct { + Date time.Time `json:"date"` + User User `json:"user"` +} + +// IssueChanges is the common Bitbucket Issue Changes Sub Entity +type IssueChanges struct { + Status IssueChangeStatus `json:"status"` +} + +// IssueChangeStatus is the common Bitbucket Issue Change Status Sub Entity +type IssueChangeStatus struct { + Old string `json:"old"` + New string `json:"new"` +} + +// 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"` +} + +// Push is the common Bitbucket Push Sub Entity +type Push struct { + Changes []Change `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"` +} + +// 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"` +} + +// 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"` +} + +// Parent is the common Bitbucket Parent Sub Entity +type Parent struct { + Type string `json:"type"` + Hash string `json:"hash"` + Links LinksHTMLSelf `json:"links"` +} + +// 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"` +} + +// User is the common Bitbucket User Entity +type User struct { + Username string `json:"username"` + DisplayName string `json:"display_name"` + UUID string `json:"uuid"` + Links Links `json:"links"` +} + +// Repository is the common Bitbucket Repository 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"` +} + +// Issue is the common Bitbucket Issue 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"` +} + +// Comment is the common Bitbucket Comment 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"` +} + +// PullRequest is the common Bitbucket PullRequest 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"` +} diff --git a/github/github.go b/github/github.go index 1709473..efced88 100644 --- a/github/github.go +++ b/github/github.go @@ -18,7 +18,7 @@ type Webhook struct { eventFuncs map[Event]webhooks.ProcessPayloadFunc } -// Config defines the configuration to create a new GitHubWebhook instance +// Config defines the configuration to create a new GitHub Webhook instance type Config struct { Secret string } diff --git a/webhooks.go b/webhooks.go index d95c7c8..6dcd6f1 100644 --- a/webhooks.go +++ b/webhooks.go @@ -9,6 +9,8 @@ func (p Provider) String() string { switch p { case GitHub: return "GitHub" + case Bitbucket: + return "Bitbucket" default: return "Unknown" } @@ -17,6 +19,7 @@ func (p Provider) String() string { // webhooks available providers const ( GitHub Provider = iota + Bitbucket ) // Webhook interface defines a webhook to recieve events diff --git a/webhooks_test.go b/webhooks_test.go index 049a345..9ade530 100644 --- a/webhooks_test.go +++ b/webhooks_test.go @@ -235,5 +235,6 @@ D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g== func TestProviderString(t *testing.T) { Equal(t, GitHub.String(), "GitHub") + Equal(t, Bitbucket.String(), "Bitbucket") Equal(t, Provider(999999).String(), "Unknown") }