Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
790fcdf
feat(workflow): pass through webhook payload to runtime notifications
huanghongbo-hhb May 7, 2026
9b6fa0d
fix(workflow): preserve runtime context job outputs
huanghongbo-hhb May 11, 2026
55e2117
fix(workflow): preserve webhook repo fields across scm providers
huanghongbo-hhb May 12, 2026
11dd783
fix(workflow): keep only payload runtime variables
huanghongbo-hhb Jun 5, 2026
412e26d
support workflow trigger runtime variables
huanghongbo-hhb Jun 16, 2026
87a0649
feat(workflow): add commit sha runtime variable
huanghongbo-hhb Jun 16, 2026
7d49aac
fix dynamic notification recipients
huanghongbo-hhb Jun 16, 2026
7b6a2c4
fix trigger vars and lark hook recipients
huanghongbo-hhb Jun 17, 2026
73f951e
fix payload scope for workflow runtime
huanghongbo-hhb Jun 17, 2026
6c2d37d
fix: allow payload variables in notification recipients
huanghongbo-hhb Jun 17, 2026
bf1fd96
fix: preserve notification dynamic recipients runtime rendering
huanghongbo-hhb Jun 18, 2026
ddae297
fix: preserve notification payload templates at runtime
huanghongbo-hhb Jun 18, 2026
de788d3
fix: send mail to dynamic email recipients
huanghongbo-hhb Jun 23, 2026
9ed0761
fix: resolve workflow notification dynamic recipients
huanghongbo-hhb Jun 23, 2026
5ed0f13
fix: make dingding notifications mention recipients
huanghongbo-hhb Jun 24, 2026
1a2bba7
chore: remove ua migration from pr4667 4.3 backport
huanghongbo-hhb Jun 25, 2026
042ae72
fix: preserve webhook repo context fields in 4.3 backport
huanghongbo-hhb Jun 25, 2026
031e0e3
chore: remove backport test files
huanghongbo-hhb Jun 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package models

import (
"encoding/json"
"fmt"

"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/bsontype"
)

// DynamicRecipients keeps compatibility with the temporary PR schema
// [{"value":"{{.payload.user.email}}","identity_type":"email"}].
type DynamicRecipients []string

type legacyDynamicRecipient struct {
Value string `bson:"value" json:"value"`
IdentityType string `bson:"identity_type" json:"identity_type"`
}

func (r *DynamicRecipients) UnmarshalJSON(data []byte) error {
var recipients []string
if err := json.Unmarshal(data, &recipients); err == nil {
*r = recipients
return nil
}

var legacyRecipients []legacyDynamicRecipient
if err := json.Unmarshal(data, &legacyRecipients); err != nil {
return fmt.Errorf("failed to unmarshal dynamic recipients: %w", err)
}

*r = legacyDynamicRecipientsToStrings(legacyRecipients)
return nil
}

func (r *DynamicRecipients) UnmarshalBSONValue(t bsontype.Type, data []byte) error {
if t == bsontype.Null || t == bsontype.Undefined {
*r = nil
return nil
}

var recipients []string
if err := (bson.RawValue{Type: t, Value: data}).Unmarshal(&recipients); err == nil {
*r = recipients
return nil
}

var legacyRecipients []legacyDynamicRecipient
if err := (bson.RawValue{Type: t, Value: data}).Unmarshal(&legacyRecipients); err != nil {
return fmt.Errorf("failed to unmarshal dynamic recipients: %w", err)
}

*r = legacyDynamicRecipientsToStrings(legacyRecipients)
return nil
}

