added email notifications
This commit is contained in:
parent
aec5d06ff1
commit
994b6f0994
7 changed files with 276 additions and 74 deletions
38
debian/drone/etc/default/drone
vendored
38
debian/drone/etc/default/drone
vendored
|
@ -8,3 +8,41 @@
|
||||||
# -workers="4":
|
# -workers="4":
|
||||||
#
|
#
|
||||||
#DRONED_OPTS="--port=:80"
|
#DRONED_OPTS="--port=:80"
|
||||||
|
|
||||||
|
# Email configuration
|
||||||
|
#SMTP_HOST=
|
||||||
|
#SMTP_PORT=
|
||||||
|
#SMTP_FROM=
|
||||||
|
#SMTP_USER=
|
||||||
|
#SMTP_PASS=
|
||||||
|
|
||||||
|
# GitHub configuration
|
||||||
|
#GITHUB_CLIENT=
|
||||||
|
#GITHUB_SECRET=
|
||||||
|
|
||||||
|
# GitHub Enterprise configuration
|
||||||
|
#GITHUB_ENTERPRISE_CLIENT=
|
||||||
|
#GITHUB_ENTERPRISE_SECRET=
|
||||||
|
#GITHUB_ENTERPRISE_URL=
|
||||||
|
#GITHUB_ENTERPRISE_API=
|
||||||
|
|
||||||
|
# GitLab configuration
|
||||||
|
#GITLAB_URL=
|
||||||
|
|
||||||
|
# Atlassian Bitbucket configuration
|
||||||
|
#BITBUCKET_CLIENT=
|
||||||
|
#BITBUCKET_SECRET=
|
||||||
|
|
||||||
|
# Atlassian Stash configuration
|
||||||
|
#STASH_CLIENT=
|
||||||
|
#STASH_SECRET=
|
||||||
|
#STASH_URL=
|
||||||
|
#STASH_API=
|
||||||
|
|
||||||
|
# Optional global configuration options.
|
||||||
|
#
|
||||||
|
# This allows you, for example, to set a default Hipchat token
|
||||||
|
# so that you don't need to specify in each .drone.yml file.
|
||||||
|
#HIPCHAT_TOKEN=
|
||||||
|
#SLACK_TOKEN=
|
||||||
|
#ZAPIER_TOKEN=
|
11
debian/drone/etc/init/drone.conf
vendored
11
debian/drone/etc/init/drone.conf
vendored
|
@ -4,9 +4,10 @@ chdir /var/lib/drone
|
||||||
console log
|
console log
|
||||||
|
|
||||||
script
|
script
|
||||||
DRONED_OPTS="--port=:80"
|
set -a
|
||||||
if [ -f /etc/default/$UPSTART_JOB ]; then
|
DRONED_OPTS="--port=:80"
|
||||||
. /etc/default/$UPSTART_JOB
|
if [ -f /etc/default/$UPSTART_JOB ]; then
|
||||||
fi
|
. /etc/default/$UPSTART_JOB
|
||||||
/usr/local/bin/droned $DRONED_OPTS
|
fi
|
||||||
|
/usr/local/bin/droned $DRONED_OPTS
|
||||||
end script
|
end script
|
|
@ -1,48 +0,0 @@
|
||||||
package notify
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/drone/drone/shared/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Email struct {
|
|
||||||
Recipients []string `yaml:"recipients,omitempty"`
|
|
||||||
Success string `yaml:"on_success"`
|
|
||||||
Failure string `yaml:"on_failure"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send will send an email, either success or failure,
|
|
||||||
// based on the Commit Status.
|
|
||||||
func (e *Email) Send(context *model.Request) error {
|
|
||||||
switch {
|
|
||||||
case context.Commit.Status == "Success" && e.Success != "never":
|
|
||||||
return e.sendSuccess(context)
|
|
||||||
case context.Commit.Status == "Failure" && e.Failure != "never":
|
|
||||||
return e.sendFailure(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendFailure sends email notifications to the list of
|
|
||||||
// recipients indicating the build failed.
|
|
||||||
func (e *Email) sendFailure(context *model.Request) error {
|
|
||||||
// loop through and email recipients
|
|
||||||
//for _, email := range e.Recipients {
|
|
||||||
//if err := mail.SendFailure(context.Repo.Name, context.Commit.HashShort(), email, context); err != nil {
|
|
||||||
// return err
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendSuccess sends email notifications to the list of
|
|
||||||
// recipients indicating the build was a success.
|
|
||||||
func (e *Email) sendSuccess(context *model.Request) error {
|
|
||||||
// loop through and email recipients
|
|
||||||
//for _, email := range e.Recipients {
|
|
||||||
// if err := mail.SendSuccess(context.Repo.Name, context.Commit.HashShort(), email, context); err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
return nil
|
|
||||||
}
|
|
161
plugin/notify/email/email.go
Normal file
161
plugin/notify/email/email.go
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
package email
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/smtp"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/drone/drone/shared/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
NotifyAlways = "always" // always send email notification
|
||||||
|
NotifyNever = "never" // never send email notifications
|
||||||
|
NotifyAuthor = "author" // only send email notifications to the author
|
||||||
|
|
||||||
|
NotifyTrue = "true" // alias for NotifyTrue
|
||||||
|
NotifyFalse = "false" // alias for NotifyFalse
|
||||||
|
NotifyOn = "on" // alias for NotifyTrue
|
||||||
|
NotifyOff = "off" // alias for NotifyFalse
|
||||||
|
NotifyBlame = "blame" // alias for NotifyAuthor
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SubjectSuccess = "[SUCCESS] %s/%s %s"
|
||||||
|
SubjectFailure = "[FAILURE] %s/%s %s"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
DefaultHost = os.Getenv("SMTP_HOST")
|
||||||
|
DefaultPort = os.Getenv("SMTP_PORT")
|
||||||
|
DefaultFrom = os.Getenv("SMTP_FROM")
|
||||||
|
DefaultUser = os.Getenv("SMTP_USER")
|
||||||
|
DefaultPass = os.Getenv("SMTP_PASS")
|
||||||
|
)
|
||||||
|
|
||||||
|
type Email struct {
|
||||||
|
Recipients []string `yaml:"recipients"`
|
||||||
|
Success string `yaml:"on_success"`
|
||||||
|
Failure string `yaml:"on_failure"`
|
||||||
|
|
||||||
|
Host string `yaml:"host"`
|
||||||
|
Port string `yaml:"port"`
|
||||||
|
From string `yaml:"from"`
|
||||||
|
Username string `yaml:"username"`
|
||||||
|
Password string `yaml:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send will send an email, either success or failure,
|
||||||
|
// based on the Commit Status.
|
||||||
|
func (e *Email) Send(context *model.Request) error {
|
||||||
|
var status = context.Commit.Status
|
||||||
|
|
||||||
|
switch status {
|
||||||
|
// no builds are triggered for pending builds
|
||||||
|
case model.StatusEnqueue, model.StatusStarted:
|
||||||
|
return nil
|
||||||
|
case model.StatusSuccess:
|
||||||
|
return e.sendSuccess(context)
|
||||||
|
default:
|
||||||
|
return e.sendFailure(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendFailure sends email notifications to the list of
|
||||||
|
// recipients indicating the build failed.
|
||||||
|
func (e *Email) sendFailure(context *model.Request) error {
|
||||||
|
|
||||||
|
switch e.Failure {
|
||||||
|
case NotifyFalse, NotifyNever, NotifyOff:
|
||||||
|
return nil
|
||||||
|
// if configured to email the author, replace
|
||||||
|
// the recipiends with the commit author email.
|
||||||
|
case NotifyBlame, NotifyAuthor:
|
||||||
|
e.Recipients = []string{context.Commit.Author}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate the email failure template
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err := failureTemplate.ExecuteTemplate(&buf, "_", context)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate the email subject
|
||||||
|
var subject = fmt.Sprintf(
|
||||||
|
SubjectFailure,
|
||||||
|
context.Repo.Owner,
|
||||||
|
context.Repo.Name,
|
||||||
|
context.Commit.ShaShort(),
|
||||||
|
)
|
||||||
|
|
||||||
|
return e.send(subject, buf.String(), e.Recipients)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendSuccess sends email notifications to the list of
|
||||||
|
// recipients indicating the build was a success.
|
||||||
|
func (e *Email) sendSuccess(context *model.Request) error {
|
||||||
|
|
||||||
|
switch e.Success {
|
||||||
|
case NotifyFalse, NotifyNever, NotifyOff:
|
||||||
|
return nil
|
||||||
|
// if configured to email the author, replace
|
||||||
|
// the recipiends with the commit author email.
|
||||||
|
case NotifyBlame, NotifyAuthor:
|
||||||
|
e.Recipients = []string{context.Commit.Author}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate the email success template
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err := successTemplate.ExecuteTemplate(&buf, "_", context)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate the email subject
|
||||||
|
var subject = fmt.Sprintf(
|
||||||
|
SubjectSuccess,
|
||||||
|
context.Repo.Owner,
|
||||||
|
context.Repo.Name,
|
||||||
|
context.Commit.ShaShort(),
|
||||||
|
)
|
||||||
|
|
||||||
|
return e.send(subject, buf.String(), e.Recipients)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Email) send(subject, body string, recipients []string) error {
|
||||||
|
|
||||||
|
if len(recipients) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// the user can provide their own smtp server
|
||||||
|
// configuration. If None provided, attempt to
|
||||||
|
// use the global configuration set in the environet
|
||||||
|
// variables.
|
||||||
|
if len(DefaultHost) != 0 {
|
||||||
|
e.Host = DefaultHost
|
||||||
|
e.Port = DefaultPort
|
||||||
|
e.From = DefaultFrom
|
||||||
|
e.Username = DefaultUser
|
||||||
|
e.Password = DefaultPass
|
||||||
|
}
|
||||||
|
|
||||||
|
var auth smtp.Auth
|
||||||
|
var addr = net.JoinHostPort(e.Host, e.Port)
|
||||||
|
|
||||||
|
// setup the authentication to the smtp server
|
||||||
|
// if the username and password are provided.
|
||||||
|
if len(e.Username) > 0 {
|
||||||
|
auth = smtp.PlainAuth("", e.Username, e.Password, e.Host)
|
||||||
|
}
|
||||||
|
|
||||||
|
// genereate the raw email message
|
||||||
|
var to = strings.Join(e.Recipients, ",")
|
||||||
|
var raw = fmt.Sprintf(rawMessage, e.From, to, subject, body)
|
||||||
|
|
||||||
|
return smtp.SendMail(addr, auth, e.From, e.Recipients, []byte(raw))
|
||||||
|
}
|
36
plugin/notify/email/template.go
Normal file
36
plugin/notify/email/template.go
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
package email
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
// raw email message template
|
||||||
|
var rawMessage = `From: %s
|
||||||
|
To: %s
|
||||||
|
Subject: %s
|
||||||
|
MIME-version: 1.0
|
||||||
|
Content-Type: text/html; charset="UTF-8"
|
||||||
|
|
||||||
|
%s`
|
||||||
|
|
||||||
|
// default success email template
|
||||||
|
var successTemplate = template.Must(template.New("_").Parse(`
|
||||||
|
<p><b>Build was Successful</b></p>
|
||||||
|
<p>Repository : {{.Repo.Owner}}/{{.Repo.Name}}</p>
|
||||||
|
<p>Commit : {{.Commit.ShaShort}}</p>
|
||||||
|
<p>Author : {{.Commit.Author}}</p>
|
||||||
|
<p>Branch : {{.Commit.Branch}}</p>
|
||||||
|
<p>Message:</p>
|
||||||
|
<p>{{ .Commit.Message }}</p>
|
||||||
|
`))
|
||||||
|
|
||||||
|
// default failure email template
|
||||||
|
var failureTemplate = template.Must(template.New("_").Parse(`
|
||||||
|
<p><b>Build Failed</b></p>
|
||||||
|
<p>Repository : {{.Repo.Owner}}/{{.Repo.Name}}</p>
|
||||||
|
<p>Commit : {{.Commit.ShaShort}}</p>
|
||||||
|
<p>Author : {{.Commit.Author}}</p>
|
||||||
|
<p>Branch : {{.Commit.Branch}}</p>
|
||||||
|
<p>Message:</p>
|
||||||
|
<p>{{ .Commit.Message }}</p>
|
||||||
|
`))
|
|
@ -1,6 +1,9 @@
|
||||||
package notify
|
package notify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/drone/drone/plugin/notify/email"
|
||||||
"github.com/drone/drone/shared/model"
|
"github.com/drone/drone/shared/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -12,32 +15,52 @@ type Sender interface {
|
||||||
// for notifying a user, or group of users,
|
// for notifying a user, or group of users,
|
||||||
// when their Build has completed.
|
// when their Build has completed.
|
||||||
type Notification struct {
|
type Notification struct {
|
||||||
Email *Email `yaml:"email,omitempty"`
|
Email *email.Email `yaml:"email,omitempty"`
|
||||||
Webhook *Webhook `yaml:"webhook,omitempty"`
|
Webhook *Webhook `yaml:"webhook,omitempty"`
|
||||||
Hipchat *Hipchat `yaml:"hipchat,omitempty"`
|
Hipchat *Hipchat `yaml:"hipchat,omitempty"`
|
||||||
Irc *IRC `yaml:"irc,omitempty"`
|
Irc *IRC `yaml:"irc,omitempty"`
|
||||||
Slack *Slack `yaml:"slack,omitempty"`
|
Slack *Slack `yaml:"slack,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Notification) Send(context *model.Request) error {
|
func (n *Notification) Send(context *model.Request) error {
|
||||||
// send email notifications
|
// send email notifications
|
||||||
if n.Webhook != nil {
|
if n.Email != nil {
|
||||||
n.Webhook.Send(context)
|
err := n.Email.Send(context)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send email notifications
|
// send webhook notifications
|
||||||
|
if n.Webhook != nil {
|
||||||
|
err := n.Webhook.Send(context)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// send hipchat notifications
|
||||||
if n.Hipchat != nil {
|
if n.Hipchat != nil {
|
||||||
n.Hipchat.Send(context)
|
err := n.Hipchat.Send(context)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send irc notifications
|
// send irc notifications
|
||||||
if n.Irc != nil {
|
if n.Irc != nil {
|
||||||
n.Irc.Send(context)
|
err := n.Irc.Send(context)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send slack notifications
|
// send slack notifications
|
||||||
if n.Slack != nil {
|
if n.Slack != nil {
|
||||||
n.Slack.Send(context)
|
err := n.Slack.Send(context)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
package smtp
|
|
||||||
|
|
||||||
type SMTP struct {
|
|
||||||
Host string `json:"host"`
|
|
||||||
Port string `json:"port"`
|
|
||||||
From string `json:"from"`
|
|
||||||
Username string `json:"username"`
|
|
||||||
Password string `json:"password"`
|
|
||||||
}
|
|
Loading…
Reference in a new issue