diff --git a/services/tasks/TaskRunner_logging.go b/services/tasks/TaskRunner_logging.go index 0dca84e7d..bbd7b9d84 100644 --- a/services/tasks/TaskRunner_logging.go +++ b/services/tasks/TaskRunner_logging.go @@ -128,6 +128,7 @@ func (t *TaskRunner) SetStatus(status task_logger.TaskStatus) { t.sendMicrosoftTeamsAlert() t.sendDingTalkAlert() t.sendGotifyAlert() + t.sendLarkAlert() } for _, l := range t.statusListeners { diff --git a/services/tasks/alert.go b/services/tasks/alert.go index c1b088cfb..4a233f97a 100644 --- a/services/tasks/alert.go +++ b/services/tasks/alert.go @@ -504,6 +504,69 @@ func (t *TaskRunner) sendGotifyAlert() { } } +func (t *TaskRunner) sendLarkAlert() { + if !util.Config.LarkAlert || !t.alert { + return + } + + if t.Template.SuppressSuccessAlerts && t.Task.Status == task_logger.TaskSuccessStatus { + return + } + + body := bytes.NewBufferString("") + author, version := t.alertInfos() + + alert := Alert{ + Name: t.Template.Name, + Author: author, + Color: t.alertColor("lark"), + Task: alertTask{ + ID: strconv.Itoa(t.Task.ID), + URL: t.taskLink(), + Result: t.Task.Status.Format(), + Version: version, + Desc: t.Task.Message, + }, + } + + tpl, err := template.ParseFS(templates, "templates/lark.tmpl") + + if err != nil { + t.Log("Can't parse lark alert template!") + panic(err) + } + + if err := tpl.Execute(body, alert); err != nil { + t.Log("Can't generate lark alert template!") + panic(err) + } + + if body.Len() == 0 { + t.Log("Buffer for lark alert is empty") + return + } + + t.Log("Attempting to send lark alert") + + resp, err := http.Post( + util.Config.LarkUrl, + "application/json", + body, + ) + + if err != nil { + t.Log("Can't send lark alert! Error: " + err.Error()) + } else if resp.StatusCode != 200 { + t.Log("Can't send lark alert! Response code: " + strconv.Itoa(resp.StatusCode)) + } else { + t.Log("Sent successfully lark alert") + } + + if resp != nil { + defer resp.Body.Close() //nolint:errcheck + } +} + func (t *TaskRunner) alertInfos() (string, string) { version := "" @@ -567,6 +630,21 @@ func (t *TaskRunner) alertColor(kind string) string { case task_logger.TaskStoppedStatus: return "#5B5B5B" } + case "lark": + switch t.Task.Status { + case task_logger.TaskSuccessStatus: + return "green" + case task_logger.TaskFailStatus: + return "red" + case task_logger.TaskRunningStatus: + return "blue" + case task_logger.TaskWaitingStatus: + return "yellow" + case task_logger.TaskStoppingStatus: + return "grey" + case task_logger.TaskStoppedStatus: + return "black" + } } return "" diff --git a/services/tasks/alert_test_sender.go b/services/tasks/alert_test_sender.go index 304e2ac71..83c50bc7b 100644 --- a/services/tasks/alert_test_sender.go +++ b/services/tasks/alert_test_sender.go @@ -47,6 +47,7 @@ func SendProjectTestAlerts(project db.Project, store db.Store) (err error) { tr.sendDingTalkAlert() tr.sendGotifyAlert() tr.sendMailAlert() + tr.sendLarkAlert() return } diff --git a/services/tasks/templates/lark.tmpl b/services/tasks/templates/lark.tmpl new file mode 100644 index 000000000..ee72c6b58 --- /dev/null +++ b/services/tasks/templates/lark.tmpl @@ -0,0 +1,26 @@ + { + "msg_type": "interactive", + "card": { + "header": { + "title": { + "tag": "plain_text", + "content": "Task: {{ .Name }}" + }, + "template": "{{ .Color }}" + }, + "elements": [ + { + "tag": "div", + "fields": [ + { + "is_short": true, + "text": { + "tag": "lark_md", + "content": "**Execution : ** {{ .Task.ID }} \n**Status: **{{ .Task.Result }} \n**Author: **{{ .Author }} \n{{ if .Task.Version }}**Version: **{{ .Task.Version }} \n{{ end }}[Task Link]({{ .Task.URL }})" + } + } + ] + } + ] + } + } \ No newline at end of file diff --git a/util/config.go b/util/config.go index fa725bbf0..5188b0377 100644 --- a/util/config.go +++ b/util/config.go @@ -279,7 +279,7 @@ type ConfigType struct { LdapMappings *LdapMappings `json:"ldap_mappings,omitempty"` LdapNeedTLS bool `json:"ldap_needtls,omitempty" env:"SEMAPHORE_LDAP_NEEDTLS"` - // Telegram, Slack, Rocket.Chat, Microsoft Teams, DingTalk, and Gotify alerting + // Telegram, Slack, Rocket.Chat, Microsoft Teams, DingTalk, Gotify and Lark alerting TelegramAlert bool `json:"telegram_alert,omitempty" env:"SEMAPHORE_TELEGRAM_ALERT"` TelegramChat string `json:"telegram_chat,omitempty" env:"SEMAPHORE_TELEGRAM_CHAT"` TelegramToken string `json:"telegram_token,omitempty" env:"SEMAPHORE_TELEGRAM_TOKEN"` @@ -294,6 +294,8 @@ type ConfigType struct { GotifyAlert bool `json:"gotify_alert,omitempty" env:"SEMAPHORE_GOTIFY_ALERT"` GotifyUrl string `json:"gotify_url,omitempty" env:"SEMAPHORE_GOTIFY_URL"` GotifyToken string `json:"gotify_token,omitempty" env:"SEMAPHORE_GOTIFY_TOKEN"` + LarkAlert bool `json:"lark_alert,omitempty" env:"SEMAPHORE_LARK_ALERT"` + LarkUrl string `json:"lark_url,omitempty" env:"SEMAPHORE_LARK_URL"` // oidc settings OidcProviders map[string]OidcProvider `json:"oidc_providers,omitempty" env:"SEMAPHORE_OIDC_PROVIDERS"`