Skip to content

Commit

Permalink
feat: announce: slack
Browse files Browse the repository at this point in the history
Fixes #2425

Signed-off-by: Furkan <furkan.turkal@trendyol.com>
  • Loading branch information
Dentrax committed Sep 1, 2021
1 parent b661a57 commit fd4940d
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 23 deletions.
3 changes: 3 additions & 0 deletions go.mod
Expand Up @@ -95,6 +95,7 @@ require (
github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/slack-go/slack v0.9.4
github.com/spf13/pflag v1.0.5 // indirect
github.com/xanzy/ssh-agent v0.3.0 // indirect
go.opencensus.io v0.23.0 // indirect
Expand All @@ -115,3 +116,5 @@ require (
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)

require github.com/gorilla/websocket v1.4.2 // indirect
4 changes: 4 additions & 0 deletions go.sum
Expand Up @@ -244,6 +244,7 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
Expand Down Expand Up @@ -351,6 +352,7 @@ github.com/goreleaser/fileglob v1.2.0/go.mod h1:rFyb2pXaK3YdnYnSjn6lifw0h2Q6s8Of
github.com/goreleaser/nfpm/v2 v2.6.0 h1:bwDU9o4/CVTSpqASJA7+r+rkqpTGamQKYHMRH3wDlRE=
github.com/goreleaser/nfpm/v2 v2.6.0/go.mod h1:qaMnjBaZz/2vInOIWx0IbuKuaZpaVB6O8oLG0u4qH1Y=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
Expand Down Expand Up @@ -532,6 +534,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/slack-go/slack v0.9.4 h1:C+FC3zLxLxUTQjDy2RZeMHYon005zsCROiZNWVo+opQ=
github.com/slack-go/slack v0.9.4/go.mod h1:wWL//kk0ho+FcQXcBTmEafUI5dz4qz5f4mMk8oIkioQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
Expand Down
2 changes: 2 additions & 0 deletions internal/pipe/announce/announce.go
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/goreleaser/goreleaser/internal/middleware"
"github.com/goreleaser/goreleaser/internal/pipe/reddit"
"github.com/goreleaser/goreleaser/internal/pipe/slack"
"github.com/goreleaser/goreleaser/internal/pipe/twitter"
"github.com/goreleaser/goreleaser/pkg/context"
)
Expand All @@ -28,6 +29,7 @@ type Announcer interface {
var announcers = []Announcer{
twitter.Pipe{}, // announce to twitter
reddit.Pipe{}, // announce to twitter
slack.Pipe{}, // announce to slack
}

// Run the pipe.
Expand Down
71 changes: 71 additions & 0 deletions internal/pipe/slack/slack.go
@@ -0,0 +1,71 @@
package slack

import (
"fmt"
"github.com/slack-go/slack"

"github.com/apex/log"
"github.com/caarlos0/env/v6"
"github.com/goreleaser/goreleaser/internal/pipe"
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/goreleaser/goreleaser/pkg/context"
)

const (
defaultUsername = `GoReleaser`
defaultMessageTemplate = `{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .GitURL }}/releases/tag/{{ .Tag }}`
)

type Pipe struct{}

func (Pipe) String() string { return "slack" }

type Config struct {
Webhook string `env:"SLACK_WEBHOOK,notEmpty"`
}

func (Pipe) Default(ctx *context.Context) error {
if ctx.Config.Announce.Slack.MessageTemplate == "" {
ctx.Config.Announce.Slack.MessageTemplate = defaultMessageTemplate
}
if ctx.Config.Announce.Slack.Username == "" {
ctx.Config.Announce.Slack.Username = defaultUsername
}
return nil
}

func (Pipe) Announce(ctx *context.Context) error {
if ctx.SkipAnnounce {
return pipe.ErrSkipAnnounceEnabled
}
if !ctx.Config.Announce.Slack.Enabled {
return pipe.ErrSkipDisabledPipe
}

msg, err := tmpl.New(ctx).Apply(ctx.Config.Announce.Slack.MessageTemplate)
if err != nil {
return fmt.Errorf("announce: failed to announce to slack: %w", err)
}

var cfg Config
if err := env.Parse(&cfg); err != nil {
return fmt.Errorf("announce: failed to announce to slack: %w", err)
}

log.Infof("posting: '%s'", msg)

wm := &slack.WebhookMessage{
Username: ctx.Config.Announce.Slack.Username,
IconEmoji: ctx.Config.Announce.Slack.IconEmoji,
IconURL: ctx.Config.Announce.Slack.IconURL,
Channel: ctx.Config.Announce.Slack.Channel,
Text: msg,
}

err = slack.PostWebhook(cfg.Webhook, wm)
if err != nil {
return fmt.Errorf("announce: failed to announce to slack: %w", err)
}

return nil
}
62 changes: 62 additions & 0 deletions internal/pipe/slack/slack_test.go
@@ -0,0 +1,62 @@
package slack

import (
"testing"

"github.com/goreleaser/goreleaser/internal/testlib"
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/stretchr/testify/require"
)

func TestStringer(t *testing.T) {
require.Equal(t, Pipe{}.String(), "slack")
}

func TestDefault(t *testing.T) {
ctx := context.New(config.Project{})
require.NoError(t, Pipe{}.Default(ctx))
require.Equal(t, ctx.Config.Announce.Slack.MessageTemplate, defaultMessageTemplate)
}

func TestAnnounceDisabled(t *testing.T) {
ctx := context.New(config.Project{})
require.NoError(t, Pipe{}.Default(ctx))
testlib.AssertSkipped(t, Pipe{}.Announce(ctx))
}

func TestAnnounceInvalidTemplate(t *testing.T) {
ctx := context.New(config.Project{
Announce: config.Announce{
Slack: config.Slack{
Enabled: true,
MessageTemplate: "{{ .Foo }",
},
},
})
require.EqualError(t, Pipe{}.Announce(ctx), `announce: failed to announce to slack: template: tmpl:1: unexpected "}" in operand`)
}

func TestAnnounceMissingEnv(t *testing.T) {
ctx := context.New(config.Project{
Announce: config.Announce{
Slack: config.Slack{
Enabled: true,
},
},
})
require.NoError(t, Pipe{}.Default(ctx))
require.EqualError(t, Pipe{}.Announce(ctx), `announce: failed to announce to slack: env: environment variable "SLACK_WEBHOOK" should not be empty`)
}

func TestAnnounceSkipAnnounce(t *testing.T) {
ctx := context.New(config.Project{
Announce: config.Announce{
Slack: config.Slack{
Enabled: true,
},
},
})
ctx.SkipAnnounce = true
testlib.AssertSkipped(t, Pipe{}.Announce(ctx))
}
53 changes: 31 additions & 22 deletions pkg/config/config.go
Expand Up @@ -90,28 +90,27 @@ func (r Repo) String() string {

// Homebrew contains the brew section.
type Homebrew struct {
Name string `yaml:",omitempty"`
Tap RepoRef `yaml:",omitempty"`
CommitAuthor CommitAuthor `yaml:"commit_author,omitempty"`
CommitMessageTemplate string `yaml:"commit_msg_template,omitempty"`
Folder string `yaml:",omitempty"`
Caveats string `yaml:",omitempty"`
Plist string `yaml:",omitempty"`
Install string `yaml:",omitempty"`
PostInstall string `yaml:"post_install,omitempty"`
Dependencies []HomebrewDependency `yaml:",omitempty"`
Test string `yaml:",omitempty"`
Conflicts []string `yaml:",omitempty"`
Description string `yaml:",omitempty"`
Homepage string `yaml:",omitempty"`
License string `yaml:",omitempty"`
SkipUpload string `yaml:"skip_upload,omitempty"`
DownloadStrategy string `yaml:"download_strategy,omitempty"`
URLTemplate string `yaml:"url_template,omitempty"`
CustomRequire string `yaml:"custom_require,omitempty"`
CustomBlock string `yaml:"custom_block,omitempty"`
IDs []string `yaml:"ids,omitempty"`
Goarm string `yaml:"goarm,omitempty"`
Name string `yaml:",omitempty"`
Tap RepoRef `yaml:",omitempty"`
CommitAuthor CommitAuthor `yaml:"commit_author,omitempty"`
Folder string `yaml:",omitempty"`
Caveats string `yaml:",omitempty"`
Plist string `yaml:",omitempty"`
Install string `yaml:",omitempty"`
PostInstall string `yaml:"post_install,omitempty"`
Dependencies []HomebrewDependency `yaml:",omitempty"`
Test string `yaml:",omitempty"`
Conflicts []string `yaml:",omitempty"`
Description string `yaml:",omitempty"`
Homepage string `yaml:",omitempty"`
License string `yaml:",omitempty"`
SkipUpload string `yaml:"skip_upload,omitempty"`
DownloadStrategy string `yaml:"download_strategy,omitempty"`
URLTemplate string `yaml:"url_template,omitempty"`
CustomRequire string `yaml:"custom_require,omitempty"`
CustomBlock string `yaml:"custom_block,omitempty"`
IDs []string `yaml:"ids,omitempty"`
Goarm string `yaml:"goarm,omitempty"`
}

// Scoop contains the scoop.sh section.
Expand Down Expand Up @@ -692,6 +691,7 @@ type GoMod struct {
type Announce struct {
Twitter Twitter `yaml:"twitter,omitempty"`
Reddit Reddit `yaml:"reddit,omitempty"`
Slack Slack `yaml:"slack,omitempty"`
}

type Twitter struct {
Expand All @@ -708,6 +708,15 @@ type Reddit struct {
Sub string `yaml:"sub,omitempty"`
}

type Slack struct {
Enabled bool `yaml:"enabled,omitempty"`
MessageTemplate string `yaml:"message_template,omitempty"`
Channel string `yaml:"channel,omitempty"`
Username string `yaml:"username,omitempty"`
IconEmoji string `yaml:"icon_emoji,omitempty"`
IconURL string `yaml:"icon_url,omitempty"`
}

// Load config file.
func Load(file string) (config Project, err error) {
f, err := os.Open(file) // #nosec
Expand Down
2 changes: 2 additions & 0 deletions pkg/defaults/defaults.go
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/goreleaser/goreleaser/internal/pipe/nfpm"
"github.com/goreleaser/goreleaser/internal/pipe/project"
"github.com/goreleaser/goreleaser/internal/pipe/reddit"
"github.com/goreleaser/goreleaser/internal/pipe/slack"
"github.com/goreleaser/goreleaser/internal/pipe/release"
"github.com/goreleaser/goreleaser/internal/pipe/scoop"
"github.com/goreleaser/goreleaser/internal/pipe/sign"
Expand Down Expand Up @@ -59,5 +60,6 @@ var Defaulters = []Defaulter{
scoop.Pipe{},
twitter.Pipe{},
reddit.Pipe{},
slack.Pipe{},
milestone.Pipe{},
}
35 changes: 34 additions & 1 deletion www/docs/customization/announce.md
Expand Up @@ -2,7 +2,7 @@
title: Announce
---

GoReleaser can also announce new releases, currently, to Twitter only.
GoReleaser can also announce new releases, currently, to Twitter and Slack only.

It runs at the very end of the pipeline.

Expand Down Expand Up @@ -30,6 +30,39 @@ announce:
message_template: 'Awesome project {{.Tag}} is out!'
```

## Slack

For it to work, you'll need to [create a new Incoming Webhook](https://api.slack.com/messaging/webhooks), and set some environment variables on your pipeline:

- `SLACK_WEBHOOK`

Then, you can add something like the following to your `.goreleaser.yml` config:

```yaml
# .goreleaser.yml
announce:
slack:
# Wether its enabled or not.
# Defaults to false.
enabled: true

# Message template to use while publishing.
# Defaults to `{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .GitURL }}/releases/tag/{{ .Tag }}`
message_template: 'Awesome project {{.Tag}} is out!'

# The name of the channel that the user selected as a destination for webhook messages.
channel: '#channel'

# Set your Webhook's user name.
username: ''

# Emoji to use as the icon for this message. Overrides icon_url.
icon_emoji: ''

# URL to an image to use as the icon for this message.
icon_url: ''
```

!!! tip
Learn more about the [name template engine](/customization/templates/).

Expand Down

0 comments on commit fd4940d

Please sign in to comment.