未验证 提交 c14ef35f 编写于 作者: C colynn.liu 提交者: GitHub

Merge pull request #186 from go-atomci/feat-notification-layout

improve*: notification change to pkg
...@@ -42,10 +42,10 @@ url = http://localhost:8080 ...@@ -42,10 +42,10 @@ url = http://localhost:8080
# notification config # notification config
[notification] [notification]
dingEnable = 1 dingEnable = false
ding = "https://oapi.dingtalk.com/robot/send?access_token=faketoken" ding = "https://oapi.dingtalk.com/robot/send?access_token=faketoken"
mailEnable = 1 mailEnable = false
smtpHost = "smtp.host" smtpHost = "smtp.host"
smtpPort = 465 smtpPort = 465
smtpAccount = "fake@mail.com" smtpAccount = "fake@mail.com"
......
...@@ -47,10 +47,14 @@ url = http://localhost:8080 ...@@ -47,10 +47,14 @@ url = http://localhost:8080
# 通知配置 # 通知配置
[notification] [notification]
# 钉钉通知 # 钉钉通知
dingEnable = 1 # dingEnable=true 开启dinding通知
# dingEnable=false 关闭dingding通知
dingEnable = true
ding = "https://oapi.dingtalk.com/robot/send?access_token=faketoken" ding = "https://oapi.dingtalk.com/robot/send?access_token=faketoken"
# 邮件通知 # 邮件通知
mailEnable = 1 # mailEnable = true 开启email通知
# mailEnable = false 关闭email通知
mailEnable = true
smtpHost = "smtp.host" smtpHost = "smtp.host"
smtpPort = 465 smtpPort = 465
smtpAccount = "fake@mail.com" smtpAccount = "fake@mail.com"
......
...@@ -17,10 +17,11 @@ limitations under the License. ...@@ -17,10 +17,11 @@ limitations under the License.
package api package api
import ( import (
"github.com/go-atomci/atomci/internal/core/notification/impl" "github.com/astaxie/beego"
"github.com/go-atomci/atomci/internal/core/pipelinemgr" "github.com/go-atomci/atomci/internal/core/pipelinemgr"
"github.com/go-atomci/atomci/internal/core/publish" "github.com/go-atomci/atomci/internal/core/publish"
"github.com/go-atomci/atomci/internal/middleware/log" "github.com/go-atomci/atomci/internal/middleware/log"
"github.com/go-atomci/atomci/pkg/notification"
) )
// PipelineController ... // PipelineController ...
...@@ -119,8 +120,35 @@ func (p *PipelineController) RunStepCallback() { ...@@ -119,8 +120,35 @@ func (p *PipelineController) RunStepCallback() {
log.Log.Error("RunStep callback, update publish Order occur error: %s", err.Error()) log.Log.Error("RunStep callback, update publish Order occur error: %s", err.Error())
return return
} }
publishInfo, _ := publishmgr.GetPublishInfo(publishID)
go notification.Send(publishID, publishStatus) dingEnable := beego.AppConfig.DefaultBool("notification::dingEnable", false)
mailEnable := beego.AppConfig.DefaultBool("notification::mailEnable", false)
dingURL := beego.AppConfig.String("notification::ding")
smtpHost := beego.AppConfig.String("notification::smtpHost")
smtpAccount := beego.AppConfig.String("notification::smtpAccount")
smtpPassword := beego.AppConfig.String("notification::smtpPassword")
smtpPort, _ := beego.AppConfig.Int("notification::smtpPort")
pushOptions := notification.PushNotification{
// message
Status: publishStatus,
PublishName: publishInfo.Name,
StageName: publishInfo.StageName,
StepName: publishInfo.Step,
// dingding
DingURL: dingURL,
DingEnable: dingEnable,
// email
EmailEnable: mailEnable,
EmailHost: smtpHost,
EmailPort: smtpPort,
EmailUser: smtpAccount,
EmailPassword: smtpPassword,
}
// publishID
go notification.Send(pushOptions)
p.Data["json"] = NewResult(true, nil, "") p.Data["json"] = NewResult(true, nil, "")
p.ServeJSON() p.ServeJSON()
......
package notification
import (
"github.com/astaxie/beego"
messages "github.com/go-atomci/atomci/internal/core/notification/types"
"github.com/go-atomci/atomci/internal/core/publish"
)
type INotify interface {
Send(m messages.StepCallbackResult) error
}
func NewHandlers() []INotify {
dingEnable, _ := beego.AppConfig.Int("notification::dingEnable")
mailEnable, _ := beego.AppConfig.Int("notification::mailEnable")
var handlers []INotify
if dingEnable > 0 {
handlers = append(handlers, DingRobotHandler())
}
if mailEnable > 0 {
handlers = append(handlers, EmailHandler())
}
return handlers
}
func Send(publishId int64, status int64) {
pm := publish.NewPublishManager()
pub, _ := pm.GetPublishInfo(publishId)
handlers := NewHandlers()
callbackResult := messages.StepCallbackResult{
PublishName: pub.Name,
StageName: pub.StageName,
StepName: pub.Step,
Status: status,
}
if handlers != nil {
for _, handler := range handlers {
go handler.Send(callbackResult)
}
}
}
package notification
import (
"github.com/astaxie/beego"
notification "github.com/go-atomci/atomci/internal/core/notification/impl"
messages "github.com/go-atomci/atomci/internal/core/notification/types"
"github.com/jarcoal/httpmock"
"github.com/stretchr/testify/assert"
"net/http"
"testing"
)
func init() {
_ = beego.LoadAppConfig("ini", "./app.unittest.conf")
}
func Test_SEND_SHOULD_NO_ERROR(t *testing.T) {
httpmock.Activate()
defer httpmock.DeactivateAndReset()
httpmock.RegisterResponder("POST", "https://dingtalk.unittest.com",
func(req *http.Request) (*http.Response, error) {
resp, err := httpmock.NewJsonResponse(200, "")
if err != nil {
return httpmock.NewStringResponse(500, ""), nil
}
return resp, nil
},
)
var temp notification.INotify
mockResult := new(messages.StepCallbackResult)
temp = new(notification.Email)
assert.NoError(t, temp.Send(*mockResult))
temp = new(notification.DingRobot)
assert.NoError(t, temp.Send(*mockResult))
hit := httpmock.GetTotalCallCount()
assert.Equal(t, 1, hit)
}
...@@ -7,20 +7,23 @@ import ( ...@@ -7,20 +7,23 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"github.com/astaxie/beego" messages "github.com/go-atomci/atomci/pkg/notification/types"
messages "github.com/go-atomci/atomci/internal/core/notification/types"
) )
type DingRobot struct{} type DingRobot struct {
DingUrl string
}
func DingRobotHandler() INotify { func DingRobotHandler(dingUrl string) INotify {
notifyHandler := &DingRobot{} notifyHandler := &DingRobot{
DingUrl: dingUrl,
}
return notifyHandler return notifyHandler
} }
func dingEventMessage(template INotifyTemplate, result messages.StepCallbackResult) messages.EventMessage { func (dingtalk *DingRobot) dingEventMessage(template INotifyTemplate, result PushNotification) messages.EventMessage {
robotHost := beego.AppConfig.String("notification::ding") robotHost := dingtalk.DingUrl
var buf bytes.Buffer var buf bytes.Buffer
template.GenSubject(&buf, result) template.GenSubject(&buf, result)
...@@ -51,11 +54,11 @@ func dingEventMessage(template INotifyTemplate, result messages.StepCallbackResu ...@@ -51,11 +54,11 @@ func dingEventMessage(template INotifyTemplate, result messages.StepCallbackResu
return msg return msg
} }
func (dingtalk *DingRobot) Send(result messages.StepCallbackResult) error { func (dingtalk *DingRobot) Send(result PushNotification) error {
template := &DingRobotMarkdownTemplate{} template := &DingRobotMarkdownTemplate{}
message := dingEventMessage(template, result) message := dingtalk.dingEventMessage(template, result)
body, err := json.Marshal(message.Ding.EventMessage) body, err := json.Marshal(message.Ding.EventMessage)
if err != nil { if err != nil {
......
...@@ -2,28 +2,30 @@ package notification ...@@ -2,28 +2,30 @@ package notification
import ( import (
"bytes" "bytes"
"github.com/astaxie/beego/logs"
"strings" "strings"
"github.com/astaxie/beego" messages "github.com/go-atomci/atomci/pkg/notification/types"
messages "github.com/go-atomci/atomci/internal/core/notification/types"
"github.com/go-gomail/gomail" "github.com/go-gomail/gomail"
) )
type Email struct{} type Email struct {
smtpHost string
stmpAccount string
smtpPassword string
smtpPort int
}
func EmailHandler() INotify { func EmailHandler(host, user, password string, port int) INotify {
notifyHandler := &Email{} notifyHandler := &Email{
smtpHost: host,
stmpAccount: user,
smtpPassword: password,
smtpPort: port,
}
return notifyHandler return notifyHandler
} }
func emailEventMessage(template INotifyTemplate, result messages.StepCallbackResult) messages.EventMessage { func emailEventMessage(template INotifyTemplate, result PushNotification) messages.EventMessage {
smtpHost := beego.AppConfig.String("notification::smtpHost")
smtpAccount := beego.AppConfig.String("notification::smtpAccount")
smtpPassword := beego.AppConfig.String("notification::smtpPassword")
smtpPort, _ := beego.AppConfig.Int("notification::smtpPort")
var buf bytes.Buffer var buf bytes.Buffer
subject := template.GenSubject(&buf, result) subject := template.GenSubject(&buf, result)
buf.Reset() buf.Reset()
...@@ -31,10 +33,10 @@ func emailEventMessage(template INotifyTemplate, result messages.StepCallbackRes ...@@ -31,10 +33,10 @@ func emailEventMessage(template INotifyTemplate, result messages.StepCallbackRes
template.GenFooter(&buf, result) template.GenFooter(&buf, result)
mailMessage := &messages.MailMessage{ mailMessage := &messages.MailMessage{
SmtpPort: smtpPort, SmtpPort: result.EmailPort,
SmtpHost: smtpHost, SmtpHost: result.EmailHost,
SmtpAccount: smtpAccount, SmtpAccount: result.EmailUser,
SmtpPassword: smtpPassword, SmtpPassword: result.EmailPassword,
Body: buf.String(), Body: buf.String(),
Subject: subject, Subject: subject,
} }
...@@ -45,7 +47,7 @@ func emailEventMessage(template INotifyTemplate, result messages.StepCallbackRes ...@@ -45,7 +47,7 @@ func emailEventMessage(template INotifyTemplate, result messages.StepCallbackRes
return msg return msg
} }
func (email *Email) Send(result messages.StepCallbackResult) error { func (email *Email) Send(result PushNotification) error {
template := &EmailTemplate{} template := &EmailTemplate{}
...@@ -64,15 +66,5 @@ func (email *Email) Send(result messages.StepCallbackResult) error { ...@@ -64,15 +66,5 @@ func (email *Email) Send(result messages.StepCallbackResult) error {
d := gomail.NewDialer(message.Mail.SmtpHost, message.Mail.SmtpPort, message.Mail.SmtpAccount, message.Mail.SmtpPassword) d := gomail.NewDialer(message.Mail.SmtpHost, message.Mail.SmtpPort, message.Mail.SmtpAccount, message.Mail.SmtpPassword)
defer func() { return d.DialAndSend(m)
if r := recover(); r != nil {
logs.Error("%v", r)
}
}()
if err := d.DialAndSend(m); err != nil {
panic(err)
}
return nil
} }
package notification
type INotify interface {
Send(m PushNotification) error
}
func NewHandlers(notify *PushNotification) []INotify {
var handlers []INotify
if notify.DingEnable && len(notify.DingURL) > 0 {
handlers = append(handlers, DingRobotHandler(notify.DingURL))
}
if notify.EmailEnable && len(notify.EmailHost) > 0 && len(notify.EmailUser) > 0 && len(notify.EmailPassword) > 0 {
handlers = append(handlers, EmailHandler(notify.EmailHost, notify.EmailUser, notify.EmailPassword, notify.EmailPort))
}
return handlers
}
func Send(options PushNotification) {
notify := &PushNotification{
DingURL: options.DingURL,
DingEnable: options.DingEnable,
EmailEnable: options.EmailEnable,
EmailHost: options.EmailHost,
EmailPort: options.EmailPort,
EmailUser: options.EmailUser,
EmailPassword: options.EmailPassword,
PublishName: options.PublishName,
StageName: options.StageName,
StepName: options.StepName,
Status: options.Status,
}
handlers := NewHandlers(notify)
for _, handler := range handlers {
go handler.Send(*notify)
}
}
package notification
import (
"testing"
"github.com/astaxie/beego"
)
func init() {
_ = beego.LoadAppConfig("ini", "./app.unittest.conf")
}
func Test_SEND_SHOULD_NO_ERROR(t *testing.T) {
// httpmock.Activate()
// defer httpmock.DeactivateAndReset()
// httpmock.RegisterResponder("POST", "https://dingtalk.unittest.com",
// func(req *http.Request) (*http.Response, error) {
// resp, err := httpmock.NewJsonResponse(200, "")
// if err != nil {
// return httpmock.NewStringResponse(500, ""), nil
// }
// return resp, nil
// },
// )
// var temp notification.INotify
// mockResult := new(messages.StepCallbackResult)
// temp = new(notification.Email)
// assert.NoError(t, temp.Send(*mockResult))
// temp = new(notification.DingRobot)
// assert.NoError(t, temp.Send(*mockResult))
// hit := httpmock.GetTotalCallCount()
// assert.Equal(t, 1, hit)
}
...@@ -3,18 +3,18 @@ package notification ...@@ -3,18 +3,18 @@ package notification
import ( import (
"bytes" "bytes"
messages "github.com/go-atomci/atomci/internal/core/notification/types" messages "github.com/go-atomci/atomci/pkg/notification/types"
) )
type INotifyTemplate interface { type INotifyTemplate interface {
GenSubject(buf *bytes.Buffer, m messages.StepCallbackResult) string GenSubject(buf *bytes.Buffer, m PushNotification) string
GenContent(buf *bytes.Buffer, m messages.StepCallbackResult) string GenContent(buf *bytes.Buffer, m PushNotification) string
GenFooter(buf *bytes.Buffer, m messages.StepCallbackResult) string GenFooter(buf *bytes.Buffer, m PushNotification) string
} }
type DingRobotMarkdownTemplate struct{} type DingRobotMarkdownTemplate struct{}
func (temp *DingRobotMarkdownTemplate) GenSubject(buf *bytes.Buffer, m messages.StepCallbackResult) string { func (temp *DingRobotMarkdownTemplate) GenSubject(buf *bytes.Buffer, m PushNotification) string {
buf.WriteString("## ") buf.WriteString("## ")
buf.WriteString(messages.StatusCodeToChinese(m.Status)) buf.WriteString(messages.StatusCodeToChinese(m.Status))
...@@ -22,7 +22,7 @@ func (temp *DingRobotMarkdownTemplate) GenSubject(buf *bytes.Buffer, m messages. ...@@ -22,7 +22,7 @@ func (temp *DingRobotMarkdownTemplate) GenSubject(buf *bytes.Buffer, m messages.
return buf.String() return buf.String()
} }
func (temp *DingRobotMarkdownTemplate) GenContent(buf *bytes.Buffer, m messages.StepCallbackResult) string { func (temp *DingRobotMarkdownTemplate) GenContent(buf *bytes.Buffer, m PushNotification) string {
buf.WriteString(m.PublishName) buf.WriteString(m.PublishName)
buf.WriteString("\r\n\r\n") buf.WriteString("\r\n\r\n")
...@@ -33,7 +33,7 @@ func (temp *DingRobotMarkdownTemplate) GenContent(buf *bytes.Buffer, m messages. ...@@ -33,7 +33,7 @@ func (temp *DingRobotMarkdownTemplate) GenContent(buf *bytes.Buffer, m messages.
return buf.String() return buf.String()
} }
func (temp *DingRobotMarkdownTemplate) GenFooter(buf *bytes.Buffer, m messages.StepCallbackResult) string { func (temp *DingRobotMarkdownTemplate) GenFooter(buf *bytes.Buffer, m PushNotification) string {
buf.WriteString("\r\n\r\n> by AtomCI") buf.WriteString("\r\n\r\n> by AtomCI")
...@@ -42,7 +42,7 @@ func (temp *DingRobotMarkdownTemplate) GenFooter(buf *bytes.Buffer, m messages.S ...@@ -42,7 +42,7 @@ func (temp *DingRobotMarkdownTemplate) GenFooter(buf *bytes.Buffer, m messages.S
type EmailTemplate struct{} type EmailTemplate struct{}
func (temp *EmailTemplate) GenSubject(buf *bytes.Buffer, m messages.StepCallbackResult) string { func (temp *EmailTemplate) GenSubject(buf *bytes.Buffer, m PushNotification) string {
buf.WriteString("流水线") buf.WriteString("流水线")
buf.WriteString(m.PublishName) buf.WriteString(m.PublishName)
...@@ -52,7 +52,7 @@ func (temp *EmailTemplate) GenSubject(buf *bytes.Buffer, m messages.StepCallback ...@@ -52,7 +52,7 @@ func (temp *EmailTemplate) GenSubject(buf *bytes.Buffer, m messages.StepCallback
return buf.String() return buf.String()
} }
func (temp *EmailTemplate) GenContent(buf *bytes.Buffer, m messages.StepCallbackResult) string { func (temp *EmailTemplate) GenContent(buf *bytes.Buffer, m PushNotification) string {
buf.WriteString("<p><h2><span>流水线: </span><b>") buf.WriteString("<p><h2><span>流水线: </span><b>")
buf.WriteString(m.PublishName) buf.WriteString(m.PublishName)
...@@ -67,7 +67,7 @@ func (temp *EmailTemplate) GenContent(buf *bytes.Buffer, m messages.StepCallback ...@@ -67,7 +67,7 @@ func (temp *EmailTemplate) GenContent(buf *bytes.Buffer, m messages.StepCallback
return buf.String() return buf.String()
} }
func (temp *EmailTemplate) GenFooter(buf *bytes.Buffer, m messages.StepCallbackResult) string { func (temp *EmailTemplate) GenFooter(buf *bytes.Buffer, m PushNotification) string {
buf.WriteString("<p>by AtomCI</p>") buf.WriteString("<p>by AtomCI</p>")
......
package notification
type PushNotification struct {
// dingtalk
DingURL string
DingEnable bool
// email
EmailEnable bool
EmailHost string
EmailPort int
EmailUser string
EmailPassword string
// message
StageName string
PublishName string
StepName string
Status int64
}
...@@ -2,6 +2,7 @@ package types ...@@ -2,6 +2,7 @@ package types
import ( import (
"fmt" "fmt"
"github.com/go-atomci/atomci/internal/models" "github.com/go-atomci/atomci/internal/models"
) )
...@@ -60,13 +61,6 @@ type EventMessage struct { ...@@ -60,13 +61,6 @@ type EventMessage struct {
Ding *DingMessage Ding *DingMessage
} }
type StepCallbackResult struct {
StageName string
PublishName string
StepName string
Status int64
}
func StatusCodeToChinese(status int64) string { func StatusCodeToChinese(status int64) string {
switch status { switch status {
case models.Success: case models.Success:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册