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 @@
+
+