From b297674e2bed1941d6a48d7b4ba6ee1dc30c4e38 Mon Sep 17 00:00:00 2001 From: joeybloggs Date: Thu, 7 Jan 2016 13:31:00 -0500 Subject: [PATCH 1/5] Add BitBucket Payload JSON -> Structs --- bitbucket/bitbucket.go | 18 ++ bitbucket/payload.go | 389 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 407 insertions(+) create mode 100644 bitbucket/bitbucket.go create mode 100644 bitbucket/payload.go diff --git a/bitbucket/bitbucket.go b/bitbucket/bitbucket.go new file mode 100644 index 0000000..1a8fd9d --- /dev/null +++ b/bitbucket/bitbucket.go @@ -0,0 +1,18 @@ +package bitbucket + +import "gopkg.in/go-playground/webhooks.v1" + +// 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 GitHubWebhook instance +type Config struct { + Secret string +} + +// Event defines a GitHub hook event type +type Event string diff --git a/bitbucket/payload.go b/bitbucket/payload.go new file mode 100644 index 0000000..e32a2ac --- /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"` +} + +// PullRequestUnapprovedPayload is the BitBucket pullrequest:unapproved payload +type PullRequestUnapprovedPayload 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"` +} + +// RepoCommitCommentedPayload is the BitBucket repo:commit_comment_created payload +type RepoCommitCommentedPayload 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"` +} From 45987456019a1dc0facb7dbd449627f951e799d0 Mon Sep 17 00:00:00 2001 From: joeybloggs Date: Thu, 7 Jan 2016 14:19:13 -0500 Subject: [PATCH 2/5] Add Bitbucket logic. --- bitbucket/bitbucket.go | 171 +++++++++++++++++++++++++++++++++++++++-- bitbucket/payload.go | 104 ++++++++++++------------- github/github.go | 2 +- webhooks.go | 1 + 4 files changed, 220 insertions(+), 58 deletions(-) diff --git a/bitbucket/bitbucket.go b/bitbucket/bitbucket.go index 1a8fd9d..36eb66b 100644 --- a/bitbucket/bitbucket.go +++ b/bitbucket/bitbucket.go @@ -1,18 +1,179 @@ package bitbucket -import "gopkg.in/go-playground/webhooks.v1" +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 - secret string + uuid string eventFuncs map[Event]webhooks.ProcessPayloadFunc } -// Config defines the configuration to create a new GitHubWebhook instance +// Config defines the configuration to create a new Bitbucket Webhook instance type Config struct { - Secret string + UUID string } -// Event defines a GitHub hook event type +// 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" + PullRequestUnapprovedEvent 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.GitHub, + 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 PullRequestUnapprovedEvent: + var pl PullRequestUnapprovedPayload + 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/payload.go b/bitbucket/payload.go index e32a2ac..6a1d3b0 100644 --- a/bitbucket/payload.go +++ b/bitbucket/payload.go @@ -2,7 +2,7 @@ package bitbucket import "time" -// PullRequestCommentDeletedPayload is the BitBucket pull_request:comment_deleted payload +// PullRequestCommentDeletedPayload is the Bitbucket pull_request:comment_deleted payload type PullRequestCommentDeletedPayload struct { Actor User `json:"actor"` Repository Repository `json:"repository"` @@ -10,7 +10,7 @@ type PullRequestCommentDeletedPayload struct { Comment Comment `json:"comment"` } -// PullRequestCommentUpdatedPayload is the BitBucket pullrequest:comment_updated payload +// PullRequestCommentUpdatedPayload is the Bitbucket pullrequest:comment_updated payload type PullRequestCommentUpdatedPayload struct { Actor User `json:"actor"` Repository Repository `json:"repository"` @@ -18,7 +18,7 @@ type PullRequestCommentUpdatedPayload struct { Comment Comment `json:"comment"` } -// PullRequestCommentCreatedPayload is the BitBucket pullrequest:comment_created payload +// PullRequestCommentCreatedPayload is the Bitbucket pullrequest:comment_created payload type PullRequestCommentCreatedPayload struct { Actor User `json:"actor"` Repository Repository `json:"repository"` @@ -26,21 +26,21 @@ type PullRequestCommentCreatedPayload struct { Comment Comment `json:"comment"` } -// PullRequestDeclinedPayload is the BitBucket pullrequest:rejected payload +// 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 +// PullRequestMergedPayload is the Bitbucket pullrequest:fulfilled payload type PullRequestMergedPayload struct { Actor User `json:"actor"` PullRequest PullRequest `json:"pullrequest"` Repository Repository `json:"repository"` } -// PullRequestUnapprovedPayload is the BitBucket pullrequest:unapproved payload +// PullRequestUnapprovedPayload is the Bitbucket pullrequest:unapproved payload type PullRequestUnapprovedPayload struct { Actor User `json:"actor"` PullRequest PullRequest `json:"pullrequest"` @@ -48,7 +48,7 @@ type PullRequestUnapprovedPayload struct { Approval Approval `json:"approval"` } -// PullRequestApprovedPayload is the BitBucket pullrequest:approved payload +// PullRequestApprovedPayload is the Bitbucket pullrequest:approved payload type PullRequestApprovedPayload struct { Actor User `json:"actor"` PullRequest PullRequest `json:"pullrequest"` @@ -56,21 +56,21 @@ type PullRequestApprovedPayload struct { Approval Approval `json:"approval"` } -// PullRequestUpdatedPayload is the BitBucket pullrequest:updated payload +// 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 +// 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 +// IssueCommentCreatedPayload is the Bitbucket issue:comment_created payload type IssueCommentCreatedPayload struct { Actor User `json:"actor"` Repository Repository `json:"repository"` @@ -78,7 +78,7 @@ type IssueCommentCreatedPayload struct { Comment Comment `json:"comment"` } -// IssueUpdatedPayload is the BitBucket issue:updated payload +// IssueUpdatedPayload is the Bitbucket issue:updated payload type IssueUpdatedPayload struct { Actor User `json:"actor"` Issue Issue `json:"issue"` @@ -87,67 +87,67 @@ type IssueUpdatedPayload struct { Changes IssueChanges `json:"changes"` } -// IssueCreatedPayload is the BitBucket issue:created payload +// 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 +// 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 +// 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"` } -// RepoCommitCommentedPayload is the BitBucket repo:commit_comment_created payload -type RepoCommitCommentedPayload struct { +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +// CommitStatus is the common Bitbucket CommitStatus Sub Entity type CommitStatus struct { Name string `json:"name"` Description string `json:"description"` @@ -160,12 +160,12 @@ type CommitStatus struct { Links LinksSelfCommit `json:"links"` } -// Push is the common BitBucket Push Sub Entity +// Push is the common Bitbucket Push Sub Entity type Push struct { Changes []Change `json:"changes"` } -// Change is the common BitBucket Change Sub Entity +// Change is the common Bitbucket Change Sub Entity type Change struct { New ChangeData `json:"new"` Old ChangeData `json:"old"` @@ -177,7 +177,7 @@ type Change struct { Truncated bool `json:"truncated"` } -// ChangeData is the common BitBucket ChangeData Sub Entity +// ChangeData is the common Bitbucket ChangeData Sub Entity type ChangeData struct { Type string `json:"type"` Name string `json:"name"` @@ -185,7 +185,7 @@ type ChangeData struct { Links LinksHTMLSelfCommits `json:"links"` } -// Target is the common BitBucket Target Sub Entity +// Target is the common Bitbucket Target Sub Entity type Target struct { Type string `json:"type"` Hash string `json:"hash"` @@ -196,14 +196,14 @@ type Target struct { Links LinksHTMLSelf `json:"links"` } -// Parent is the common BitBucket Parent Sub Entity +// 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 +// Commit is the common Bitbucket Commit Sub Entity type Commit struct { Hash string `json:"hash"` Type string `json:"type"` @@ -212,7 +212,7 @@ type Commit struct { Links LinksHTMLSelf `json:"links"` } -// User is the common BitBucket User Entity +// User is the common Bitbucket User Entity type User struct { Username string `json:"username"` DisplayName string `json:"display_name"` @@ -220,7 +220,7 @@ type User struct { Links Links `json:"links"` } -// Repository is the common BitBucket Repository Entity +// Repository is the common Bitbucket Repository Entity type Repository struct { Links Links `json:"links"` UUID string `json:"uuid"` @@ -230,7 +230,7 @@ type Repository struct { IsPrivate bool `json:"is_private"` } -// Issue is the common BitBucket Issue Entity +// Issue is the common Bitbucket Issue Entity type Issue struct { ID int64 `json:"id"` Component string `json:"component"` @@ -246,7 +246,7 @@ type Issue struct { Links LinksHTMLSelf `json:"links"` } -// Comment is the common BitBucket Comment Entity +// Comment is the common Bitbucket Comment Entity type Comment struct { ID int64 `json:"id"` Parent ParentID `json:"parent"` @@ -257,7 +257,7 @@ type Comment struct { Links LinksHTMLSelf `json:"links"` } -// PullRequest is the common BitBucket PullRequest Entity +// PullRequest is the common Bitbucket PullRequest Entity type PullRequest struct { ID int64 `json:"id"` Title string `json:"title"` @@ -277,113 +277,113 @@ type PullRequest struct { Links LinksHTMLSelf `json:"links"` } -// Destination is the common BitBucket Destination Sub Entity +// 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 +// 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 +// Branch is the common Bitbucket Branch Sub Entity type Branch struct { Name string `json:"name"` } -// CommitHash is the common BitBucket CommitHash Sub Entity +// CommitHash is the common Bitbucket CommitHash Sub Entity type CommitHash struct { Hash string `json:"hash"` } -// Inline is the common BitBucket Inline Sub Entity +// 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 +// ParentID is the common Bitbucket ParentID Sub Entity type ParentID struct { ID int64 `json:"id"` } -// Avatar is the common BitBucket Avatar Sub Entity +// Avatar is the common Bitbucket Avatar Sub Entity type Avatar struct { HREF string `json:"href"` } -// HTML is the common BitBucket HTML Sub Entity +// HTML is the common Bitbucket HTML Sub Entity type HTML struct { HREF string `json:"href"` } -// Self is the common BitBucket Self Sub Entity +// Self is the common Bitbucket Self Sub Entity type Self struct { HREF string `json:"href"` } -// Diff is the common BitBucket Diff Sub Entity +// Diff is the common Bitbucket Diff Sub Entity type Diff struct { HREF string `json:"href"` } -// Commits is the common BitBucket Commits Sub Entity +// Commits is the common Bitbucket Commits Sub Entity type Commits struct { HREF string `json:"href"` } -// LinksSelfCommit is the common BitBucket LinksSelfCommit Sub Entity +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +// Milestone is the common Bitbucket Milestone Sub Entity type Milestone struct { Name string `json:"name"` } -// Version is the common BitBucket Version Sub Entity +// 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..968eee8 100644 --- a/webhooks.go +++ b/webhooks.go @@ -17,6 +17,7 @@ func (p Provider) String() string { // webhooks available providers const ( GitHub Provider = iota + Bitbucket ) // Webhook interface defines a webhook to recieve events From b6efbd9323d092263dc51448ad26d48416c39013 Mon Sep 17 00:00:00 2001 From: joeybloggs Date: Thu, 7 Jan 2016 15:51:13 -0500 Subject: [PATCH 3/5] Add Bitbucket tests --- bitbucket/bitbucket.go | 40 +- bitbucket/bitbucket_test.go | 2881 +++++++++++++++++++++++++++++++++++ bitbucket/payload.go | 4 +- webhooks.go | 2 + webhooks_test.go | 1 + 5 files changed, 2906 insertions(+), 22 deletions(-) create mode 100644 bitbucket/bitbucket_test.go diff --git a/bitbucket/bitbucket.go b/bitbucket/bitbucket.go index 36eb66b..b43c154 100644 --- a/bitbucket/bitbucket.go +++ b/bitbucket/bitbucket.go @@ -25,29 +25,29 @@ 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" - PullRequestUnapprovedEvent 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" + 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.GitHub, + provider: webhooks.Bitbucket, uuid: config.UUID, eventFuncs: map[Event]webhooks.ProcessPayloadFunc{}, } @@ -145,8 +145,8 @@ func (hook Webhook) ParsePayload(w http.ResponseWriter, r *http.Request) { var pl PullRequestApprovedPayload json.Unmarshal([]byte(payload), &pl) hook.runProcessPayloadFunc(fn, pl) - case PullRequestUnapprovedEvent: - var pl PullRequestUnapprovedPayload + case PullRequestApprovalRemovedEvent: + var pl PullRequestApprovalRemovedPayload json.Unmarshal([]byte(payload), &pl) hook.runProcessPayloadFunc(fn, pl) case PullRequestMergedEvent: 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 index 6a1d3b0..aac6a8a 100644 --- a/bitbucket/payload.go +++ b/bitbucket/payload.go @@ -40,8 +40,8 @@ type PullRequestMergedPayload struct { Repository Repository `json:"repository"` } -// PullRequestUnapprovedPayload is the Bitbucket pullrequest:unapproved payload -type PullRequestUnapprovedPayload struct { +// PullRequestApprovalRemovedPayload is the Bitbucket pullrequest:unapproved payload +type PullRequestApprovalRemovedPayload struct { Actor User `json:"actor"` PullRequest PullRequest `json:"pullrequest"` Repository Repository `json:"repository"` diff --git a/webhooks.go b/webhooks.go index 968eee8..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" } 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") } From 19ee65a547881eaf98ba4b65fd855eda8697868c Mon Sep 17 00:00:00 2001 From: joeybloggs Date: Fri, 8 Jan 2016 14:17:21 -0500 Subject: [PATCH 4/5] Add Bitbucket to README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 044b612..c771c57 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Library 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) [![GoDoc](https://godoc.org/gopkg.in/go-playground/webhooks.v1?status.svg)](https://godoc.org/gopkg.in/go-playground/webhooks.v1) -Library webhooks allows for easy recieving and parsing of GitHub Webhook Events; more services to come i.e. BitBucket... +Library webhooks allows for easy recieving and parsing of GitHub & Bitbucket Webhook Events Features: From 6bfbae2ae33d4c4cc08178f2d5fd77c465e16596 Mon Sep 17 00:00:00 2001 From: joeybloggs Date: Thu, 18 Feb 2016 16:48:04 -0500 Subject: [PATCH 5/5] Update README --- README.md | 5 ++++- logo.png | Bin 0 -> 2419 bytes 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 logo.png diff --git a/README.md b/README.md index c771c57..0bff573 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,12 @@ Library webhooks ================ - + +![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) +[![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) +![License](https://img.shields.io/dub/l/vibe-d.svg) Library webhooks allows for easy recieving and parsing of GitHub & Bitbucket Webhook Events diff --git a/logo.png b/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1a160788dddb294f1a4de278d2363a4cb22700c9 GIT binary patch literal 2419 zcmV-(35@oMP)rqDZMo0yuLUMLNEI2JM$1Q{qq zMj;aw6A=^%1P&7&4izR12nP}+W(^GuKN<%cDMd~r5gjmEeo8PD4F_8@BQ+HX5Dg15 z6$?g6P!AR;H5CgzB_0bA9z|e=dwY8vF>08D z{dKbEElGY>U0^Cyr-FuuDMoZrS6Om36KOCJ_5AB+j*vn~OOr|=jX@YtBMZ;r^6TsD#nw$#9#SrmCwSK$A9H zi!o4#b$WXiD_=@cRhCdFA|xd9_4b6m?c?O+ugBnDpxceL+IgSF!NbFCleMa?t}95P@p~B+d;Ni&A-@DD+Y^B<% zzSxhg$~$wuBTJxUeV#~WoGD0;IaQ1%K5sx)XeBjfGeBTyV_y&GIp; z?vuXeWvAnizucX=*}>1&P>ju|w#h?+$!L+mc9gqjiMW%cupTpKbYN0FK|?b%HAXWh zj?4UpxZHoP++~}{o~*%wo4!17xE3#cFfA%sE)@8QhGhT%0CaRxPE!B`4HXF>CL9q( zH(*OGay(E$F|B(3x}#hEt8`cX{{8*?_}9I!lZbw5{`~jo=Hc4V#lE<-rJtLDasK}O z_xAMi?(N^+(8eO|+8SC!u?(S3s1_FvTz;2yA zb#_jt(@mZ0?(XjHJMWD%Hj#V6m>XmNWtm8OOyLHVZ)P6VQX+8~}m6JZ=eg8Cv4(*1iEf$e4ikH~~~^ zYlCJ12<-y;V3iVTPr(V85YU#5juiu=6#=hC$6>wO0yhBEVH8HVh8=JN zcKCP0=ow}!5?+9ze;@mkxH);gVfD0!=R$I7u zx)jNU7FRpr0Bm$OZjiq*99OT_|^dcHm% z1OP&z{HfoKovypw4%Zk_wF);`^5O1XPMysR4 zpLrSCJxSU_d!Xa&*^Zhso?{jWHvpuT1RY8ADlIE7FaPSgXYZxMZ!->Qm(p}CU*`8d zR=i;;_-@vXjqGC4%TtL#3A}`a1ZSU}`(NzM>LSe$G12ymRD40SEMFWg5G*82Fzbd4 z-~|(3KM6^6<~f5LhN_E@btgM=2!ygXS4vb8ezaJSE0OS*niq_!50N_bW_aoGL@zbK zC-mI2i*8kSBDErbtgI?Bm6g$AzA7TqYSkS7am2cf(DBwyON*1oc>urz5r7nQiHel6 z&;dlGg&n9+3B;8VX(?%{cX93OcjCxfw?Gn(dwT=G-xS=j%pOBT&8uw+-{R9@nfz$w z0pDU@#XFDs`PtE=X7|mE(v#jkUe3IInnu2E8D)qbAR`V0A1z8cZIv4qTy!)z<#wP! zeG2Dw=61?SJ@wFs2LQ>g7qjxRtF>xK1^^czUxoTJDeQJPxW32LVZ?-&J`DBdd51pQ zlYTg=x+jDNP&TC%Ck3BQ$rUSngOiHWCfR7(00~2s`ZzSyM;$@dTj?@DN6RrH#Wzf$ z66fb;f-lOC>M9}{+uinx#h2urpayPTYKCH6VBpG3MTL?t%NIx@6cw`H;~K4U$V8)X zi*v57d(sD)jAdZnYqk$mswxGb6ZsOQ;G?zHDF_V-PX#^H(}}5LCetpu zwzjq-yH7FcNYr~Qt@AKO-E9onWDI(}VQ|@M z3IaikU|L{9)dsKu07wG>e$W7+Rx}z^>zx`5xP5KL0d8Xi3A_jW6|FV|M07e`L#hkS l*uFDSD~W(oC&X9%`U3