Skip to content

Commit

Permalink
Slack integration (#199)
Browse files Browse the repository at this point in the history
Thanks to @nicholas-wu-hs !
  • Loading branch information
lkysow authored Nov 17, 2017
1 parent cc015af commit 9dc9434
Show file tree
Hide file tree
Showing 17 changed files with 1,144 additions and 33 deletions.
2 changes: 1 addition & 1 deletion cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ var stringFlags = []stringFlag{
env: "ATLANTIS_GITLAB_TOKEN",
},
{
name: GitlabWebHookSecret,
name: GitlabWebHookSecret,
description: "Optional secret used to validate GitLab webhooks." +
" If not specified, Atlantis won't be able to validate that the incoming webhook call came from GitLab. " +
"Can also be specified via the ATLANTIS_GITLAB_WEBHOOK_SECRET environment variable.",
Expand Down
11 changes: 11 additions & 0 deletions server/events/apply_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/hootsuite/atlantis/server/events/run"
"github.com/hootsuite/atlantis/server/events/terraform"
"github.com/hootsuite/atlantis/server/events/vcs"
"github.com/hootsuite/atlantis/server/events/webhooks"
)

type ApplyExecutor struct {
Expand All @@ -21,6 +22,7 @@ type ApplyExecutor struct {
Run *run.Run
Workspace Workspace
ProjectPreExecute *ProjectPreExecute
Webhooks webhooks.Sender
}

func (a *ApplyExecutor) Execute(ctx *CommandContext) CommandResponse {
Expand Down Expand Up @@ -92,6 +94,15 @@ func (a *ApplyExecutor) apply(ctx *CommandContext, repoDir string, plan models.P
env := ctx.Command.Environment
tfApplyCmd := append(append(append([]string{"apply", "-no-color"}, applyExtraArgs...), ctx.Command.Flags...), plan.LocalPath)
output, err := a.Terraform.RunCommandWithVersion(ctx.Log, absolutePath, tfApplyCmd, terraformVersion, env)

a.Webhooks.Send(ctx.Log, webhooks.ApplyResult{ // nolint: errcheck
Workspace: env,
User: ctx.User,
Repo: ctx.BaseRepo,
Pull: ctx.Pull,
Success: err == nil,
})

if err != nil {
return ProjectResult{Error: fmt.Errorf("%s\n%s", err.Error(), output)}
}
Expand Down
2 changes: 1 addition & 1 deletion server/events/command_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func setup(t *testing.T) {
MarkdownRenderer: &events.MarkdownRenderer{},
GithubPullGetter: githubGetter,
GitlabMergeRequestGetter: gitlabGetter,
Logger: logger,
Logger: logger,
}
}

Expand Down
3 changes: 2 additions & 1 deletion server/events/mocks/mock_commit_status_updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
package mocks

import (
"reflect"

events "github.com/hootsuite/atlantis/server/events"
models "github.com/hootsuite/atlantis/server/events/models"
vcs "github.com/hootsuite/atlantis/server/events/vcs"
pegomock "github.com/petergtz/pegomock"
"reflect"
)

type MockCommitStatusUpdater struct {
Expand Down
17 changes: 8 additions & 9 deletions server/events/pull_closed_executor_test.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package events_test

import (
"errors"
"reflect"
"testing"

"github.com/hootsuite/atlantis/server/events"
lockmocks "github.com/hootsuite/atlantis/server/events/locking/mocks"
"github.com/hootsuite/atlantis/server/events/mocks"
"github.com/hootsuite/atlantis/server/events/models"
"github.com/hootsuite/atlantis/server/events/models/fixtures"
"github.com/hootsuite/atlantis/server/events/vcs"
vcsmocks "github.com/hootsuite/atlantis/server/events/vcs/mocks"
. "github.com/hootsuite/atlantis/testing"
. "github.com/petergtz/pegomock"
"testing"
"github.com/hootsuite/atlantis/server/events/mocks"
lockmocks "github.com/hootsuite/atlantis/server/events/locking/mocks"
vcsmocks "github.com/hootsuite/atlantis/server/events/vcs/mocks"
"github.com/hootsuite/atlantis/server/events"
"errors"
"github.com/hootsuite/atlantis/server/events/vcs"
"github.com/hootsuite/atlantis/server/events/models/fixtures"
)

func TestCleanUpPullWorkspaceErr(t *testing.T) {
Expand Down Expand Up @@ -155,4 +155,3 @@ func AnyPullRequest() models.PullRequest {
RegisterMatcher(NewAnyMatcher(reflect.TypeOf(models.PullRequest{})))
return models.PullRequest{}
}

81 changes: 81 additions & 0 deletions server/events/webhooks/mocks/mock_sender.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Automatically generated by pegomock. DO NOT EDIT!
// Source: github.com/hootsuite/atlantis/server/events/webhooks (interfaces: Sender)

package mocks

import (
"reflect"

webhooks "github.com/hootsuite/atlantis/server/events/webhooks"
logging "github.com/hootsuite/atlantis/server/logging"
pegomock "github.com/petergtz/pegomock"
)

type MockSender struct {
fail func(message string, callerSkip ...int)
}

func NewMockSender() *MockSender {
return &MockSender{fail: pegomock.GlobalFailHandler}
}

func (mock *MockSender) Send(log *logging.SimpleLogger, applyResult webhooks.ApplyResult) error {
params := []pegomock.Param{log, applyResult}
result := pegomock.GetGenericMockFrom(mock).Invoke("Send", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()})
var ret0 error
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(error)
}
}
return ret0
}

func (mock *MockSender) VerifyWasCalledOnce() *VerifierSender {
return &VerifierSender{mock, pegomock.Times(1), nil}
}

func (mock *MockSender) VerifyWasCalled(invocationCountMatcher pegomock.Matcher) *VerifierSender {
return &VerifierSender{mock, invocationCountMatcher, nil}
}

func (mock *MockSender) VerifyWasCalledInOrder(invocationCountMatcher pegomock.Matcher, inOrderContext *pegomock.InOrderContext) *VerifierSender {
return &VerifierSender{mock, invocationCountMatcher, inOrderContext}
}

type VerifierSender struct {
mock *MockSender
invocationCountMatcher pegomock.Matcher
inOrderContext *pegomock.InOrderContext
}

func (verifier *VerifierSender) Send(log *logging.SimpleLogger, applyResult webhooks.ApplyResult) *Sender_Send_OngoingVerification {
params := []pegomock.Param{log, applyResult}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Send", params)
return &Sender_Send_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}

type Sender_Send_OngoingVerification struct {
mock *MockSender
methodInvocations []pegomock.MethodInvocation
}

func (c *Sender_Send_OngoingVerification) GetCapturedArguments() (*logging.SimpleLogger, webhooks.ApplyResult) {
log, applyResult := c.GetAllCapturedArguments()
return log[len(log)-1], applyResult[len(applyResult)-1]
}

func (c *Sender_Send_OngoingVerification) GetAllCapturedArguments() (_param0 []*logging.SimpleLogger, _param1 []webhooks.ApplyResult) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]*logging.SimpleLogger, len(params[0]))
for u, param := range params[0] {
_param0[u] = param.(*logging.SimpleLogger)
}
_param1 = make([]webhooks.ApplyResult, len(params[1]))
for u, param := range params[1] {
_param1[u] = param.(webhooks.ApplyResult)
}
}
return
}
181 changes: 181 additions & 0 deletions server/events/webhooks/mocks/mock_slack_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// Automatically generated by pegomock. DO NOT EDIT!
// Source: github.com/hootsuite/atlantis/server/events/webhooks (interfaces: SlackClient)

