Skip to content

Commit ddab5c9

Browse files
authored
Update Webhook to return response as a struct (#170)
This makes it easier for consumers of these methods to extract data easily without having to manually convert the interface into a matching struct. Also added tests to cover the webhook functionality.
1 parent cfcf42a commit ddab5c9

File tree

3 files changed

+189
-9
lines changed

3 files changed

+189
-9
lines changed

bitbucket.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ type WebhooksOptions struct {
387387
Description string `json:"description"`
388388
Url string `json:"url"`
389389
Active bool `json:"active"`
390-
Events []string `json:"events"` // EX) {'repo:push','issue:created',..} REF) https://goo.gl/VTj93b
390+
Events []string `json:"events"` // EX: {'repo:push','issue:created',..} REF: https://bit.ly/3FjRHHu
391391
}
392392

393393
type RepositoryPipelineOptions struct {

tests/webhooks_test.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package tests
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/ktrysmt/go-bitbucket"
8+
)
9+
10+
func TestWebhook(t *testing.T) {
11+
user := os.Getenv("BITBUCKET_TEST_USERNAME")
12+
pass := os.Getenv("BITBUCKET_TEST_PASSWORD")
13+
owner := os.Getenv("BITBUCKET_TEST_OWNER")
14+
repo := os.Getenv("BITBUCKET_TEST_REPOSLUG")
15+
16+
if user == "" {
17+
t.Error("BITBUCKET_TEST_USERNAME is empty.")
18+
}
19+
if pass == "" {
20+
t.Error("BITBUCKET_TEST_PASSWORD is empty.")
21+
}
22+
if owner == "" {
23+
t.Error("BITBUCKET_TEST_OWNER is empty.")
24+
}
25+
if repo == "" {
26+
t.Error("BITBUCKET_TEST_REPOSLUG is empty.")
27+
}
28+
29+
c := bitbucket.NewBasicAuth(user, pass)
30+
31+
var webhookResourceUuid string
32+
33+
t.Run("create", func(t *testing.T) {
34+
opt := &bitbucket.WebhooksOptions{
35+
Owner: owner,
36+
RepoSlug: repo,
37+
Description: "go-bb-test",
38+
Url: "https://example.com",
39+
Active: false,
40+
Events: []string{"repo:push", "issue:created"},
41+
}
42+
43+
webhook, err := c.Repositories.Webhooks.Create(opt)
44+
if err != nil {
45+
t.Error(err)
46+
}
47+
48+
if webhook == nil {
49+
t.Error("The webhook could not be created.")
50+
}
51+
52+
if webhook.Description != "go-bb-test" {
53+
t.Error("The webhook `description` attribute does not match the expected value.")
54+
}
55+
if webhook.Url != "https://example.com" {
56+
t.Error("The webhook `url` attribute does not match the expected value.")
57+
}
58+
if webhook.Active != false {
59+
t.Error("The webhook `active` attribute does not match the expected value.")
60+
}
61+
if len(webhook.Events) != 2 {
62+
t.Error("The webhook `events` attribute does not match the expected value.")
63+
}
64+
65+
webhookResourceUuid = webhook.Uuid
66+
})
67+
68+
t.Run("get", func(t *testing.T) {
69+
opt := &bitbucket.WebhooksOptions{
70+
Owner: owner,
71+
RepoSlug: repo,
72+
Uuid: webhookResourceUuid,
73+
}
74+
webhook, err := c.Repositories.Webhooks.Get(opt)
75+
if err != nil {
76+
t.Error(err)
77+
}
78+
79+
if webhook == nil {
80+
t.Error("The webhook could not be retrieved.")
81+
}
82+
83+
if webhook.Description != "go-bb-test" {
84+
t.Error("The webhook `description` attribute does not match the expected value.")
85+
}
86+
if webhook.Url != "https://example.com" {
87+
t.Error("The webhook `url` attribute does not match the expected value.")
88+
}
89+
if webhook.Active != false {
90+
t.Error("The webhook `active` attribute does not match the expected value.")
91+
}
92+
if len(webhook.Events) != 2 {
93+
t.Error("The webhook `events` attribute does not match the expected value.")
94+
}
95+
})
96+
97+
t.Run("update", func(t *testing.T) {
98+
opt := &bitbucket.WebhooksOptions{
99+
Owner: owner,
100+
RepoSlug: repo,
101+
Uuid: webhookResourceUuid,
102+
Description: "go-bb-test-new",
103+
Url: "https://new-example.com",
104+
Events: []string{"repo:push", "issue:created", "repo:fork"},
105+
}
106+
webhook, err := c.Repositories.Webhooks.Update(opt)
107+
if err != nil {
108+
t.Error(err)
109+
}
110+
111+
if webhook == nil {
112+
t.Error("The webhook could not be retrieved.")
113+
}
114+
115+
if webhook.Description != "go-bb-test-new" {
116+
t.Error("The webhook `description` attribute does not match the expected value.")
117+
}
118+
if webhook.Url != "https://new-example.com" {
119+
t.Error("The webhook `url` attribute does not match the expected value.")
120+
}
121+
if webhook.Active != false {
122+
t.Error("The webhook `active` attribute does not match the expected value.")
123+
}
124+
if len(webhook.Events) != 3 {
125+
t.Error("The webhook `events` attribute does not match the expected value.")
126+
}
127+
})
128+
129+
t.Run("delete", func(t *testing.T) {
130+
opt := &bitbucket.WebhooksOptions{
131+
Owner: owner,
132+
RepoSlug: repo,
133+
Uuid: webhookResourceUuid,
134+
}
135+
_, err := c.Repositories.Webhooks.Delete(opt)
136+
if err != nil {
137+
t.Error(err)
138+
}
139+
})
140+
}

webhooks.go

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,39 @@ import (
55
"os"
66

77
"github.com/k0kubun/pp"
8+
"github.com/mitchellh/mapstructure"
89
)
910

1011
type Webhooks struct {
1112
c *Client
1213
}
1314

15+
type Webhook struct {
16+
Owner string `json:"owner"`
17+
RepoSlug string `json:"repo_slug"`
18+
Uuid string `json:"uuid"`
19+
Description string `json:"description"`
20+
Url string `json:"url"`
21+
Active bool `json:"active"`
22+
Events []string `json:"events"` // EX: {'repo:push','issue:created',..} REF: https://bit.ly/3FjRHHu
23+
}
24+
25+
func decodeWebhook(response interface{}) (*Webhook, error) {
26+
respMap := response.(map[string]interface{})
27+
28+
if respMap["type"] == "error" {
29+
return nil, DecodeError(respMap)
30+
}
31+
32+
var webhook = new(Webhook)
33+
err := mapstructure.Decode(respMap, webhook)
34+
if err != nil {
35+
return nil, err
36+
}
37+
38+
return webhook, nil
39+
}
40+
1441
func (r *Webhooks) buildWebhooksBody(ro *WebhooksOptions) string {
1542

1643
body := map[string]interface{}{}
@@ -41,26 +68,39 @@ func (r *Webhooks) Gets(ro *WebhooksOptions) (interface{}, error) {
4168
return r.c.execute("GET", urlStr, "")
4269
}
4370

44-
func (r *Webhooks) Create(ro *WebhooksOptions) (interface{}, error) {
71+
func (r *Webhooks) Create(ro *WebhooksOptions) (*Webhook, error) {
4572
data := r.buildWebhooksBody(ro)
4673
urlStr := r.c.requestUrl("/repositories/%s/%s/hooks", ro.Owner, ro.RepoSlug)
47-
return r.c.execute("POST", urlStr, data)
74+
response, err := r.c.execute("POST", urlStr, data)
75+
if err != nil {
76+
return nil, err
77+
}
78+
79+
return decodeWebhook(response)
4880
}
4981

50-
func (r *Webhooks) Get(ro *WebhooksOptions) (interface{}, error) {
82+
func (r *Webhooks) Get(ro *WebhooksOptions) (*Webhook, error) {
5183
urlStr := r.c.requestUrl("/repositories/%s/%s/hooks/%s", ro.Owner, ro.RepoSlug, ro.Uuid)
52-
return r.c.execute("GET", urlStr, "")
84+
response, err := r.c.execute("GET", urlStr, "")
85+
if err != nil {
86+
return nil, err
87+
}
88+
89+
return decodeWebhook(response)
5390
}
5491

55-
func (r *Webhooks) Update(ro *WebhooksOptions) (interface{}, error) {
92+
func (r *Webhooks) Update(ro *WebhooksOptions) (*Webhook, error) {
5693
data := r.buildWebhooksBody(ro)
5794
urlStr := r.c.requestUrl("/repositories/%s/%s/hooks/%s", ro.Owner, ro.RepoSlug, ro.Uuid)
58-
return r.c.execute("PUT", urlStr, data)
95+
response, err := r.c.execute("PUT", urlStr, data)
96+
if err != nil {
97+
return nil, err
98+
}
99+
100+
return decodeWebhook(response)
59101
}
60102

61103
func (r *Webhooks) Delete(ro *WebhooksOptions) (interface{}, error) {
62104
urlStr := r.c.requestUrl("/repositories/%s/%s/hooks/%s", ro.Owner, ro.RepoSlug, ro.Uuid)
63105
return r.c.execute("DELETE", urlStr, "")
64106
}
65-
66-
//

0 commit comments

Comments
 (0)