commit
bea3fb3511
|
@ -27,6 +27,9 @@ data:
|
|||
{{- if .Values.teams.enabled }}
|
||||
TEAMS_WEBHOOK_URL: {{ .Values.teams.webhookUrl | b64enc }}
|
||||
{{- end }}
|
||||
{{- if .Values.discord.enabled }}
|
||||
DISCORD_WEBHOOK_URL: {{ .Values.discord.webhookUrl | b64enc }}
|
||||
{{- end }}
|
||||
{{- if and .Values.mail.enabled .Values.mail.smtp.pass }}
|
||||
MAIL_SMTP_PASS: {{ .Values.mail.smtp.pass | b64enc }}
|
||||
{{- end }}
|
||||
|
|
|
@ -93,6 +93,11 @@ teams:
|
|||
enabled: false
|
||||
webhookUrl: ""
|
||||
|
||||
# Discord notifications
|
||||
discord:
|
||||
enabled: false
|
||||
webhookUrl: ""
|
||||
|
||||
# Mail notifications
|
||||
mail:
|
||||
enabled: false
|
||||
|
|
|
@ -39,6 +39,7 @@ import (
|
|||
|
||||
// notification extensions
|
||||
"github.com/keel-hq/keel/extension/notification/auditor"
|
||||
_ "github.com/keel-hq/keel/extension/notification/discord"
|
||||
_ "github.com/keel-hq/keel/extension/notification/hipchat"
|
||||
_ "github.com/keel-hq/keel/extension/notification/mail"
|
||||
_ "github.com/keel-hq/keel/extension/notification/mattermost"
|
||||
|
|
|
@ -34,6 +34,9 @@ const (
|
|||
// MS Teams webhook url, see https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using#setting-up-a-custom-incoming-webhook
|
||||
EnvTeamsWebhookUrl = "TEAMS_WEBHOOK_URL"
|
||||
|
||||
// Discord webhook url, see https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks
|
||||
EnvDiscordWebhookUrl = "DISCORD_WEBHOOK_URL"
|
||||
|
||||
// Mail notification settings
|
||||
EnvMailTo = "MAIL_TO"
|
||||
EnvMailFrom = "MAIL_FROM"
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
package discord
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/keel-hq/keel/constants"
|
||||
"github.com/keel-hq/keel/extension/notification"
|
||||
"github.com/keel-hq/keel/types"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const timeout = 5 * time.Second
|
||||
|
||||
type sender struct {
|
||||
endpoint string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// Config represents the configuration of a Discord Webhook Sender.
|
||||
type Config struct {
|
||||
Endpoint string
|
||||
}
|
||||
|
||||
func init() {
|
||||
log.Info(0)
|
||||
notification.RegisterSender("discord", &sender{})
|
||||
}
|
||||
|
||||
func (s *sender) Configure(config *notification.Config) (bool, error) {
|
||||
log.Info(1)
|
||||
// Get configuration
|
||||
var httpConfig Config
|
||||
|
||||
if os.Getenv(constants.EnvDiscordWebhookUrl) != "" {
|
||||
httpConfig.Endpoint = os.Getenv(constants.EnvDiscordWebhookUrl)
|
||||
} else {
|
||||
return false, nil
|
||||
}
|
||||
// Validate endpoint URL.
|
||||
if httpConfig.Endpoint == "" {
|
||||
return false, nil
|
||||
}
|
||||
if _, err := url.ParseRequestURI(httpConfig.Endpoint); err != nil {
|
||||
return false, fmt.Errorf("could not parse endpoint URL: %s", err)
|
||||
}
|
||||
s.endpoint = httpConfig.Endpoint
|
||||
|
||||
// Setup HTTP client.
|
||||
s.client = &http.Client{
|
||||
Transport: http.DefaultTransport,
|
||||
Timeout: timeout,
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"name": "discord",
|
||||
"endpoint": s.endpoint,
|
||||
}).Info("extension.notification.discord: sender configured")
|
||||
log.Info(2)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
type DiscordMessage struct {
|
||||
Username string `json:"username"`
|
||||
Content string `json:"content"`
|
||||
Embeds []Embed `json:"embeds"`
|
||||
}
|
||||
|
||||
type Embed struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Footer Footer `json:"footer"`
|
||||
}
|
||||
|
||||
type Footer struct {
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
func (s *sender) Send(event types.EventNotification) error {
|
||||
discordMessage := DiscordMessage{
|
||||
Username: "Keel",
|
||||
Embeds: []Embed{
|
||||
{
|
||||
Title: fmt.Sprintf("%s: %s", event.Type.String(), event.Name),
|
||||
Description: event.Message,
|
||||
Footer: Footer{Text: event.Level.String()},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
jsonMessage, err := json.Marshal(discordMessage)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not marshal: %s", err)
|
||||
}
|
||||
|
||||
resp, err := s.client.Post(s.endpoint, "application/json", bytes.NewBuffer(jsonMessage))
|
||||
if err != nil || resp == nil || (resp.StatusCode != 200 && resp.StatusCode != 204) {
|
||||
if resp != nil {
|
||||
return fmt.Errorf("got status %d, expected 200/204", resp.StatusCode)
|
||||
}
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package discord
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/keel-hq/keel/types"
|
||||
)
|
||||
|
||||
func TestDiscordWebhookRequest(t *testing.T) {
|
||||
currentTime := time.Now()
|
||||
handler := func(resp http.ResponseWriter, req *http.Request) {
|
||||
body, err := io.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
t.Errorf("failed to parse body: %s", err)
|
||||
}
|
||||
|
||||
bodyStr := string(body)
|
||||
|
||||
if !strings.Contains(bodyStr, types.NotificationPreDeploymentUpdate.String()) {
|
||||
t.Errorf("missing deployment type")
|
||||
}
|
||||
|
||||
if !strings.Contains(bodyStr, "debug") {
|
||||
t.Errorf("missing level")
|
||||
}
|
||||
|
||||
if !strings.Contains(bodyStr, "update deployment") {
|
||||
t.Errorf("missing name")
|
||||
}
|
||||
if !strings.Contains(bodyStr, "message here") {
|
||||
t.Errorf("missing message")
|
||||
}
|
||||
|
||||
t.Log(bodyStr)
|
||||
}
|
||||
|
||||
// create test server with handler
|
||||
ts := httptest.NewServer(http.HandlerFunc(handler))
|
||||
defer ts.Close()
|
||||
|
||||
s := &sender{
|
||||
endpoint: ts.URL,
|
||||
client: &http.Client{},
|
||||
}
|
||||
|
||||
s.Send(types.EventNotification{
|
||||
Name: "update deployment",
|
||||
Message: "message here",
|
||||
CreatedAt: currentTime,
|
||||
Type: types.NotificationPreDeploymentUpdate,
|
||||
Level: types.LevelDebug,
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue