Fix incompleted commit status events

This commit is contained in:
Lunny Xiao 2024-12-17 18:58:23 -08:00
parent 2d7e6e9482
commit a9080fabe4
No known key found for this signature in database
GPG Key ID: C3B7C91B632F738A
18 changed files with 110 additions and 9 deletions

View File

@ -515,7 +515,7 @@ type CommitStatusPayload struct {
Repo *Repository `json:"repository"` Repo *Repository `json:"repository"`
Sender *User `json:"sender"` Sender *User `json:"sender"`
SHA string `json:"sha"` SHA string `json:"sha"`
State string `json:"state"` State CommitStatusState `json:"state"`
TargetURL string `json:"target_url"` TargetURL string `json:"target_url"`
// swagger:strfmt date-time // swagger:strfmt date-time
UpdatedAt *time.Time `json:"updated_at"` UpdatedAt *time.Time `json:"updated_at"`

View File

@ -26,6 +26,7 @@ type HookEvents struct {
Repository bool `json:"repository"` Repository bool `json:"repository"`
Release bool `json:"release"` Release bool `json:"release"`
Package bool `json:"package"` Package bool `json:"package"`
CommitStatus bool `json:"commit_status"`
} }
// HookEvent represents events that will delivery hook. // HookEvent represents events that will delivery hook.

View File

@ -2362,6 +2362,8 @@ settings.event_pull_request_approvals = Pull Request Approvals
settings.event_pull_request_merge = Pull Request Merge settings.event_pull_request_merge = Pull Request Merge
settings.event_package = Package settings.event_package = Package
settings.event_package_desc = Package created or deleted in a repository. 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 = Branch filter
settings.branch_filter_desc = Branch whitelist for push, branch creation and branch deletion events, specified as glob pattern. If empty or <code>*</code>, events for all branches are reported. See <a href="%[1]s">%[2]s</a> documentation for syntax. Examples: <code>master</code>, <code>{master,release*}</code>. settings.branch_filter_desc = Branch whitelist for push, branch creation and branch deletion events, specified as glob pattern. If empty or <code>*</code>, events for all branches are reported. See <a href="%[1]s">%[2]s</a> documentation for syntax. Examples: <code>master</code>, <code>{master,release*}</code>.
settings.authorization_header = Authorization Header settings.authorization_header = Authorization Header

View File

@ -184,6 +184,7 @@ func ParseHookEvent(form forms.WebhookForm) *webhook_module.HookEvent {
Wiki: form.Wiki, Wiki: form.Wiki,
Repository: form.Repository, Repository: form.Repository,
Package: form.Package, Package: form.Package,
CommitStatus: form.CommitStatus,
}, },
BranchFilter: form.BranchFilter, BranchFilter: form.BranchFilter,
} }

View File

