diff --git a/go.mod b/go.mod
index dc02acce8b..88af79856c 100644
--- a/go.mod
+++ b/go.mod
@@ -15,6 +15,7 @@ require (
github.com/andygrunwald/go-gerrit v0.0.0-20220906192238-4fc99996c860
github.com/andygrunwald/go-jira v1.16.0
github.com/antihax/optional v1.0.0
+ github.com/atc0005/go-teams-notify/v2 v2.13.0
github.com/aws/aws-sdk-go v1.44.99
github.com/blang/semver/v4 v4.0.0
github.com/bradleyfalzon/ghinstallation v1.1.1
@@ -78,7 +79,6 @@ require (
github.com/robfig/cron/v3 v3.0.1
github.com/samber/lo v1.37.0
github.com/sashabaranov/go-openai v1.24.0
- github.com/segmentio/encoding v0.4.1
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/shirou/gopsutil/v3 v3.22.8
github.com/spf13/cobra v1.8.0
@@ -287,7 +287,6 @@ require (
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rubenv/sql-migrate v1.3.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
- github.com/segmentio/asm v1.1.3 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/afero v1.9.2 // indirect
diff --git a/go.sum b/go.sum
index bafba7d808..efd1af5126 100644
--- a/go.sum
+++ b/go.sum
@@ -180,6 +180,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY=
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
+github.com/atc0005/go-teams-notify/v2 v2.13.0 h1:nbDeHy89NjYlF/PEfLVF6lsserY9O5SnN1iOIw3AxXw=
+github.com/atc0005/go-teams-notify/v2 v2.13.0/go.mod h1:WSv9moolRsBcpZbwEf6gZxj7h0uJlJskJq5zkEWKO8Y=
github.com/aws/aws-sdk-go v1.44.99 h1:ITZ9q/fmH+Ksaz2TbyMU2d19vOOWs/hAlt8NbXAieHw=
github.com/aws/aws-sdk-go v1.44.99/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
@@ -1013,10 +1015,6 @@ github.com/sashabaranov/go-openai v1.24.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adO
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y=
github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
-github.com/segmentio/asm v1.1.3 h1:WM03sfUOENvvKexOLp+pCqgb/WDjsi7EK8gIsICtzhc=
-github.com/segmentio/asm v1.1.3/go.mod h1:Ld3L4ZXGNcSLRg4JBsZ3//1+f/TjYl0Mzen/DQy1EJg=
-github.com/segmentio/encoding v0.4.1 h1:KLGaLSW0jrmhB58Nn4+98spfvPvmo4Ci1P/WIQ9wn7w=
-github.com/segmentio/encoding v0.4.1/go.mod h1:/d03Cd8PoaDeceuhUUUQWjU0KhWjrmYrWPgtJHYZSnI=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
@@ -1086,6 +1084,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM=
diff --git a/pkg/microservice/aslan/core/common/repository/models/wokflow_task_v4.go b/pkg/microservice/aslan/core/common/repository/models/wokflow_task_v4.go
index 3580e9d977..4d8db38709 100644
--- a/pkg/microservice/aslan/core/common/repository/models/wokflow_task_v4.go
+++ b/pkg/microservice/aslan/core/common/repository/models/wokflow_task_v4.go
@@ -640,6 +640,7 @@ type JobTaskNotificationSpec struct {
LarkPersonNotificationConfig *LarkPersonNotificationConfig `bson:"lark_person_notification_config,omitempty" yaml:"lark_person_notification_config,omitempty" json:"lark_person_notification_config,omitempty"`
WechatNotificationConfig *WechatNotificationConfig `bson:"wechat_notification_config,omitempty" yaml:"wechat_notification_config,omitempty" json:"wechat_notification_config,omitempty"`
DingDingNotificationConfig *DingDingNotificationConfig `bson:"dingding_notification_config,omitempty" yaml:"dingding_notification_config,omitempty" json:"dingding_notification_config,omitempty"`
+ MSTeamsNotificationConfig *MSTeamsNotificationConfig `bson:"msteams_notification_config,omitempty" yaml:"msteams_notification_config,omitempty" json:"msteams_notification_config,omitempty"`
MailNotificationConfig *MailNotificationConfig `bson:"mail_notification_config,omitempty" yaml:"mail_notification_config,omitempty" json:"mail_notification_config,omitempty"`
WebhookNotificationConfig *WebhookNotificationConfig `bson:"webhook_notification_config,omitempty" yaml:"webhook_notification_config,omitempty" json:"webhook_notification_config,omitempty"`
diff --git a/pkg/microservice/aslan/core/common/repository/models/workflow.go b/pkg/microservice/aslan/core/common/repository/models/workflow.go
index c6d047a5de..c97873e845 100644
--- a/pkg/microservice/aslan/core/common/repository/models/workflow.go
+++ b/pkg/microservice/aslan/core/common/repository/models/workflow.go
@@ -337,6 +337,7 @@ type NotifyCtl struct {
LarkHookNotificationConfig *LarkHookNotificationConfig `bson:"lark_hook_notification_config,omitempty" yaml:"lark_hook_notification_config,omitempty" json:"lark_hook_notification_config,omitempty"`
WechatNotificationConfig *WechatNotificationConfig `bson:"wechat_notification_config,omitempty" yaml:"wechat_notification_config,omitempty" json:"wechat_notification_config,omitempty"`
DingDingNotificationConfig *DingDingNotificationConfig `bson:"dingding_notification_config,omitempty" yaml:"dingding_notification_config,omitempty" json:"dingding_notification_config,omitempty"`
+ MSTeamsNotificationConfig *MSTeamsNotificationConfig `bson:"msteams_notification_config,omitempty" yaml:"msteams_notification_config,omitempty" json:"msteams_notification_config,omitempty"`
MailNotificationConfig *MailNotificationConfig `bson:"mail_notification_config,omitempty" yaml:"mail_notification_config,omitempty" json:"mail_notification_config,omitempty"`
WebhookNotificationConfig *WebhookNotificationConfig `bson:"webhook_notification_config,omitempty" yaml:"webhook_notification_config,omitempty" json:"webhook_notification_config,omitempty"`
@@ -436,6 +437,8 @@ func (n *NotifyCtl) GenerateNewNotifyConfigWithOldData() error {
IsAtAll: n.IsAtAll,
}
}
+ case setting.NotifyWebHookTypeMSTeam:
+ break
default:
return fmt.Errorf("unsupported notification type: %s", n.WebHookType)
}
diff --git a/pkg/microservice/aslan/core/common/repository/models/workflow_v4.go b/pkg/microservice/aslan/core/common/repository/models/workflow_v4.go
index 6614fb6b75..dab68f416c 100644
--- a/pkg/microservice/aslan/core/common/repository/models/workflow_v4.go
+++ b/pkg/microservice/aslan/core/common/repository/models/workflow_v4.go
@@ -968,6 +968,7 @@ type NotificationJobSpec struct {
//LarkHookNotificationConfig *LarkHookNotificationConfig `bson:"lark_hook_notification_config,omitempty" yaml:"lark_hook_notification_config,omitempty" json:"lark_hook_notification_config,omitempty"`
WechatNotificationConfig *WechatNotificationConfig `bson:"wechat_notification_config,omitempty" yaml:"wechat_notification_config,omitempty" json:"wechat_notification_config,omitempty"`
DingDingNotificationConfig *DingDingNotificationConfig `bson:"dingding_notification_config,omitempty" yaml:"dingding_notification_config,omitempty" json:"dingding_notification_config,omitempty"`
+ MSTeamsNotificationConfig *MSTeamsNotificationConfig `bson:"msteams_notification_config,omitempty" yaml:"msteams_notification_config,omitempty" json:"msteams_notification_config,omitempty"`
MailNotificationConfig *MailNotificationConfig `bson:"mail_notification_config,omitempty" yaml:"mail_notification_config,omitempty" json:"mail_notification_config,omitempty"`
WebhookNotificationConfig *WebhookNotificationConfig `bson:"webhook_notification_config,omitempty" yaml:"webhook_notification_config,omitempty" json:"webhook_notification_config,omitempty"`
@@ -1092,6 +1093,11 @@ type DingDingNotificationConfig struct {
IsAtAll bool `bson:"is_at_all" json:"is_at_all" yaml:"is_at_all"`
}
+type MSTeamsNotificationConfig struct {
+ HookAddress string `bson:"hook_address" json:"hook_address" yaml:"hook_address"`
+ AtEmails []string `bson:"at_emails" json:"at_emails" yaml:"at_emails"`
+}
+
type MailNotificationConfig struct {
TargetUsers []*User `bson:"target_users" json:"target_users" yaml:"target_users"`
}
diff --git a/pkg/microservice/aslan/core/common/service/instantmessage/msteams.go b/pkg/microservice/aslan/core/common/service/instantmessage/msteams.go
new file mode 100644
index 0000000000..8dcd6ee667
--- /dev/null
+++ b/pkg/microservice/aslan/core/common/service/instantmessage/msteams.go
@@ -0,0 +1,96 @@
+/*
+Copyright 2022 The KodeRover Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package instantmessage
+
+import (
+ "fmt"
+ "strings"
+
+ goteamsnotify "github.com/atc0005/go-teams-notify/v2"
+ "github.com/atc0005/go-teams-notify/v2/adaptivecard"
+
+ "github.com/koderover/zadig/v2/pkg/microservice/aslan/config"
+)
+
+func (w *Service) sendMSTeamsMessage(uri, title, content, actionURL string, atEmails []string, taskStatus config.Status) error {
+ card := adaptivecard.NewCard()
+
+ _, content, found := strings.Cut(content, "\n")
+ if !found {
+ return fmt.Errorf("failed to cut content")
+ }
+
+ titleElement := adaptivecard.NewTitleTextBlock(title, false)
+
+ if taskStatus == config.StatusPassed || taskStatus == config.StatusCreated {
+ titleElement.Color = adaptivecard.ColorGood
+ } else if taskStatus == config.StatusFailed {
+ titleElement.Color = adaptivecard.ColorAttention
+ } else {
+ titleElement.Color = adaptivecard.ColorWarning
+ }
+
+ err := card.AddElement(false, titleElement)
+ if err != nil {
+ return fmt.Errorf("failed to add title element to card: %v", err)
+ }
+
+ bodyElement := adaptivecard.NewTextBlock(content, true)
+ err = card.AddElement(false, bodyElement)
+ if err != nil {
+ return fmt.Errorf("failed to add body element to card: %v", err)
+ }
+
+ userMentions := make([]adaptivecard.Mention, 0, len(atEmails))
+ for _, email := range atEmails {
+ userMention, err := adaptivecard.NewMention(email, email)
+ if err != nil {
+ return fmt.Errorf("failed to create mention: %v", err)
+ }
+ userMentions = append(userMentions, userMention)
+ }
+
+ if len(userMentions) > 0 {
+ if err := card.AddMention(false, userMentions...); err != nil {
+ return fmt.Errorf("failed to add mention to card: %v", err)
+ }
+ }
+
+ actionURLDesc := "点击查看更多信息"
+ urlAction, err := adaptivecard.NewActionOpenURL(actionURL, actionURLDesc)
+ if err != nil {
+ return fmt.Errorf("failed to create action open url: %v", err)
+ }
+
+ err = card.AddAction(false, urlAction)
+ if err != nil {
+ return fmt.Errorf("failed to add action to card: %v", err)
+ }
+
+ msg, err := adaptivecard.NewMessageFromCard(card)
+ if err != nil {
+ return fmt.Errorf("failed to create message from card: %v", err)
+ }
+
+ mstClient := goteamsnotify.NewTeamsClient()
+ err = mstClient.Send(uri, msg)
+ if err != nil {
+ return fmt.Errorf("failed to send message to MSTeams: %v", err)
+ }
+
+ return nil
+}
diff --git a/pkg/microservice/aslan/core/common/service/instantmessage/workflow_task.go b/pkg/microservice/aslan/core/common/service/instantmessage/workflow_task.go
index 6ad4316358..db6902c975 100644
--- a/pkg/microservice/aslan/core/common/service/instantmessage/workflow_task.go
+++ b/pkg/microservice/aslan/core/common/service/instantmessage/workflow_task.go
@@ -146,7 +146,7 @@ func (w *Service) SendWorkflowTaskApproveNotifications(workflowName string, task
}
}
- if err := w.sendNotification(title, content, notify, larkCard, webhookNotify); err != nil {
+ if err := w.sendNotification(title, content, notify, larkCard, webhookNotify, task.Status); err != nil {
log.Errorf("failed to send notification, err: %s", err)
}
}
@@ -253,7 +253,7 @@ func (w *Service) SendWorkflowTaskNotifications(task *models.WorkflowTask) error
}
}
- if err := w.sendNotification(title, content, notify, larkCard, webhookNotify); err != nil {
+ if err := w.sendNotification(title, content, notify, larkCard, webhookNotify, task.Status); err != nil {
log.Errorf("failed to send notification, err: %s", err)
}
}
@@ -296,11 +296,11 @@ func (w *Service) getApproveNotificationContent(notify *models.NotifyCtl, task *
tplTitle := "{{if and (ne .WebHookType \"feishu\") (ne .WebHookType \"feishu_app\") (ne .WebHookType \"feishu_person\")}}### {{end}}{{if eq .WebHookType \"dingding\"}}**{{end}}{{getIcon .Task.Status }}工作流 {{.Task.WorkflowDisplayName}} #{{.Task.TaskID}} 等待审批{{if eq .WebHookType \"dingding\"}}**{{end}} \n"
mailTplTitle := "{{getIcon .Task.Status }}工作流 {{.Task.WorkflowDisplayName}} #{{.Task.TaskID}} 等待审批\n"
- tplBaseInfo := []string{"{{if eq .WebHookType \"dingding\"}}##### {{end}}**执行用户**:{{.Task.TaskCreator}} \n",
- "{{if eq .WebHookType \"dingding\"}}##### {{end}}**项目名称**:{{.ProjectDisplayName}} \n",
- "{{if eq .WebHookType \"dingding\"}}##### {{end}}**开始时间**:{{ getStartTime .Task.StartTime}} \n",
- "{{if eq .WebHookType \"dingding\"}}##### {{end}}**持续时间**:{{ getDuration .TotalTime}} \n",
- "{{if eq .WebHookType \"dingding\"}}##### {{end}}**备注**:{{.Task.Remark}} \n",
+ tplBaseInfo := []string{"{{if eq .WebHookType \"dingding\"}}##### {{end}}**执行用户**:{{.Task.TaskCreator}} \n",
+ "{{if eq .WebHookType \"dingding\"}}##### {{end}}**项目名称**:{{.ProjectDisplayName}} \n",
+ "{{if eq .WebHookType \"dingding\"}}##### {{end}}**开始时间**:{{ getStartTime .Task.StartTime}} \n",
+ "{{if eq .WebHookType \"dingding\"}}##### {{end}}**持续时间**:{{ getDuration .TotalTime}} \n",
+ "{{if eq .WebHookType \"dingding\"}}##### {{end}}**备注**:{{.Task.Remark}} \n",
}
mailTplBaseInfo := []string{"执行用户:{{.Task.TaskCreator}} \n",
"项目名称:{{.ProjectDisplayName}} \n",
@@ -427,10 +427,10 @@ func (w *Service) getNotificationContent(notify *models.NotifyCtl, task *models.
tplTitle := "{{if and (ne .WebHookType \"feishu\") (ne .WebHookType \"feishu_app\") (ne .WebHookType \"feishu_person\")}}### {{end}}{{if eq .WebHookType \"dingding\"}}{{end}}{{getIcon .Task.Status }}{{getTaskType .Task.Type}} {{.Task.WorkflowDisplayName}} #{{.Task.TaskID}} {{ taskStatus .Task.Status }}{{if eq .WebHookType \"dingding\"}}{{end}} \n"
mailTplTitle := "{{getIcon .Task.Status }} {{getTaskType .Task.Type}} {{.Task.WorkflowDisplayName}}#{{.Task.TaskID}} {{ taskStatus .Task.Status }}"
- tplBaseInfo := []string{"{{if eq .WebHookType \"dingding\"}}##### {{end}}**执行用户**:{{.Task.TaskCreator}} \n",
- "{{if eq .WebHookType \"dingding\"}}##### {{end}}**项目名称**:{{.ProjectDisplayName}} \n",
- "{{if eq .WebHookType \"dingding\"}}##### {{end}}**开始时间**:{{ getStartTime .Task.StartTime}} \n",
- "{{if eq .WebHookType \"dingding\"}}##### {{end}}**持续时间**:{{ getDuration .TotalTime}} \n",
+ tplBaseInfo := []string{"{{if eq .WebHookType \"dingding\"}}##### {{end}}**执行用户**:{{.Task.TaskCreator}} \n",
+ "{{if eq .WebHookType \"dingding\"}}##### {{end}}**项目名称**:{{.ProjectDisplayName}} \n",
+ "{{if eq .WebHookType \"dingding\"}}##### {{end}}**开始时间**:{{ getStartTime .Task.StartTime}} \n",
+ "{{if eq .WebHookType \"dingding\"}}##### {{end}}**持续时间**:{{ getDuration .TotalTime}} \n",
"{{if eq .WebHookType \"dingding\"}}##### {{end}}**备注**:{{.Task.Remark}} \n",
}
mailTplBaseInfo := []string{"执行用户:{{.Task.TaskCreator}} \n",
@@ -462,7 +462,7 @@ func (w *Service) getNotificationContent(notify *models.NotifyCtl, task *models.
Error: job.Error,
}
- jobTplcontent := "{{if and (ne .WebHookType \"feishu\") (ne .WebHookType \"feishu_app\") (ne .WebHookType \"feishu_person\")}}\n\n{{end}}{{if eq .WebHookType \"dingding\"}}---\n\n##### {{end}}**{{jobType .Job.JobType }}**: {{.Job.DisplayName}} **状态**: {{taskStatus .Job.Status }} \n"
+ jobTplcontent := "{{if and (ne .WebHookType \"feishu\") (ne .WebHookType \"feishu_app\") (ne .WebHookType \"feishu_person\")}}\n\n{{end}}{{if eq .WebHookType \"dingding\"}}---\n\n##### {{end}}**{{jobType .Job.JobType }}**: {{.Job.DisplayName}} **状态**: {{taskStatus .Job.Status }} \n"
mailJobTplcontent := "{{jobType .Job.JobType }}:{{.Job.DisplayName}} 状态:{{taskStatus .Job.Status }} \n"
switch job.JobType {
case string(config.JobZadigBuild):
@@ -554,7 +554,7 @@ func (w *Service) getNotificationContent(notify *models.NotifyCtl, task *models.
}
}
if len(commitID) > 0 {
- jobTplcontent += fmt.Sprintf("{{if eq .WebHookType \"dingding\"}}##### {{end}}**代码信息**:%s %s[%s](%s) \n", branchTag, prInfo, commitID, gitCommitURL)
+ jobTplcontent += fmt.Sprintf("{{if eq .WebHookType \"dingding\"}}##### {{end}}**代码信息**:%s %s[%s](%s) \n", branchTag, prInfo, commitID, gitCommitURL)
jobTplcontent += "{{if eq .WebHookType \"dingding\"}}##### {{end}}**提交信息**:"
mailJobTplcontent += fmt.Sprintf("代码信息:%s %s[%s]( %s )\n", branchTag, prInfo, commitID, gitCommitURL)
if len(commitMsgs) == 1 {
@@ -567,7 +567,7 @@ func (w *Service) getNotificationContent(notify *models.NotifyCtl, task *models.
}
}
if image != "" && !strings.HasPrefix(image, "{{.") && !strings.Contains(image, "}}") {
- jobTplcontent += fmt.Sprintf("{{if eq .WebHookType \"dingding\"}}##### {{end}}**镜像信息**:%s \n", image)
+ jobTplcontent += fmt.Sprintf("{{if eq .WebHookType \"dingding\"}}##### {{end}}**镜像信息**:%s \n", image)
mailJobTplcontent += fmt.Sprintf("镜像信息:%s \n", image)
workflowNotifyJobTaskSpec.Image = image
}
@@ -576,7 +576,7 @@ func (w *Service) getNotificationContent(notify *models.NotifyCtl, task *models.
case string(config.JobZadigDeploy):
jobSpec := &models.JobTaskDeploySpec{}
models.IToi(job.Spec, jobSpec)
- jobTplcontent += fmt.Sprintf("{{if eq .WebHookType \"dingding\"}}##### {{end}}**环境**:%s \n", jobSpec.Env)
+ jobTplcontent += fmt.Sprintf("{{if eq .WebHookType \"dingding\"}}##### {{end}}**环境**:%s \n", jobSpec.Env)
mailJobTplcontent += fmt.Sprintf("环境:%s \n", jobSpec.Env)
serviceModules := []*webhooknotify.WorkflowNotifyDeployServiceModule{}
@@ -597,7 +597,7 @@ func (w *Service) getNotificationContent(notify *models.NotifyCtl, task *models.
case string(config.JobZadigHelmDeploy):
jobSpec := &models.JobTaskHelmDeploySpec{}
models.IToi(job.Spec, jobSpec)
- jobTplcontent += fmt.Sprintf("{{if eq .WebHookType \"dingding\"}}##### {{end}}**环境**:%s \n", jobSpec.Env)
+ jobTplcontent += fmt.Sprintf("{{if eq .WebHookType \"dingding\"}}##### {{end}}**环境**:%s \n", jobSpec.Env)
mailJobTplcontent += fmt.Sprintf("环境:%s \n", jobSpec.Env)
serviceModules := []*webhooknotify.WorkflowNotifyDeployServiceModule{}
@@ -906,9 +906,9 @@ func getJobTaskTplExec(tplcontent string, args *jobTaskNotification) (string, er
return buffer.String(), nil
}
-func (w *Service) sendNotification(title, content string, notify *models.NotifyCtl, card *LarkCard, webhookNotify *webhooknotify.WorkflowNotify) error {
+func (w *Service) sendNotification(title, content string, notify *models.NotifyCtl, card *LarkCard, webhookNotify *webhooknotify.WorkflowNotify, taskStatus config.Status) error {
link := ""
- if notify.WebHookType == setting.NotifyWebHookTypeDingDing || notify.WebHookType == setting.NotifyWebHookTypeWechatWork {
+ if notify.WebHookType == setting.NotifyWebHookTypeDingDing || notify.WebHookType == setting.NotifyWebHookTypeWechatWork || notify.WebHookType == setting.NotifyWebHookTypeMSTeam {
switch webhookNotify.TaskType {
case config.WorkflowTaskTypeWorkflow:
link = fmt.Sprintf("%s/v1/projects/detail/%s/pipelines/custom/%s/%d?display_name=%s", configbase.SystemAddress(), webhookNotify.ProjectName, webhookNotify.WorkflowName, webhookNotify.TaskID, url.PathEscape(webhookNotify.WorkflowDisplayName))
@@ -923,6 +923,10 @@ func (w *Service) sendNotification(title, content string, notify *models.NotifyC
}
switch notify.WebHookType {
+ case setting.NotifyWebHookTypeMSTeam:
+ if err := w.sendMSTeamsMessage(notify.MSTeamsNotificationConfig.HookAddress, title, content, link, notify.MSTeamsNotificationConfig.AtEmails, taskStatus); err != nil {
+ return err
+ }
case setting.NotifyWebHookTypeDingDing:
if err := w.sendDingDingMessage(notify.DingDingNotificationConfig.HookAddress, title, content, link, notify.DingDingNotificationConfig.AtMobiles, notify.DingDingNotificationConfig.IsAtAll); err != nil {
return err
diff --git a/pkg/microservice/aslan/core/common/service/workflowcontroller/jobcontroller/job_notification.go b/pkg/microservice/aslan/core/common/service/workflowcontroller/jobcontroller/job_notification.go
index 0a6aad8acc..4377363ea0 100644
--- a/pkg/microservice/aslan/core/common/service/workflowcontroller/jobcontroller/job_notification.go
+++ b/pkg/microservice/aslan/core/common/service/workflowcontroller/jobcontroller/job_notification.go
@@ -26,6 +26,8 @@ import (
"github.com/hashicorp/go-multierror"
"github.com/samber/lo"
"go.uber.org/zap"
+ goteamsnotify "github.com/atc0005/go-teams-notify/v2"
+ "github.com/atc0005/go-teams-notify/v2/adaptivecard"
configbase "github.com/koderover/zadig/v2/pkg/config"
"github.com/koderover/zadig/v2/pkg/microservice/aslan/config"
@@ -107,6 +109,15 @@ func (c *NotificationJobCtl) Run(ctx context.Context) {
c.ack()
return
}
+ } else if c.jobTaskSpec.WebHookType == setting.NotifyWebHookTypeMSTeam {
+ err := sendMSTeamsMessage(c.workflowCtx.ProjectName, c.workflowCtx.WorkflowName, c.workflowCtx.WorkflowDisplayName, c.workflowCtx.TaskID, c.jobTaskSpec.MSTeamsNotificationConfig.HookAddress, c.jobTaskSpec.Title, c.jobTaskSpec.Content, c.jobTaskSpec.MSTeamsNotificationConfig.AtEmails)
+ if err != nil {
+ c.logger.Error(err)
+ c.job.Status = config.StatusFailed
+ c.job.Error = err.Error()
+ c.ack()
+ return
+ }
} else if c.jobTaskSpec.WebHookType == setting.NotifyWebHookTypeWechatWork {
err := sendWorkWxMessage(c.workflowCtx.ProjectName, c.workflowCtx.WorkflowName, c.workflowCtx.WorkflowDisplayName, c.workflowCtx.TaskID, c.jobTaskSpec.WechatNotificationConfig.HookAddress, c.jobTaskSpec.Title, c.jobTaskSpec.Content, c.jobTaskSpec.WechatNotificationConfig.AtUsers, c.jobTaskSpec.WechatNotificationConfig.IsAtAll)
if err != nil {
@@ -358,6 +369,60 @@ func sendWorkWxMessage(productName, workflowName, workflowDisplayName string, ta
return nil
}
+func sendMSTeamsMessage(productName, workflowName, workflowDisplayName string, taskID int64, uri, title, message string, emailList []string) error {
+ card, err := adaptivecard.NewTextBlockCard(message, title, true)
+ if err != nil {
+ return fmt.Errorf("failed to create text block card: %v", err)
+ }
+
+ userMentions := make([]adaptivecard.Mention, 0, len(emailList))
+ for _, email := range emailList {
+ userMention, err := adaptivecard.NewMention(email, email)
+ if err != nil {
+ return fmt.Errorf("failed to create mention: %v", err)
+ }
+ userMentions = append(userMentions, userMention)
+ }
+
+ if len(userMentions) > 0 {
+ if err := card.AddMention(false, userMentions...); err != nil {
+ return fmt.Errorf("failed to add mention to card: %v", err)
+ }
+ }
+
+ actionURL := fmt.Sprintf("%s/v1/projects/detail/%s/pipelines/custom/%s/%d?display_name=%s",
+ configbase.SystemAddress(),
+ productName,
+ workflowName,
+ taskID,
+ url.PathEscape(workflowDisplayName),
+ )
+ actionURLDesc := "点击查看更多信息"
+
+ urlAction, err := adaptivecard.NewActionOpenURL(actionURL, actionURLDesc)
+ if err != nil {
+ return fmt.Errorf("failed to create action open url: %v", err)
+ }
+
+ err = card.AddAction(false, urlAction)
+ if err != nil {
+ return fmt.Errorf("failed to add action to card: %v", err)
+ }
+
+ msg, err := adaptivecard.NewMessageFromCard(card)
+ if err != nil {
+ return fmt.Errorf("failed to create message from card: %v", err)
+ }
+
+ mstClient := goteamsnotify.NewTeamsClient()
+ err = mstClient.Send(uri, msg)
+ if err != nil {
+ return fmt.Errorf("failed to send message to MSTeams: %v", err)
+ }
+
+ return nil
+}
+
func sendMailMessage(title, message string, users []*commonmodels.User, callerID string) error {
if len(users) == 0 {
return nil
diff --git a/pkg/microservice/aslan/core/workflow/service/workflow/job/job_jenkins.go b/pkg/microservice/aslan/core/workflow/service/workflow/job/job_jenkins.go
index a70cee2515..e8d840e584 100644
--- a/pkg/microservice/aslan/core/workflow/service/workflow/job/job_jenkins.go
+++ b/pkg/microservice/aslan/core/workflow/service/workflow/job/job_jenkins.go
@@ -171,7 +171,7 @@ func (j *JenkinsJob) ToJobs(taskID int64) ([]*commonmodels.JobTask, error) {
resp = append(resp, &commonmodels.JobTask{
Name: GenJobName(j.workflow, j.job.Name, 0),
Key: genJobKey(j.job.Name, job.JobName),
- DisplayName: genJobDisplayName(j.job.Name),
+ DisplayName: genJobDisplayName(j.job.Name, job.JobName),
OriginName: j.job.Name,
JobInfo: map[string]string{
JobNameKey: j.job.Name,
diff --git a/pkg/microservice/aslan/core/workflow/service/workflow/job/job_notification.go b/pkg/microservice/aslan/core/workflow/service/workflow/job/job_notification.go
index 1690abb478..f7fcaefd8b 100644
--- a/pkg/microservice/aslan/core/workflow/service/workflow/job/job_notification.go
+++ b/pkg/microservice/aslan/core/workflow/service/workflow/job/job_notification.go
@@ -111,6 +111,7 @@ func (j *NotificationJob) UpdateWithLatestSetting() error {
j.spec.LarkPersonNotificationConfig = latestSpec.LarkPersonNotificationConfig
j.spec.WechatNotificationConfig = latestSpec.WechatNotificationConfig
j.spec.DingDingNotificationConfig = latestSpec.DingDingNotificationConfig
+ j.spec.MSTeamsNotificationConfig = latestSpec.MSTeamsNotificationConfig
j.spec.MailNotificationConfig = latestSpec.MailNotificationConfig
j.spec.WebhookNotificationConfig = latestSpec.WebhookNotificationConfig
@@ -175,6 +176,7 @@ func generateNotificationJobSpec(spec *commonmodels.NotificationJobSpec) (*commo
resp.LarkPersonNotificationConfig = spec.LarkPersonNotificationConfig
resp.LarkGroupNotificationConfig = spec.LarkGroupNotificationConfig
resp.DingDingNotificationConfig = spec.DingDingNotificationConfig
+ resp.MSTeamsNotificationConfig = spec.MSTeamsNotificationConfig
resp.WebhookNotificationConfig = spec.WebhookNotificationConfig
return resp, nil
diff --git a/pkg/setting/consts.go b/pkg/setting/consts.go
index 7e7e6b3bb4..bc3a953563 100644
--- a/pkg/setting/consts.go
+++ b/pkg/setting/consts.go
@@ -946,6 +946,7 @@ const (
NotifyWebHookTypeFeishuPerson NotifyWebHookType = "feishu_person"
NotifyWebhookTypeFeishuApp NotifyWebHookType = "feishu_app"
NotifyWebHookTypeWechatWork NotifyWebHookType = "wechat"
+ NotifyWebHookTypeMSTeam NotifyWebHookType = "msteams"
NotifyWebHookTypeMail NotifyWebHookType = "mail"
NotifyWebHookTypeWebook NotifyWebHookType = "webhook"
)