package mocks

import (
"reflect"

webhooks "github.com/hootsuite/atlantis/server/events/webhooks"
pegomock "github.com/petergtz/pegomock"
)

type MockSlackClient struct {
fail func(message string, callerSkip ...int)
}

func NewMockSlackClient() *MockSlackClient {
return &MockSlackClient{fail: pegomock.GlobalFailHandler}
}

func (mock *MockSlackClient) AuthTest() error {
params := []pegomock.Param{}
result := pegomock.GetGenericMockFrom(mock).Invoke("AuthTest", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()})
var ret0 error
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(error)
}
}
return ret0
}

func (mock *MockSlackClient) TokenIsSet() bool {
params := []pegomock.Param{}
result := pegomock.GetGenericMockFrom(mock).Invoke("TokenIsSet", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem()})
var ret0 bool
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(bool)
}
}
return ret0
}

func (mock *MockSlackClient) ChannelExists(channelName string) (bool, error) {
params := []pegomock.Param{channelName}
result := pegomock.GetGenericMockFrom(mock).Invoke("ChannelExists", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
var ret0 bool
var ret1 error
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(bool)
}
if result[1] != nil {
ret1 = result[1].(error)
}
}
return ret0, ret1
}

func (mock *MockSlackClient) PostMessage(channel string, applyResult webhooks.ApplyResult) error {
params := []pegomock.Param{channel, applyResult}
result := pegomock.GetGenericMockFrom(mock).Invoke("PostMessage", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()})
var ret0 error
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(error)
}
}
return ret0
}

