From e7a3bf76df36ce04c851c249005982d9a431f317 Mon Sep 17 00:00:00 2001 From: shaxiaozz <2309108459@qq.com> Date: Wed, 31 Dec 2025 14:41:00 +0800 Subject: [PATCH 1/4] feat: Add Lark webhook notification medium --- services/tasks/alert.go | 78 ++++++++++++++++++++++++++++++ services/tasks/templates/lark.tmpl | 26 ++++++++++ util/config.go | 4 +- 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 services/tasks/templates/lark.tmpl 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/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"` From fa7a6a3553de29b31158b216c881fe9bab33639a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=BB=E7=AC=91zz?= <43721571+shaxiaozz@users.noreply.github.com> Date: Fri, 27 Feb 2026 10:56:54 +0800 Subject: [PATCH 2/4] Add Lark alert notification to TaskRunner --- services/tasks/TaskRunner_logging.go | 1 + 1 file changed, 1 insertion(+) diff --git a/services/tasks/TaskRunner_logging.go b/services/tasks/TaskRunner_logging.go index 0dca84e7d..b29161f51 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() + tr.sendLarkAlert() } for _, l := range t.statusListeners { From 286142788d1e9f94f8886ac53a846e30e460fdb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=BB=E7=AC=91zz?= <43721571+shaxiaozz@users.noreply.github.com> Date: Fri, 27 Feb 2026 10:57:34 +0800 Subject: [PATCH 3/4] Fix Lark alert sending method call --- services/tasks/TaskRunner_logging.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/tasks/TaskRunner_logging.go b/services/tasks/TaskRunner_logging.go index b29161f51..bbd7b9d84 100644 --- a/services/tasks/TaskRunner_logging.go +++ b/services/tasks/TaskRunner_logging.go @@ -128,7 +128,7 @@ func (t *TaskRunner) SetStatus(status task_logger.TaskStatus) { t.sendMicrosoftTeamsAlert() t.sendDingTalkAlert() t.sendGotifyAlert() - tr.sendLarkAlert() + t.sendLarkAlert() } for _, l := range t.statusListeners { From 466e933f5f2c4bdf6b44298ee4ee15f84d264638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=BB=E7=AC=91zz?= <43721571+shaxiaozz@users.noreply.github.com> Date: Fri, 27 Feb 2026 10:57:57 +0800 Subject: [PATCH 4/4] Add Lark alert sending functionality --- services/tasks/alert_test_sender.go | 1 + 1 file changed, 1 insertion(+) 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 }