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":
|
||||
#
|
||||
#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=
|
1
debian/drone/etc/init/drone.conf
vendored
1
debian/drone/etc/init/drone.conf
vendored
|
@ -4,6 +4,7 @@ chdir /var/lib/drone
|
|||
console log
|
||||
|
||||
script
|
||||
set -a
|
||||
DRONED_OPTS="--port=:80"
|
||||
if [ -f /etc/default/$UPSTART_JOB ]; then
|
||||
. /etc/default/$UPSTART_JOB
|
||||
|
|
|
@ -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
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/drone/drone/plugin/notify/email"
|
||||
"github.com/drone/drone/shared/model"
|
||||
)
|
||||
|
||||
|
@ -12,7 +15,7 @@ type Sender interface {
|
|||
// for notifying a user, or group of users,
|
||||
// when their Build has completed.
|
||||
type Notification struct {
|
||||
Email *Email `yaml:"email,omitempty"`
|
||||
Email *email.Email `yaml:"email,omitempty"`
|
||||
Webhook *Webhook `yaml:"webhook,omitempty"`
|
||||
Hipchat *Hipchat `yaml:"hipchat,omitempty"`
|
||||
Irc *IRC `yaml:"irc,omitempty"`
|
||||
|
@ -21,23 +24,43 @@ type Notification struct {
|
|||
|
||||
func (n *Notification) Send(context *model.Request) error {
|
||||
// send email notifications
|
||||
if n.Webhook != nil {
|
||||
n.Webhook.Send(context)
|
||||
if n.Email != nil {
|
||||
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 {
|
||||
n.Hipchat.Send(context)
|
||||
err := n.Hipchat.Send(context)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
// send irc notifications
|
||||
if n.Irc != nil {
|
||||
n.Irc.Send(context)
|
||||
err := n.Irc.Send(context)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
// send slack notifications
|
||||
if n.Slack != nil {
|
||||
n.Slack.Send(context)
|
||||
err := n.Slack.Send(context)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
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