Skip to content

Commit

Permalink
Merge pull request #1 from hootsuite/slack-webhooks-lkysow
Browse files Browse the repository at this point in the history
Refactor webhooks
  • Loading branch information
nicholas-wu-hs authored Nov 8, 2017
2 parents 8c1dc0f + 46d9f44 commit f94cede
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 159 deletions.
23 changes: 10 additions & 13 deletions server/events/apply_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package events
import (
"fmt"
"os"
"regexp"

"github.com/pkg/errors"

Expand All @@ -13,16 +12,17 @@ import (
"github.com/hootsuite/atlantis/server/events/models"
"github.com/hootsuite/atlantis/server/events/run"
"github.com/hootsuite/atlantis/server/events/terraform"
"github.com/hootsuite/atlantis/server/events/webhooks"
)

type ApplyExecutor struct {
Github github.Client
Terraform *terraform.Client
WSRegexToHook map[string]HookExecutor
RequireApproval bool
Run *run.Run
Workspace Workspace
ProjectPreExecute *ProjectPreExecute
Webhooks webhooks.WebhooksSender
}

func (a *ApplyExecutor) Execute(ctx *CommandContext) CommandResponse {
Expand Down Expand Up @@ -95,17 +95,14 @@ func (a *ApplyExecutor) apply(ctx *CommandContext, repoDir string, plan models.P
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)

// execute apply webhooks
for workspaceRegex, hookExecutor := range a.WSRegexToHook {
matched, err := regexp.MatchString(workspaceRegex, ctx.Command.Environment)
if err != nil {
// log the regexp error but let's continue with the apply
ctx.Log.Debug(err.Error())
}
if matched {
hookExecutor.ExecuteHook(ctx)
}
}
// Send webhooks.
a.Webhooks.Send(ctx.Log, webhooks.ApplyResult{
Environment: 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
28 changes: 0 additions & 28 deletions server/events/hook_executor.go

This file was deleted.

2 changes: 1 addition & 1 deletion server/events/plan_executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import (
rmocks "github.com/hootsuite/atlantis/server/events/run/mocks"
tmocks "github.com/hootsuite/atlantis/server/events/terraform/mocks"
"github.com/hootsuite/atlantis/server/logging"
. "github.com/petergtz/pegomock"
. "github.com/hootsuite/atlantis/testing"
. "github.com/petergtz/pegomock"
)

var planCtx = events.CommandContext{
Expand Down
61 changes: 0 additions & 61 deletions server/events/slack/slack_client.go

This file was deleted.

59 changes: 59 additions & 0 deletions server/events/webhooks/slack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package webhooks

import (
"fmt"
"regexp"

"github.com/nlopes/slack"
"github.com/pkg/errors"
)

type SlackWebhook struct {
EnvRegex *regexp.Regexp
Channel string
Token string
Client *slack.Client
}

func NewSlack(r *regexp.Regexp, channel string, token string) (*SlackWebhook, error) {
slackClient := slack.New(token)
if _, err := slackClient.AuthTest(); err != nil {
return nil, errors.Wrap(err, "testing slack authentication")
}
// todo: test channel exists

return &SlackWebhook{
Client: slackClient,
EnvRegex: r,
Channel: channel,
Token: token,
}, nil
}

func (s *SlackWebhook) Send(result ApplyResult) error {
if !s.EnvRegex.MatchString(result.Environment) {
return nil
}

params := slack.NewPostMessageParameters()
params.AsUser = true
params.EscapeText = false
text := s.createMessage(result)
_, _, err := s.Client.PostMessage(s.Channel, text, params)
return err
}

func (s *SlackWebhook) createMessage(result ApplyResult) string {
var status string
if result.Success {
status = ":white_check_mark:"
} else {
status = ":x:"
}
return fmt.Sprintf("%s *%s* %s in <%s|%s>.",
status,
result.User.Username,
"apply",
result.Pull.URL,
result.Repo.FullName)
}
77 changes: 77 additions & 0 deletions server/events/webhooks/webhooks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package webhooks

import (
"errors"
"fmt"
"regexp"

"github.com/hootsuite/atlantis/server/events/models"
"github.com/hootsuite/atlantis/server/logging"
)

const SlackKind = "slack"
const ApplyEvent = "apply"

type WebhooksSender interface {
Send(log *logging.SimpleLogger, result ApplyResult)
}

type WebhookSender interface {
Send(ApplyResult) error
}

type ApplyResult struct {
Environment string
Repo models.Repo
Pull models.PullRequest
User models.User
Success bool
}

type WebhooksManager struct {
Webhooks []WebhookSender
}

type Config struct {
Event string
WorkspaceRegex string
Kind string
Channel string
}

func NewWebhooksManager(configs []Config, slackToken string) (*WebhooksManager, error) {
var webhooks []WebhookSender
for _, c := range configs {
r, err := regexp.Compile(c.WorkspaceRegex)
if err != nil {
return nil, err
}
if c.Event != ApplyEvent {
return nil, fmt.Errorf("event: %s not supported. Only event: %s is supported right now", c.Kind, ApplyEvent)
}
if c.Kind != SlackKind {
return nil, fmt.Errorf("kind: %s not supported. Only kind: %s is supported right now", c.Kind, SlackKind)
}
if slackToken == "" {
return nil, errors.New("for slack webhooks, slack-token must be set")
}

slack, err := NewSlack(r, c.Channel, slackToken)
if err != nil {
return nil, err
}
webhooks = append(webhooks, slack)
}

return &WebhooksManager{
Webhooks: webhooks,
}, nil
}

func (w *WebhooksManager) Send(log *logging.SimpleLogger, result ApplyResult) {
for _, w := range w.Webhooks {
if err := w.Send(result); err != nil {
log.Warn("error sending slack webhook: %s", err)
}
}
}
Loading

0 comments on commit f94cede

Please sign in to comment.