@ -263,6 +263,7 @@ type WebhookForm struct {
Wiki bool Wiki bool
Repository bool Repository bool
Package bool Package bool
CommitStatus bool
Active bool Active bool
BranchFilter string `binding:"GlobPattern"` BranchFilter string `binding:"GlobPattern"`
AuthorizationHeader string AuthorizationHeader string

View File

@ -170,6 +170,12 @@ func (dc dingtalkConvertor) Package(p *api.PackagePayload) (DingtalkPayload, err
return createDingtalkPayload(text, text, "view package", p.Package.HTMLURL), nil 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 { func createDingtalkPayload(title, text, singleTitle, singleURL string) DingtalkPayload {
return DingtalkPayload{ return DingtalkPayload{
MsgType: "actionCard", MsgType: "actionCard",

View File

@ -265,6 +265,12 @@ func (d discordConvertor) Package(p *api.PackagePayload) (DiscordPayload, error)
return d.createPayload(p.Sender, text, "", p.Package.HTMLURL, color), nil 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) { func newDiscordRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) {
meta := &DiscordMeta{} meta := &DiscordMeta{}
if err := json.Unmarshal([]byte(w.Meta), meta); err != nil { if err := json.Unmarshal([]byte(w.Meta), meta); err != nil {

View File

@ -166,6 +166,12 @@ func (fc feishuConvertor) Package(p *api.PackagePayload) (FeishuPayload, error)
return newFeishuTextPayload(text), nil 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) { func newFeishuRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) {
var pc payloadConvertor[FeishuPayload] = feishuConvertor{} var pc payloadConvertor[FeishuPayload] = feishuConvertor{}
return newJSONRequest(pc, w, t, true) return newJSONRequest(pc, w, t, true)

View File

@ -28,6 +28,10 @@ func htmlLinkFormatter(url, text string) string {
return fmt.Sprintf(`<a href="%s">%s</a>`, html.EscapeString(url), html.EscapeString(text)) return fmt.Sprintf(`<a href="%s">%s</a>`, 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 // getPullRequestInfo gets the information for a pull request
func getPullRequestInfo(p *api.PullRequestPayload) (title, link, by, operator, operateResult, assignees string) { 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) 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 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 // ToHook convert models.Webhook to api.Hook
// This function is not part of the convert package to prevent an import cycle // 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) { func ToHook(repoLink string, w *webhook_model.Webhook) (*api.Hook, error) {

View File

@ -240,6 +240,12 @@ func (m matrixConvertor) Package(p *api.PackagePayload) (MatrixPayload, error) {
return m.newPayload(text) 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(`<a [^>]*?href="([^">]*?)">(.*?)</a>`) var urlRegex = regexp.MustCompile(`<a [^>]*?href="([^">]*?)">(.*?)</a>`)
func getMessageBody(htmlText string) string { func getMessageBody(htmlText string) string {

View File

@ -303,6 +303,20 @@ func (m msteamsConvertor) Package(p *api.PackagePayload) (MSTeamsPayload, error)
), nil ), 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 { func createMSTeamsPayload(r *api.Repository, s *api.User, title, text, actionTarget string, color int, fact *MSTeamsFact) MSTeamsPayload {
facts := make([]MSTeamsFact, 0, 2) facts := make([]MSTeamsFact, 0, 2)
if r != nil { if r != nil {

View File

@ -876,7 +876,7 @@ func (m *webhookNotifier) CreateCommitStatus(ctx context.Context, repo *repo_mod
Description: status.Description, Description: status.Description,
ID: status.ID, ID: status.ID,
SHA: commit.Sha1, SHA: commit.Sha1,
State: status.State.String(), State: status.State,
TargetURL: status.TargetURL, TargetURL: status.TargetURL,
Commit: apiCommit, Commit: apiCommit,

View File

@ -110,6 +110,10 @@ func (pc packagistConvertor) Package(_ *api.PackagePayload) (PackagistPayload, e
return PackagistPayload{}, nil 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) { func newPackagistRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) {
meta := &PackagistMeta{} meta := &PackagistMeta{}
if err := json.Unmarshal([]byte(w.Meta), meta); err != nil { if err := json.Unmarshal([]byte(w.Meta), meta); err != nil {

View File

@ -28,6 +28,7 @@ type payloadConvertor[T any] interface {
Release(*api.ReleasePayload) (T, error) Release(*api.ReleasePayload) (T, error)
Wiki(*api.WikiPayload) (T, error) Wiki(*api.WikiPayload) (T, error)
Package(*api.PackagePayload) (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) { 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) return convertUnmarshalledJSON(rc.Wiki, data)
case webhook_module.HookEventPackage: case webhook_module.HookEventPackage:
return convertUnmarshalledJSON(rc.Package, data) return convertUnmarshalledJSON(rc.Package, data)
case webhook_module.HookEventStatus:
return convertUnmarshalledJSON(rc.CommitStatus, data)
} }
return t, fmt.Errorf("newPayload unsupported event: %s", event) return t, fmt.Errorf("newPayload unsupported event: %s", event)
} }

View File

@ -264,6 +264,12 @@ func (s slackConvertor) Repository(p *api.RepositoryPayload) (SlackPayload, erro
return s.createPayload(text, nil), nil 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 { func (s slackConvertor) createPayload(text string, attachments []SlackAttachment) SlackPayload {
return SlackPayload{ return SlackPayload{
Channel: s.Channel, Channel: s.Channel,

View File

@ -174,6 +174,12 @@ func (t telegramConvertor) Package(p *api.PackagePayload) (TelegramPayload, erro
return createTelegramPayloadHTML(text), nil 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 { func createTelegramPayloadHTML(msgHTML string) TelegramPayload {
// https://core.telegram.org/bots/api#formatting-options // https://core.telegram.org/bots/api#formatting-options
return TelegramPayload{ return TelegramPayload{

View File

@ -175,6 +175,12 @@ func (wc wechatworkConvertor) Package(p *api.PackagePayload) (WechatworkPayload,
return newWechatworkMarkdownPayload(text), nil 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) { func newWechatworkRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) {
var pc payloadConvertor[WechatworkPayload] = wechatworkConvertor{} var pc payloadConvertor[WechatworkPayload] = wechatworkConvertor{}
return newJSONRequest(pc, w, t, true) return newJSONRequest(pc, w, t, true)

View File

@ -109,6 +109,17 @@
</div> </div>
</div> </div>
<!-- CommitStatus -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input name="commit_status" type="checkbox" {{if .Webhook.CommitStatus}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.settings.event_commitstatus"}}</label>
<span class="help">{{ctx.Locale.Tr "repo.settings.event_commitstatus_desc"}}</span>
</div>
</div>
</div>
<!-- Issue Events --> <!-- Issue Events -->
<div class="fourteen wide column"> <div class="fourteen wide column">
<label>{{ctx.Locale.Tr "repo.settings.event_header_issue"}}</label> <label>{{ctx.Locale.Tr "repo.settings.event_header_issue"}}</label>