From e1db3374b1eaf003c44d4e2597729af7ea6688cc Mon Sep 17 00:00:00 2001 From: lucasgomide Date: Mon, 23 Jul 2018 14:30:43 -0300 Subject: [PATCH 1/2] Add hook: HangoutsChat --- hook/hangouts_chat.go | 32 ++++++++++++++++++++ hook/hangouts_chat_test.go | 61 ++++++++++++++++++++++++++++++++++++++ hook/hook.go | 10 ++++++- hook/hook_test.go | 4 +++ testdata/config.yaml | 4 ++- 5 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 hook/hangouts_chat.go create mode 100644 hook/hangouts_chat_test.go diff --git a/hook/hangouts_chat.go b/hook/hangouts_chat.go new file mode 100644 index 0000000..1618980 --- /dev/null +++ b/hook/hangouts_chat.go @@ -0,0 +1,32 @@ +package hook + +import ( + "bytes" + "errors" + "net/http" + + "github.com/lucasgomide/snitch/types" +) + +type HangoutsChat struct { + WebhookUrl string +} + +func (s HangoutsChat) CallHook(deploy []types.Deploy) error { + message := `"The application *` + deploy[0].App + `* has been deployed just now by ` + deploy[0].User + ` at _` + deploy[0].ConvertTimestampToRFC822() + `_"` + + data := []byte(`{"text":` + message + `}`) + resp, err := http.Post(s.WebhookUrl, "application/json", bytes.NewReader(data)) + if err != nil { + return err + } + + if resp.StatusCode != 200 { + return errors.New(`HangoutsChat - response status code is ` + resp.Status) + } + return nil +} + +func (s HangoutsChat) ValidatesFields() error { + return nil +} diff --git a/hook/hangouts_chat_test.go b/hook/hangouts_chat_test.go new file mode 100644 index 0000000..b4e6376 --- /dev/null +++ b/hook/hangouts_chat_test.go @@ -0,0 +1,61 @@ +package hook + +import ( + "testing" + + "github.com/lucasgomide/snitch/types" + "gopkg.in/jarcoal/httpmock.v1" +) + +var hangoutWebhookUrl = "https://hangouts.chat/123" + +func TestHangoutWhenNotificatedSuccessful(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + httpmock.RegisterResponder("POST", hangoutWebhookUrl, + httpmock.NewStringResponder(200, `ok`)) + + hangout := &HangoutsChat{WebhookUrl: hangoutWebhookUrl} + var deploy []types.Deploy + deploy = append(deploy, types.Deploy{App: "app-sample"}) + + err := hangout.CallHook(deploy) + if err != nil { + t.Error(err) + } +} + +func TestHangoutWhenResponseStatusCodeIsnt200(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + httpmock.RegisterResponder("POST", hangoutWebhookUrl, + httpmock.NewStringResponder(400, `error`)) + + hangout := &HangoutsChat{WebhookUrl: hangoutWebhookUrl} + var deploy []types.Deploy + deploy = append(deploy, types.Deploy{App: "app-sample"}) + + err := hangout.CallHook(deploy) + expected := "HangoutsChat - response status code is 400" + if err == nil || err.Error() != expected { + t.Error("Expected: "+expected+", but got", err.Error()) + } +} + +func TestHangoutReturnsErrorWhenRequestFail(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + httpmock.RegisterNoResponder(nil) + + hangout := &HangoutsChat{WebhookUrl: hangoutWebhookUrl} + var deploy []types.Deploy + deploy = append(deploy, types.Deploy{App: "app-sample"}) + + err := hangout.CallHook(deploy) + if err == nil { + t.Error("The request has been failed but no error was raised") + } +} diff --git a/hook/hook.go b/hook/hook.go index f6a6f64..ea9a4dd 100644 --- a/hook/hook.go +++ b/hook/hook.go @@ -22,7 +22,7 @@ func Execute(h types.Hook, t types.Tsuru) { utils.LogError(err.Error()) } else { for hookName, conf := range config.Data() { - switch strings.Title(hookName.(string)) { + switch defineHookName(hookName.(string)) { case "Slack": h = &Slack{} case "Sentry": @@ -31,6 +31,8 @@ func Execute(h types.Hook, t types.Tsuru) { h = &Rollbar{} case "Newrelic": h = &NewRelic{} + case "Hangouts Chat": + h = &HangoutsChat{} default: continue } @@ -74,3 +76,9 @@ func executeHook(h types.Hook, deploy []types.Deploy, conf interface{}) error { return nil } + +func defineHookName(name string) string { + return strings.Title( + strings.Join(strings.Split(name, "_"), " "), + ) +} diff --git a/hook/hook_test.go b/hook/hook_test.go index b063239..5406128 100644 --- a/hook/hook_test.go +++ b/hook/hook_test.go @@ -91,6 +91,9 @@ func TestShouldExecuteHooksFromConfig(t *testing.T) { httpmock.RegisterResponder("POST", "http://dummy.sample", httpmock.NewStringResponder(200, `ok`)) + httpmock.RegisterResponder("POST", "http://hangouts.chat.sample", + httpmock.NewStringResponder(200, `ok`)) + httpmock.RegisterResponder("POST", "https://api.rollbar.com/api/1/deploy/", httpmock.NewStringResponder(200, `ok`)) @@ -116,6 +119,7 @@ func TestShouldExecuteHooksFromConfig(t *testing.T) { if msg != "" { t.Error("Expected that msg is not empty, got empty msg") + t.Error(msg) } } diff --git a/testdata/config.yaml b/testdata/config.yaml index b9914da..4a7b59c 100644 --- a/testdata/config.yaml +++ b/testdata/config.yaml @@ -1,5 +1,7 @@ slack: webhook_url: http://dummy.sample +hangouts_chat: + webhook_url: http://hangouts.chat.sample missing_hook: field: value rollbar: @@ -16,4 +18,4 @@ newrelic: host: https://api.newrelic.com application_id: "01234" api_key: 0a0b11223344 - revision: 0.0.1 \ No newline at end of file + revision: 0.0.1 From d851600a523775d0abf52c9e61bf77eed4cd74eb Mon Sep 17 00:00:00 2001 From: lucasgomide Date: Mon, 23 Jul 2018 14:33:47 -0300 Subject: [PATCH 2/2] Add HangoutsChat documentation --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index e8d8387..ef5b302 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,9 @@ Here is all avaliables hook's configurations and your descriptions. Remember tha - **api_key** The API Key to use the NewRelic REST API. You can find more [here](https://docs.newrelic.com/docs/apis/rest-api-v2/getting-started/api-keys) - **revision** The application's current revision (e.g 0.0.1r42) +- HangoutsChat + - **webhook_url** Indicates the Webhook URL to dispatch messages to HangoutsChat Room. + ## Example [Snitch App Sample](https://github.com/lucasgomide/snitch-app-example)