func (mock *MockSlackClient) VerifyWasCalledOnce() *VerifierSlackClient {
return &VerifierSlackClient{mock, pegomock.Times(1), nil}
}

func (mock *MockSlackClient) VerifyWasCalled(invocationCountMatcher pegomock.Matcher) *VerifierSlackClient {
return &VerifierSlackClient{mock, invocationCountMatcher, nil}
}

func (mock *MockSlackClient) VerifyWasCalledInOrder(invocationCountMatcher pegomock.Matcher, inOrderContext *pegomock.InOrderContext) *VerifierSlackClient {
return &VerifierSlackClient{mock, invocationCountMatcher, inOrderContext}
}

type VerifierSlackClient struct {
mock *MockSlackClient
invocationCountMatcher pegomock.Matcher
inOrderContext *pegomock.InOrderContext
}

func (verifier *VerifierSlackClient) AuthTest() *SlackClient_AuthTest_OngoingVerification {
params := []pegomock.Param{}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "AuthTest", params)
return &SlackClient_AuthTest_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}

type SlackClient_AuthTest_OngoingVerification struct {
mock *MockSlackClient
methodInvocations []pegomock.MethodInvocation
}

func (c *SlackClient_AuthTest_OngoingVerification) GetCapturedArguments() {
}

func (c *SlackClient_AuthTest_OngoingVerification) GetAllCapturedArguments() {
}

func (verifier *VerifierSlackClient) TokenIsSet() *SlackClient_TokenIsSet_OngoingVerification {
params := []pegomock.Param{}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "TokenIsSet", params)
return &SlackClient_TokenIsSet_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}

type SlackClient_TokenIsSet_OngoingVerification struct {
mock *MockSlackClient
methodInvocations []pegomock.MethodInvocation
}

func (c *SlackClient_TokenIsSet_OngoingVerification) GetCapturedArguments() {
}

func (c *SlackClient_TokenIsSet_OngoingVerification) GetAllCapturedArguments() {
}

func (verifier *VerifierSlackClient) ChannelExists(channelName string) *SlackClient_ChannelExists_OngoingVerification {
params := []pegomock.Param{channelName}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "ChannelExists", params)
return &SlackClient_ChannelExists_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}

type SlackClient_ChannelExists_OngoingVerification struct {
mock *MockSlackClient
methodInvocations []pegomock.MethodInvocation
}

func (c *SlackClient_ChannelExists_OngoingVerification) GetCapturedArguments() string {
channelName := c.GetAllCapturedArguments()
return channelName[len(channelName)-1]
}

func (c *SlackClient_ChannelExists_OngoingVerification) GetAllCapturedArguments() (_param0 []string) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]string, len(params[0]))
for u, param := range params[0] {
_param0[u] = param.(string)
}
}
return
}

func (verifier *VerifierSlackClient) PostMessage(channel string, applyResult webhooks.ApplyResult) *SlackClient_PostMessage_OngoingVerification {
params := []pegomock.Param{channel, applyResult}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "PostMessage", params)
return &SlackClient_PostMessage_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}

type SlackClient_PostMessage_OngoingVerification struct {
mock *MockSlackClient
methodInvocations []pegomock.MethodInvocation
}

func (c *SlackClient_PostMessage_OngoingVerification) GetCapturedArguments() (string, webhooks.ApplyResult) {
channel, applyResult := c.GetAllCapturedArguments()
return channel[len(channel)-1], applyResult[len(applyResult)-1]
}

func (c *SlackClient_PostMessage_OngoingVerification) GetAllCapturedArguments() (_param0 []string, _param1 []webhooks.ApplyResult) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]string, len(params[0]))
for u, param := range params[0] {
_param0[u] = param.(string)
}
_param1 = make([]webhooks.ApplyResult, len(params[1]))
for u, param := range params[1] {
_param1[u] = param.(webhooks.ApplyResult)
}
}
return
}
Loading

0 comments on commit 9dc9434

Please sign in to comment.