├── .gitignore ├── rootfs └── README.md ├── Dockerfile ├── Makefile ├── LICENSE.txt ├── main.go └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | rootfs/slack-notify 3 | -------------------------------------------------------------------------------- /rootfs/README.md: -------------------------------------------------------------------------------- 1 | # Slack Notifier 2 | 3 | The slack notifier makes it possible to send messages to a slack server. 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:jessie-slim 2 | RUN apt-get update && apt-get install -y ca-certificates 3 | 4 | COPY rootfs / 5 | 6 | CMD /slack-notify 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_REGISTRY ?= "technosophos" 3 | 4 | .PHONY: build 5 | build: 6 | mkdir -p bin/ 7 | go build -o bin/slack-notify ./main.go 8 | 9 | .PHONY: docker-build 10 | docker-build: 11 | mkdir -p rootfs 12 | GOOS=linux GOARCH=amd64 go build -o rootfs/slack-notify ./main.go 13 | docker build -t $(DOCKER_REGISTRY)/slack-notify:latest . 14 | 15 | .PHONY: docker-push 16 | docker-push: 17 | docker push $(DOCKER_REGISTRY)/slack-notify 18 | 19 | .PHONY: bootstrap 20 | bootstrap: 21 | 22 | 23 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Slack Notify 2 | Copyright (C) 2017 Matt Butcher 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "os" 9 | ) 10 | 11 | const ( 12 | EnvSlackWebhook = "SLACK_WEBHOOK" 13 | EnvSlackIcon = "SLACK_ICON" 14 | EnvSlackChannel = "SLACK_CHANNEL" 15 | EnvSlackTitle = "SLACK_TITLE" 16 | EnvSlackMessage = "SLACK_MESSAGE" 17 | EnvSlackColor = "SLACK_COLOR" 18 | EnvSlackUserName = "SLACK_USERNAME" 19 | ) 20 | 21 | type Webhook struct { 22 | Text string `json:"text,omitempty"` 23 | UserName string `json:"username,omitempty"` 24 | IconURL string `json:"icon_url,omitempty"` 25 | IconEmoji string `json:"icon_emoji,omitempty"` 26 | Channel string `json:"channel,omitempty"` 27 | UnfurlLinks bool `json:"unfurl_links"` 28 | Attachments []Attachment `json:"attachments,omitmepty"` 29 | } 30 | 31 | type Attachment struct { 32 | Fallback string `json:"fallback"` 33 | Pretext string `json:"pretext,omitempty"` 34 | Color string `json:"color,omitempty"` 35 | Fields []Field `json:"fields,omitempty"` 36 | } 37 | 38 | type Field struct { 39 | Title string `json:"title"` 40 | Value string `json:"value,omitempty"` 41 | Short bool `json:short"` 42 | } 43 | 44 | func main() { 45 | endpoint := os.Getenv(EnvSlackWebhook) 46 | if endpoint == "" { 47 | fmt.Fprintln(os.Stderr, "URL is required") 48 | os.Exit(1) 49 | } 50 | text := os.Getenv(EnvSlackMessage) 51 | if text == "" { 52 | fmt.Fprintln(os.Stderr, "Message is required") 53 | os.Exit(1) 54 | } 55 | 56 | msg := Webhook{ 57 | UserName: os.Getenv(EnvSlackUserName), 58 | IconURL: os.Getenv(EnvSlackIcon), 59 | Channel: os.Getenv(EnvSlackChannel), 60 | Attachments: []Attachment{ 61 | { 62 | Fallback: envOr(EnvSlackMessage, "This space intentionally left blank"), 63 | Color: os.Getenv(EnvSlackColor), 64 | Fields: []Field{ 65 | { 66 | Title: os.Getenv(EnvSlackTitle), 67 | Value: envOr(EnvSlackMessage, "EOM"), 68 | }, 69 | }, 70 | }, 71 | }, 72 | } 73 | 74 | if err := send(endpoint, msg); err != nil { 75 | fmt.Fprintf(os.Stderr, "Error sending message: %s\n", err) 76 | os.Exit(2) 77 | } 78 | } 79 | 80 | func envOr(name, def string) string { 81 | if d, ok := os.LookupEnv(name); ok { 82 | return d 83 | } 84 | return def 85 | } 86 | 87 | func send(endpoint string, msg Webhook) error { 88 | enc, err := json.Marshal(msg) 89 | if err != nil { 90 | return err 91 | } 92 | b := bytes.NewBuffer(enc) 93 | res, err := http.Post(endpoint, "application/json", b) 94 | if err != nil { 95 | return err 96 | } 97 | 98 | if res.StatusCode >= 299 { 99 | return fmt.Errorf("Error on message: %s\n", res.Status) 100 | } 101 | fmt.Println(res.Status) 102 | return nil 103 | } 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Slack-Notify 2 | 3 | Slack-Notify is a very simple tool for sending a Slack notification via a 4 | Slack Incoming Webhook. 5 | 6 | It is designed to function as a 12-factor app, receiving configuration via 7 | environment variables. To keep things simple, it is rigid in what it allows you 8 | to set. More complex slackbots might want to customize this a little more. 9 | 10 | ## Slack Incoming Webhooks 11 | 12 | This tool uses [Slack Incoming Webhooks](https://api.slack.com/incoming-webhooks) 13 | to send a message to your slack channel. 14 | 15 | Before you can use this tool, you need to log into your Slack account and configure 16 | this. 17 | 18 | ## Usage 19 | 20 | Running `slack-notify` in a shell prompt goes like this: 21 | 22 | ```console 23 | $ export SLACK_WEBHOOK=https://hooks.slack.com/services/Txxxxxx/Bxxxxxx/xxxxxxxx 24 | $ SLACK_MESSAGE="hello" slack-notify 25 | ``` 26 | 27 | Running the Docker container goes like this: 28 | 29 | ```console 30 | $ export SLACK_WEBHOOK=https://hooks.slack.com/services/Txxxxxx/Bxxxxxx/xxxxxxxx 31 | $ docker run -e SLACK_WEBHOOK=$SLACK_WEBHOOK -e SLACK_MESSAGE="hello" -e SLACK_CHANNEL=acid technosophos/slack-notify 32 | ``` 33 | 34 | ### In Brigade 35 | 36 | You can easily use this inside of brigade hooks. Here is an example from 37 | [hello-helm](https://github.com/technosophos/hello-helm): 38 | 39 | 40 | ```javascript 41 | const {events, Job} = require("brigadier") 42 | 43 | events.on("imagePush", (e, p) => { 44 | 45 | var slack = new Job("slack-notify", "technosophos/slack-notify:latest", ["/slack-notify"]) 46 | 47 | // This doesn't need access to storage, so skip mounting to speed things up. 48 | slack.storage.enabled = false 49 | slack.env = { 50 | // It's best to store the slack webhook URL in a project's secrets. 51 | SLACK_WEBHOOK: p.secrets.SLACK_WEBHOOK, 52 | SLACK_USERNAME: "MyBot", 53 | SLACK_TITLE: "Message Title", 54 | SLACK_MESSAGE: "Message Body", 55 | SLACK_COLOR: "#0000ff" 56 | } 57 | slack.run() 58 | }) 59 | ``` 60 | 61 | 62 | 63 | ## Environment Variables 64 | 65 | ```shell 66 | # The Slack-assigned webhook 67 | SLACK_WEBHOOK=https://hooks.slack.com/services/Txxxxxx/Bxxxxxx/xxxxxxxx 68 | # A URL to an icon 69 | SLACK_ICON=http://example.com/icon.png 70 | # The channel to send the message to (if omitted, use Slack-configured default) 71 | SLACK_CHANNEL=example 72 | # The title of the message 73 | SLACK_TITLE="Hello World" 74 | # The body of the message 75 | SLACK_MESSAGE="Today is a fine day" 76 | # RGB color to for message formatting. (Slack determines what is colored by this) 77 | SLACK_COLOR="#efefef" 78 | # The name of the sender of the message. Does not need to be a "real" username 79 | SLACK_USERNAME" 80 | ``` 81 | 82 | ## Build It 83 | 84 | Configure: 85 | 86 | ``` 87 | make bootstrap 88 | ``` 89 | 90 | Compile: 91 | 92 | ``` 93 | make build 94 | ``` 95 | 96 | Publish to DockerHub 97 | 98 | ``` 99 | make docker-build docker-push 100 | ``` 101 | 102 | 103 | --------------------------------------------------------------------------------