func legacyDynamicRecipientsToStrings(recipients []legacyDynamicRecipient) []string {
resp := make([]string, 0, len(recipients))
for _, recipient := range recipients {
resp = append(resp, recipient.Value)
}
return resp
}
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,7 @@ type LarkChat struct {
type JobTaskNotificationSpec struct {
WebHookType setting.NotifyWebHookType `bson:"webhook_type" yaml:"webhook_type" json:"webhook_type"`

LarkHookNotificationConfig *LarkHookNotificationConfig `bson:"lark_hook_notification_config,omitempty" yaml:"lark_hook_notification_config,omitempty" json:"lark_hook_notification_config,omitempty"`
LarkGroupNotificationConfig *LarkGroupNotificationConfig `bson:"lark_group_notification_config,omitempty" yaml:"lark_group_notification_config,omitempty" json:"lark_group_notification_config,omitempty"`
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"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -478,14 +478,19 @@ type HookPayload struct {
Owner string `bson:"owner" json:"owner,omitempty"`
Repo string `bson:"repo" json:"repo,omitempty"`
Branch string `bson:"branch" json:"branch,omitempty"`
TargetBranch string `bson:"target_branch" json:"target_branch,omitempty"`
Ref string `bson:"ref" json:"ref,omitempty"`
IsPr bool `bson:"is_pr" json:"is_pr,omitempty"`
CheckRunID int64 `bson:"check_run_id" json:"check_run_id,omitempty"`
MergeRequestID string `bson:"merge_request_id" json:"merge_request_id,omitempty"`
CommitID string `bson:"commit_id" json:"commit_id,omitempty"`
CommitSHA string `bson:"commit_sha" json:"commit_sha,omitempty"`
CommitMessage string `bson:"commit_message" json:"commit_message,omitempty"`
Committer string `bson:"committer" json:"committer,omitempty"`
DeliveryID string `bson:"delivery_id" json:"delivery_id,omitempty"`
CodehostID int `bson:"codehost_id" json:"codehost_id"`
EventType string `bson:"event_type" json:"event_type"`
RawPayload string `bson:"raw_payload" json:"raw_payload,omitempty"`
}

type TargetArgs struct {
Expand Down
60 changes: 36 additions & 24 deletions pkg/microservice/aslan/core/common/repository/models/workflow_v4.go
Original file line number Diff line number Diff line change
Expand Up @@ -1163,12 +1163,12 @@ type NotificationJobSpec struct {

LarkGroupNotificationConfig *LarkGroupNotificationConfig `bson:"lark_group_notification_config,omitempty" yaml:"lark_group_notification_config,omitempty" json:"lark_group_notification_config,omitempty"`
LarkPersonNotificationConfig *LarkPersonNotificationConfig `bson:"lark_person_notification_config,omitempty" yaml:"lark_person_notification_config,omitempty" json:"lark_person_notification_config,omitempty"`
//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"`
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"`

Content string `bson:"content" yaml:"content" json:"content"`
Title string `bson:"title" yaml:"title" json:"title"`
Expand Down Expand Up @@ -1252,6 +1252,10 @@ func (n *NotificationJobSpec) GenerateNewNotifyConfigWithOldData() error {
if n.LarkPersonNotificationConfig == nil {
return fmt.Errorf("lark_person_notification_config cannot be empty for type feishu_person notification")
}
case setting.NotifyWebHookTypeFeishu:
if n.LarkHookNotificationConfig == nil {
return fmt.Errorf("lark_hook_notification_config cannot be empty for type feishu notification")
}
default:
// TODO: this code is commented because of chagee old data. uncomment it if possible
//return fmt.Errorf("unsupported notification type: %s", n.WebHookType)
Expand All @@ -1262,42 +1266,50 @@ func (n *NotificationJobSpec) GenerateNewNotifyConfigWithOldData() error {

// TODO: why is_at_all? it could be done in backend
type LarkGroupNotificationConfig struct {
AppID string `bson:"app_id" json:"app_id" yaml:"app_id"`
Chat *LarkChat `bson:"chat" json:"chat" yaml:"chat"`
AtUsers []*lark.UserInfo `bson:"at_users" json:"at_users" yaml:"at_users"`
IsAtAll bool `bson:"is_at_all" json:"is_at_all" yaml:"is_at_all"`
AppID string `bson:"app_id" json:"app_id" yaml:"app_id"`
Chat *LarkChat `bson:"chat" json:"chat" yaml:"chat"`
AtUsers []*lark.UserInfo `bson:"at_users" json:"at_users" yaml:"at_users"`
DynamicRecipients DynamicRecipients `bson:"dynamic_recipients" json:"dynamic_recipients" yaml:"dynamic_recipients"`
IsAtAll bool `bson:"is_at_all" json:"is_at_all" yaml:"is_at_all"`
}

type LarkPersonNotificationConfig struct {
AppID string `bson:"app_id" json:"app_id" yaml:"app_id"`
TargetUsers []*lark.UserInfo `bson:"target_users" json:"target_users" yaml:"target_users"`
AppID string `bson:"app_id" json:"app_id" yaml:"app_id"`
TargetUsers []*lark.UserInfo `bson:"target_users" json:"target_users" yaml:"target_users"`
DynamicRecipients DynamicRecipients `bson:"dynamic_recipients" json:"dynamic_recipients" yaml:"dynamic_recipients"`
}

type LarkHookNotificationConfig struct {
HookAddress string `bson:"hook_address" json:"hook_address" yaml:"hook_address"`
AtUsers []string `bson:"at_users" json:"at_users" yaml:"at_users"`
IsAtAll bool `bson:"is_at_all" json:"is_at_all" yaml:"is_at_all"`
AppID string `bson:"app_id" json:"app_id" yaml:"app_id"`
HookAddress string `bson:"hook_address" json:"hook_address" yaml:"hook_address"`
AtUsers []string `bson:"at_users" json:"at_users" yaml:"at_users"`
DynamicRecipients DynamicRecipients `bson:"dynamic_recipients" json:"dynamic_recipients" yaml:"dynamic_recipients"`
IsAtAll bool `bson:"is_at_all" json:"is_at_all" yaml:"is_at_all"`
}

type WechatNotificationConfig struct {
HookAddress string `bson:"hook_address" json:"hook_address" yaml:"hook_address"`
AtUsers []string `bson:"at_users" json:"at_users" yaml:"at_users"`
IsAtAll bool `bson:"is_at_all" json:"is_at_all" yaml:"is_at_all"`
HookAddress string `bson:"hook_address" json:"hook_address" yaml:"hook_address"`
AtUsers []string `bson:"at_users" json:"at_users" yaml:"at_users"`
DynamicRecipients DynamicRecipients `bson:"dynamic_recipients" json:"dynamic_recipients" yaml:"dynamic_recipients"`
IsAtAll bool `bson:"is_at_all" json:"is_at_all" yaml:"is_at_all"`
}

type DingDingNotificationConfig struct {
HookAddress string `bson:"hook_address" json:"hook_address" yaml:"hook_address"`
AtMobiles []string `bson:"at_mobiles" json:"at_mobiles" yaml:"at_mobiles"`
IsAtAll bool `bson:"is_at_all" json:"is_at_all" yaml:"is_at_all"`
HookAddress string `bson:"hook_address" json:"hook_address" yaml:"hook_address"`
AtMobiles []string `bson:"at_mobiles" json:"at_mobiles" yaml:"at_mobiles"`
DynamicRecipients DynamicRecipients `bson:"dynamic_recipients" json:"dynamic_recipients" yaml:"dynamic_recipients"`
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"`
HookAddress string `bson:"hook_address" json:"hook_address" yaml:"hook_address"`
AtEmails []string `bson:"at_emails" json:"at_emails" yaml:"at_emails"`
DynamicRecipients DynamicRecipients `bson:"dynamic_recipients" json:"dynamic_recipients" yaml:"dynamic_recipients"`
}

type MailNotificationConfig struct {
TargetUsers []*User `bson:"target_users" json:"target_users" yaml:"target_users"`
TargetUsers []*User `bson:"target_users" json:"target_users" yaml:"target_users"`
DynamicRecipients DynamicRecipients `bson:"dynamic_recipients" json:"dynamic_recipients" yaml:"dynamic_recipients"`
}

type WebhookNotificationConfig struct {
Expand Down
Loading
Loading