From a9080fabe4920dca1fdf84591a90b4f642ff72c7 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 17 Dec 2024 18:58:23 -0800 Subject: [PATCH] Fix incompleted commit status events --- modules/structs/hook.go | 16 +++++++------- modules/webhook/structs.go | 1 + options/locale/locale_en-US.ini | 2 ++ routers/web/repo/setting/webhook.go | 1 + services/forms/repo_form.go | 1 + services/webhook/dingtalk.go | 6 +++++ services/webhook/discord.go | 6 +++++ services/webhook/feishu.go | 6 +++++ services/webhook/general.go | 22 +++++++++++++++++++ services/webhook/matrix.go | 6 +++++ services/webhook/msteams.go | 14 ++++++++++++ services/webhook/notifier.go | 2 +- services/webhook/packagist.go | 4 ++++ services/webhook/payloader.go | 3 +++ services/webhook/slack.go | 6 +++++ services/webhook/telegram.go | 6 +++++ services/webhook/wechatwork.go | 6 +++++ templates/repo/settings/webhook/settings.tmpl | 11 ++++++++++ 18 files changed, 110 insertions(+), 9 deletions(-) diff --git a/modules/structs/hook.go b/modules/structs/hook.go index ce5742e5c7c..e8d09f85959 100644 --- a/modules/structs/hook.go +++ b/modules/structs/hook.go @@ -509,14 +509,14 @@ type CommitStatusPayload struct { Commit *PayloadCommit `json:"commit"` Context string `json:"context"` // swagger:strfmt date-time - CreatedAt time.Time `json:"created_at"` - Description string `json:"description"` - ID int64 `json:"id"` - Repo *Repository `json:"repository"` - Sender *User `json:"sender"` - SHA string `json:"sha"` - State string `json:"state"` - TargetURL string `json:"target_url"` + CreatedAt time.Time `json:"created_at"` + Description string `json:"description"` + ID int64 `json:"id"` + Repo *Repository `json:"repository"` + Sender *User `json:"sender"` + SHA string `json:"sha"` + State CommitStatusState `json:"state"` + TargetURL string `json:"target_url"` // swagger:strfmt date-time UpdatedAt *time.Time `json:"updated_at"` } diff --git a/modules/webhook/structs.go b/modules/webhook/structs.go index 927a91a74c5..73399da911a 100644 --- a/modules/webhook/structs.go +++ b/modules/webhook/structs.go @@ -26,6 +26,7 @@ type HookEvents struct { Repository bool `json:"repository"` Release bool `json:"release"` Package bool `json:"package"` + CommitStatus bool `json:"commit_status"` } // HookEvent represents events that will delivery hook. diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 92ce4f2db9f..66b30101d2f 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2362,6 +2362,8 @@ settings.event_pull_request_approvals = Pull Request Approvals settings.event_pull_request_merge = Pull Request Merge settings.event_package = Package settings.event_package_desc = Package created or deleted in a repository. +settings.event_commitstatus = Commit Status +settings.event_commitstatus_desc = Commit status updated. settings.branch_filter = Branch filter settings.branch_filter_desc = Branch whitelist for push, branch creation and branch deletion events, specified as glob pattern. If empty or *, events for all branches are reported. See %[2]s documentation for syntax. Examples: master, {master,release*}. settings.authorization_header = Authorization Header diff --git a/routers/web/repo/setting/webhook.go b/routers/web/repo/setting/webhook.go index 8d548c4e3d1..0376287ef6f 100644 --- a/routers/web/repo/setting/webhook.go +++ b/routers/web/repo/setting/webhook.go @@ -184,6 +184,7 @@ func ParseHookEvent(form forms.WebhookForm) *webhook_module.HookEvent { Wiki: form.Wiki, Repository: form.Repository, Package: form.Package, + CommitStatus: form.CommitStatus, }, BranchFilter: form.BranchFilter, } diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index 7647c74e465..4819c9e92a7 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -263,6 +263,7 @@ type WebhookForm struct { Wiki bool Repository bool Package bool + CommitStatus bool Active bool BranchFilter string `binding:"GlobPattern"` AuthorizationHeader string diff --git a/services/webhook/dingtalk.go b/services/webhook/dingtalk.go index e382f5a9df7..7a3c40b57e7 100644 --- a/services/webhook/dingtalk.go +++ b/services/webhook/dingtalk.go @@ -170,6 +170,12 @@ func (dc dingtalkConvertor) Package(p *api.PackagePayload) (DingtalkPayload, err return createDingtalkPayload(text, text, "view package", p.Package.HTMLURL), nil } +func (dc dingtalkConvertor) CommitStatus(p *api.CommitStatusPayload) (DingtalkPayload, error) { + text, _ := getCommitStatusPayloadInfo(p, noneLinkFormatter, true) + + return createDingtalkPayload(text, text, "view commit status", p.TargetURL), nil +} + func createDingtalkPayload(title, text, singleTitle, singleURL string) DingtalkPayload { return DingtalkPayload{ MsgType: "actionCard", diff --git a/services/webhook/discord.go b/services/webhook/discord.go index c562d981680..2e1f0aba459 100644 --- a/services/webhook/discord.go +++ b/services/webhook/discord.go @@ -265,6 +265,12 @@ func (d discordConvertor) Package(p *api.PackagePayload) (DiscordPayload, error) return d.createPayload(p.Sender, text, "", p.Package.HTMLURL, color), nil } +func (d discordConvertor) CommitStatus(p *api.CommitStatusPayload) (DiscordPayload, error) { + text, color := getCommitStatusPayloadInfo(p, noneLinkFormatter, true) + + return d.createPayload(p.Sender, "view commit status", text, p.TargetURL, color), nil +} + func newDiscordRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) { meta := &DiscordMeta{} if err := json.Unmarshal([]byte(w.Meta), meta); err != nil { diff --git a/services/webhook/feishu.go b/services/webhook/feishu.go index 7ca7d1cf5f3..917bfc6247c 100644 --- a/services/webhook/feishu.go +++ b/services/webhook/feishu.go @@ -166,6 +166,12 @@ func (fc feishuConvertor) Package(p *api.PackagePayload) (FeishuPayload, error) return newFeishuTextPayload(text), nil } +func (fc feishuConvertor) CommitStatus(p *api.CommitStatusPayload) (FeishuPayload, error) { + text, _ := getCommitStatusPayloadInfo(p, markdownFormatter, true) + + return newFeishuTextPayload(text), nil +} + func newFeishuRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) { var pc payloadConvertor[FeishuPayload] = feishuConvertor{} return newJSONRequest(pc, w, t, true) diff --git a/services/webhook/general.go b/services/webhook/general.go index dde43bb3495..58cf45b9524 100644 --- a/services/webhook/general.go +++ b/services/webhook/general.go @@ -28,6 +28,10 @@ func htmlLinkFormatter(url, text string) string { return fmt.Sprintf(`%s`, html.EscapeString(url), html.EscapeString(text)) } +func markdownFormatter(url, text string) string { + return fmt.Sprintf("[%s](%s)", text, url) +} + // getPullRequestInfo gets the information for a pull request func getPullRequestInfo(p *api.PullRequestPayload) (title, link, by, operator, operateResult, assignees string) { title = fmt.Sprintf("[PullRequest-%s #%d]: %s\n%s", p.Repository.FullName, p.PullRequest.Index, p.Action, p.PullRequest.Title) @@ -307,6 +311,24 @@ func getPackagePayloadInfo(p *api.PackagePayload, linkFormatter linkFormatter, w return text, color } +func getCommitStatusPayloadInfo(p *api.CommitStatusPayload, linkFormatter linkFormatter, _ bool) (string, int) { + refLink := linkFormatter(p.Commit.URL, p.Commit.ID[:10]) + var color int + switch p.State { + case api.CommitStatusSuccess: + color = greenColor + case api.CommitStatusPending: + color = greyColor + case api.CommitStatusWarning: + color = yellowColor + default: + color = redColor + } + + repoLink := linkFormatter(p.Repo.HTMLURL, p.Repo.FullName) + return fmt.Sprintf("%s Commit %s status changed to %s", repoLink, refLink, p.State.String()), color +} + // ToHook convert models.Webhook to api.Hook // This function is not part of the convert package to prevent an import cycle func ToHook(repoLink string, w *webhook_model.Webhook) (*api.Hook, error) { diff --git a/services/webhook/matrix.go b/services/webhook/matrix.go index 5e9f808d8b6..abbbc914938 100644 --- a/services/webhook/matrix.go +++ b/services/webhook/matrix.go @@ -240,6 +240,12 @@ func (m matrixConvertor) Package(p *api.PackagePayload) (MatrixPayload, error) { return m.newPayload(text) } +func (m matrixConvertor) CommitStatus(p *api.CommitStatusPayload) (MatrixPayload, error) { + text, _ := getCommitStatusPayloadInfo(p, noneLinkFormatter, true) + + return m.newPayload(text) +} + var urlRegex = regexp.MustCompile(`]*?href="([^">]*?)">(.*?)`) func getMessageBody(htmlText string) string { diff --git a/services/webhook/msteams.go b/services/webhook/msteams.go index 7ef96ffa273..b970f123f7f 100644 --- a/services/webhook/msteams.go +++ b/services/webhook/msteams.go @@ -303,6 +303,20 @@ func (m msteamsConvertor) Package(p *api.PackagePayload) (MSTeamsPayload, error) ), nil } +func (m msteamsConvertor) CommitStatus(p *api.CommitStatusPayload) (MSTeamsPayload, error) { + text, color := getCommitStatusPayloadInfo(p, noneLinkFormatter, true) + + return createMSTeamsPayload( + p.Repo, + p.Sender, + text, + "", + p.Commit.URL, + color, + &MSTeamsFact{"CommitStatus:", p.Commit.ID}, + ), nil +} + func createMSTeamsPayload(r *api.Repository, s *api.User, title, text, actionTarget string, color int, fact *MSTeamsFact) MSTeamsPayload { facts := make([]MSTeamsFact, 0, 2) if r != nil { diff --git a/services/webhook/notifier.go b/services/webhook/notifier.go index cc263947e9b..9c3d6490dea 100644 --- a/services/webhook/notifier.go +++ b/services/webhook/notifier.go @@ -876,7 +876,7 @@ func (m *webhookNotifier) CreateCommitStatus(ctx context.Context, repo *repo_mod Description: status.Description, ID: status.ID, SHA: commit.Sha1, - State: status.State.String(), + State: status.State, TargetURL: status.TargetURL, Commit: apiCommit, diff --git a/services/webhook/packagist.go b/services/webhook/packagist.go index 4d809ab3a6a..f6b1b93b1bb 100644 --- a/services/webhook/packagist.go +++ b/services/webhook/packagist.go @@ -110,6 +110,10 @@ func (pc packagistConvertor) Package(_ *api.PackagePayload) (PackagistPayload, e return PackagistPayload{}, nil } +func (pc packagistConvertor) CommitStatus(p *api.CommitStatusPayload) (PackagistPayload, error) { + return PackagistPayload{}, nil +} + func newPackagistRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) { meta := &PackagistMeta{} if err := json.Unmarshal([]byte(w.Meta), meta); err != nil { diff --git a/services/webhook/payloader.go b/services/webhook/payloader.go index ab280a25b66..1d2f8993fac 100644 --- a/services/webhook/payloader.go +++ b/services/webhook/payloader.go @@ -28,6 +28,7 @@ type payloadConvertor[T any] interface { Release(*api.ReleasePayload) (T, error) Wiki(*api.WikiPayload) (T, error) Package(*api.PackagePayload) (T, error) + CommitStatus(*api.CommitStatusPayload) (T, error) } func convertUnmarshalledJSON[T, P any](convert func(P) (T, error), data []byte) (t T, err error) { @@ -77,6 +78,8 @@ func newPayload[T any](rc payloadConvertor[T], data []byte, event webhook_module return convertUnmarshalledJSON(rc.Wiki, data) case webhook_module.HookEventPackage: return convertUnmarshalledJSON(rc.Package, data) + case webhook_module.HookEventStatus: + return convertUnmarshalledJSON(rc.CommitStatus, data) } return t, fmt.Errorf("newPayload unsupported event: %s", event) } diff --git a/services/webhook/slack.go b/services/webhook/slack.go index c905e7a89f4..985830d0a35 100644 --- a/services/webhook/slack.go +++ b/services/webhook/slack.go @@ -264,6 +264,12 @@ func (s slackConvertor) Repository(p *api.RepositoryPayload) (SlackPayload, erro return s.createPayload(text, nil), nil } +func (s slackConvertor) CommitStatus(p *api.CommitStatusPayload) (SlackPayload, error) { + text, _ := getCommitStatusPayloadInfo(p, noneLinkFormatter, true) + + return s.createPayload(text, nil), nil +} + func (s slackConvertor) createPayload(text string, attachments []SlackAttachment) SlackPayload { return SlackPayload{ Channel: s.Channel, diff --git a/services/webhook/telegram.go b/services/webhook/telegram.go index e54d6f2947d..c9967210859 100644 --- a/services/webhook/telegram.go +++ b/services/webhook/telegram.go @@ -174,6 +174,12 @@ func (t telegramConvertor) Package(p *api.PackagePayload) (TelegramPayload, erro return createTelegramPayloadHTML(text), nil } +func (t telegramConvertor) CommitStatus(p *api.CommitStatusPayload) (TelegramPayload, error) { + text, _ := getCommitStatusPayloadInfo(p, noneLinkFormatter, true) + + return createTelegramPayloadHTML(text), nil +} + func createTelegramPayloadHTML(msgHTML string) TelegramPayload { // https://core.telegram.org/bots/api#formatting-options return TelegramPayload{ diff --git a/services/webhook/wechatwork.go b/services/webhook/wechatwork.go index 1d8c1d7dacd..80aad955946 100644 --- a/services/webhook/wechatwork.go +++ b/services/webhook/wechatwork.go @@ -175,6 +175,12 @@ func (wc wechatworkConvertor) Package(p *api.PackagePayload) (WechatworkPayload, return newWechatworkMarkdownPayload(text), nil } +func (wc wechatworkConvertor) CommitStatus(p *api.CommitStatusPayload) (WechatworkPayload, error) { + text, _ := getCommitStatusPayloadInfo(p, noneLinkFormatter, true) + + return newWechatworkMarkdownPayload(text), nil +} + func newWechatworkRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) { var pc payloadConvertor[WechatworkPayload] = wechatworkConvertor{} return newJSONRequest(pc, w, t, true) diff --git a/templates/repo/settings/webhook/settings.tmpl b/templates/repo/settings/webhook/settings.tmpl index cf3b0eb0530..3607bb2c0db 100644 --- a/templates/repo/settings/webhook/settings.tmpl +++ b/templates/repo/settings/webhook/settings.tmpl @@ -109,6 +109,17 @@ + +
+
+
+ + + {{ctx.Locale.Tr "repo.settings.event_commitstatus_desc"}} +
+
+
+