-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
371 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
FROM golang:1.11 | ||
|
||
LABEL version="1.0.0" | ||
LABEL maintainer="Apex" | ||
LABEL repository="http://github.com/apex/actions" | ||
LABEL homepage="http://github.com/apex/actions/slack" | ||
LABEL "com.github.actions.name"="Slack" | ||
LABEL "com.github.actions.description"="Send a Slack message" | ||
LABEL "com.github.actions.icon"="slack" | ||
LABEL "com.github.actions.color"="white" | ||
|
||
RUN go get github.com/apex/actions/slack/cmd/slack | ||
|
||
ENTRYPOINT ["slack"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Slack | ||
|
||
GitHub Action for sending Slack messages which were defined by previous action(s) in ./slack.json. | ||
|
||
## Secrets | ||
|
||
- `SLACK_WEBHOOK_URL` - *Required* The Slack webhook URL. | ||
- `SLACK_CHANNEL` - *Optional* The Slack channel name. | ||
- `SLACK_USERNAME` - *Optional* The Slack message username. | ||
- `SLACK_ICON` - *Optional* The Slack message icon. | ||
|
||
## Example | ||
|
||
This example sends a Slack notification after a deployment is complete. The `apex/actions/up` | ||
action generates a slack.json to provide a message. | ||
|
||
``` | ||
workflow "Deployment" { | ||
on = "push" | ||
resolves = ["Deploy Notification"] | ||
} | ||
action "Build" { | ||
uses = "apex/actions/go@master" | ||
} | ||
action "Deploy" { | ||
needs = "Build" | ||
uses = "apex/actions/up@master" | ||
secrets = ["AWS_SECRET_ACCESS_KEY", "AWS_ACCESS_KEY_ID"] | ||
args = "deploy production" | ||
} | ||
action "Deploy Notification" { | ||
needs = "Deploy" | ||
uses = "apex/actions/slack@master" | ||
secrets = ["SLACK_WEBHOOK_URL"] | ||
} | ||
``` | ||
|
||
## Links | ||
|
||
- Message format: https://api.slack.com/docs/messages/builder |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"os" | ||
|
||
"github.com/apex/actions/slack" | ||
) | ||
|
||
func main() { | ||
var msg slack.Message | ||
|
||
// read message | ||
err := slack.ReadMessage("slack.json", &msg) | ||
|
||
if os.IsNotExist(err) { | ||
log.Fatalf("Missing ./slack.json file, a previous action should populate it.") | ||
} | ||
|
||
if err != nil { | ||
log.Fatalf("error reading message: %s", err) | ||
} | ||
|
||
// webhook | ||
webhook := os.Getenv("SLACK_WEBHOOK_URL") | ||
|
||
if webhook == "" { | ||
log.Fatalf("Missing SLACK_WEBHOOK_URL environment variable") | ||
} | ||
|
||
// channel | ||
if s := os.Getenv("SLACK_CHANNEL"); s != "" { | ||
msg.Channel = s | ||
} | ||
|
||
// username | ||
if s := os.Getenv("SLACK_USERNAME"); s != "" { | ||
msg.Username = s | ||
} | ||
|
||
// icon | ||
if s := os.Getenv("SLACK_ICON"); s != "" { | ||
msg.IconURL = s | ||
} | ||
|
||
err = slack.Send(webhook, &msg) | ||
if err != nil { | ||
log.Fatalf("error sending message: %s", err) | ||
} | ||
|
||
fmt.Printf("Slack message sent!\n") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
package slack | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"io/ioutil" | ||
"net/http" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
// AttachmentField contains information for an attachment field | ||
// An Attachment can contain multiple of these | ||
type AttachmentField struct { | ||
Title string `json:"title"` | ||
Value string `json:"value"` | ||
Short bool `json:"short"` | ||
} | ||
|
||
// AttachmentAction is a button or menu to be included in the attachment. Required when | ||
// using message buttons or menus and otherwise not useful. A maximum of 5 actions may be | ||
// provided per attachment. | ||
type AttachmentAction struct { | ||
Name string `json:"name"` // Required. | ||
Text string `json:"text"` // Required. | ||
Style string `json:"style,omitempty"` // Optional. Allowed values: "default", "primary", "danger". | ||
Type string `json:"type"` // Required. Must be set to "button" or "select". | ||
Value string `json:"value,omitempty"` // Optional. | ||
DataSource string `json:"data_source,omitempty"` // Optional. | ||
MinQueryLength int `json:"min_query_length,omitempty"` // Optional. Default value is 1. | ||
Options []AttachmentActionOption `json:"options,omitempty"` // Optional. Maximum of 100 options can be provided in each menu. | ||
SelectedOptions []AttachmentActionOption `json:"selected_options,omitempty"` // Optional. The first element of this array will be set as the pre-selected option for this menu. | ||
OptionGroups []AttachmentActionOptionGroup `json:"option_groups,omitempty"` // Optional. | ||
Confirm *ConfirmationField `json:"confirm,omitempty"` // Optional. | ||
URL string `json:"url,omitempty"` // Optional. | ||
} | ||
|
||
// AttachmentActionOption the individual option to appear in action menu. | ||
type AttachmentActionOption struct { | ||
Text string `json:"text"` // Required. | ||
Value string `json:"value"` // Required. | ||
Description string `json:"description,omitempty"` // Optional. Up to 30 characters. | ||
} | ||
|
||
// AttachmentActionOptionGroup is a semi-hierarchal way to list available options to appear in action menu. | ||
type AttachmentActionOptionGroup struct { | ||
Text string `json:"text"` // Required. | ||
Options []AttachmentActionOption `json:"options"` // Required. | ||
} | ||
|
||
// ActionCallback specific fields for the action callback. | ||
type ActionCallback struct { | ||
MessageTs string `json:"message_ts"` | ||
AttachmentID string `json:"attachment_id"` | ||
Actions []AttachmentAction `json:"actions"` | ||
} | ||
|
||
// ConfirmationField are used to ask users to confirm actions | ||
type ConfirmationField struct { | ||
Title string `json:"title,omitempty"` // Optional. | ||
Text string `json:"text"` // Required. | ||
OkText string `json:"ok_text,omitempty"` // Optional. Defaults to "Okay" | ||
DismissText string `json:"dismiss_text,omitempty"` // Optional. Defaults to "Cancel" | ||
} | ||
|
||
// Attachment contains all the information for an attachment | ||
type Attachment struct { | ||
Color string `json:"color,omitempty"` | ||
Fallback string `json:"fallback"` | ||
|
||
CallbackID string `json:"callback_id,omitempty"` | ||
ID int `json:"id,omitempty"` | ||
|
||
AuthorID string `json:"author_id,omitempty"` | ||
AuthorName string `json:"author_name,omitempty"` | ||
AuthorSubname string `json:"author_subname,omitempty"` | ||
AuthorLink string `json:"author_link,omitempty"` | ||
AuthorIcon string `json:"author_icon,omitempty"` | ||
|
||
Title string `json:"title,omitempty"` | ||
TitleLink string `json:"title_link,omitempty"` | ||
Pretext string `json:"pretext,omitempty"` | ||
Text string `json:"text"` | ||
|
||
ImageURL string `json:"image_url,omitempty"` | ||
ThumbURL string `json:"thumb_url,omitempty"` | ||
|
||
Fields []AttachmentField `json:"fields,omitempty"` | ||
Actions []AttachmentAction `json:"actions,omitempty"` | ||
MarkdownIn []string `json:"mrkdwn_in,omitempty"` | ||
|
||
Footer string `json:"footer,omitempty"` | ||
FooterIcon string `json:"footer_icon,omitempty"` | ||
|
||
Ts json.Number `json:"ts,omitempty"` | ||
} | ||
|
||
// Message is a Slack message payload. | ||
type Message struct { | ||
ResponseType string `json:"response_tyoe,omitempty"` | ||
Text string `json:"text,omitempty"` | ||
Channel string `json:"channel,omitempty"` | ||
Username string `json:"username,omitempty"` | ||
IconURL string `json:"icon_url,omitempty"` | ||
IconEmoji string `json:"icon_emoji,omitempty"` | ||
UnfurlLinks bool `json:"unfurl_links,omitempty"` | ||
LinkNames string `json:"link_names,omitempty"` | ||
Attachments []*Attachment `json:"attachments,omitempty"` | ||
} | ||
|
||
// ReadMessage reads a message from the given file. | ||
func ReadMessage(path string, msg *Message) error { | ||
b, err := ioutil.ReadFile(path) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = json.Unmarshal(b, msg) | ||
if err != nil { | ||
return errors.Wrap(err, "unmarshaling") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// WriteMessage writes a message to the given file. | ||
func WriteMessage(path string, msg *Message) error { | ||
b, err := json.MarshalIndent(msg, "", " ") | ||
if err != nil { | ||
return errors.Wrap(err, "marshaling") | ||
} | ||
|
||
err = ioutil.WriteFile(path, b, 0755) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Send a message to the given webhook url. | ||
func Send(url string, msg *Message) error { | ||
var buf bytes.Buffer | ||
|
||
err := json.NewEncoder(&buf).Encode(msg) | ||
if err != nil { | ||
return errors.Wrap(err, "marshaling") | ||
} | ||
|
||
res, err := http.Post(url, "application/json", &buf) | ||
if err != nil { | ||
return errors.Wrap(err, "requesting") | ||
} | ||
defer res.Body.Close() | ||
|
||
if res.StatusCode >= 300 { | ||
return errors.Errorf("%s response", res.Status) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.