package handler import ( "log" "net/http" "strconv" "time" "github.com/gin-gonic/gin" "flowstack/internal/crypto" "flowstack/internal/database" "flowstack/internal/lark" "flowstack/internal/model" ) // notifyLarkRelease 运行结束后推送飞书发布结果卡片: // Webhook 优先取流水线自带 notifyWebhookURL,否则用全局设置(需启用)。 func notifyLarkRelease(run model.PipelineRun, status string) { if status != "success" && status != "failed" && status != "cancelled" { return } var p model.Pipeline database.DB.First(&p, run.PipelineID) var s model.SystemSetting database.DB.First(&s, 1) webhook := p.NotifyWebhook if webhook == "" { if !s.LarkEnabled || s.LarkWebhook == "" { return } webhook = s.LarkWebhook } secret := "" if s.LarkSecret != "" && crypto.IsEncrypted(s.LarkSecret) { if plain, err := crypto.DecryptField(s.LarkSecret); err == nil { secret = plain } } build := run.RunID if run.BuildNumber > 0 { build = "#" + strconv.Itoa(run.BuildNumber) } card := lark.BuildReleaseCard(lark.ReleaseCardParams{ AppName: run.PipelineName, Branch: run.Branch, Build: build, Status: status, Time: time.Now().Format("2006-01-02 15:04:05"), BuildURL: run.ExternalURL, }) if err := lark.Send(webhook, secret, card); err != nil { log.Printf("[lark] 发布通知发送失败 (%s): %v", run.RunID, err) } else { log.Printf("[lark] 发布通知已发送: %s %s → %s", run.PipelineName, status, webhook) } } // TestLark POST /api/settings/test-lark —— 用已保存配置发测试卡片 func TestLark(c *gin.Context) { var s model.SystemSetting if err := database.DB.First(&s, 1).Error; err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "请先保存设置"}) return } webhook := c.Query("webhook") if webhook == "" { webhook = s.LarkWebhook } if webhook == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "未配置飞书 Webhook"}) return } secret := "" if s.LarkSecret != "" && crypto.IsEncrypted(s.LarkSecret) { if plain, err := crypto.DecryptField(s.LarkSecret); err == nil { secret = plain } } card := lark.BuildReleaseCard(lark.ReleaseCardParams{ AppName: "flowstack-test", Branch: "test", Build: "#0", Status: "success", Time: time.Now().Format("2006-01-02 15:04:05"), BuildURL: "", }) if err := lark.Send(webhook, secret, card); err != nil { c.JSON(http.StatusOK, gin.H{"success": false, "message": "发送失败: " + err.Error()}) return } c.JSON(http.StatusOK, gin.H{"success": true, "message": "测试卡片已发送到群"}) }