diff options
author | delvh <leon@kske.dev> | 2023-01-01 16:23:15 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-01 23:23:15 +0800 |
commit | 0f4e1b9ac66b8ffa0083a5a2516e4710393bb0da (patch) | |
tree | 4514951316ebfb10dabf1ffbc856142839817a80 /services | |
parent | f8e93ce4238253c01e3ca36c88eb59979be99d12 (diff) | |
download | gitea-0f4e1b9ac66b8ffa0083a5a2516e4710393bb0da.tar.gz gitea-0f4e1b9ac66b8ffa0083a5a2516e4710393bb0da.zip |
Restructure `webhook` module (#22256)
Previously, there was an `import services/webhooks` inside
`modules/notification/webhook`.
This import was removed (after fighting against many import cycles).
Additionally, `modules/notification/webhook` was moved to
`modules/webhook`,
and a few structs/constants were extracted from `models/webhooks` to
`modules/webhook`.
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Diffstat (limited to 'services')
25 files changed, 1014 insertions, 149 deletions
diff --git a/services/convert/convert.go b/services/convert/convert.go index 756a1f95d9..a8329f5285 100644 --- a/services/convert/convert.go +++ b/services/convert/convert.go @@ -22,13 +22,11 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/gitdiff" - webhook_service "code.gitea.io/gitea/services/webhook" ) // ToEmail convert models.EmailAddress to api.Email @@ -242,38 +240,6 @@ func ToGPGKeyEmail(email *user_model.EmailAddress) *api.GPGKeyEmail { } } -// ToHook convert models.Webhook to api.Hook -func ToHook(repoLink string, w *webhook.Webhook) (*api.Hook, error) { - config := map[string]string{ - "url": w.URL, - "content_type": w.ContentType.Name(), - } - if w.Type == webhook.SLACK { - s := webhook_service.GetSlackHook(w) - config["channel"] = s.Channel - config["username"] = s.Username - config["icon_url"] = s.IconURL - config["color"] = s.Color - } - - authorizationHeader, err := w.HeaderAuthorization() - if err != nil { - return nil, err - } - - return &api.Hook{ - ID: w.ID, - Type: w.Type, - URL: fmt.Sprintf("%s/settings/hooks/%d", repoLink, w.ID), - Active: w.IsActive, - Config: config, - Events: w.EventsArray(), - AuthorizationHeader: authorizationHeader, - Updated: w.UpdatedUnix.AsTime(), - Created: w.CreatedUnix.AsTime(), - }, nil -} - // ToGitHook convert git.Hook to api.GitHook func ToGitHook(h *git.Hook) *api.GitHook { return &api.GitHook{ diff --git a/services/webhook/deliver.go b/services/webhook/deliver.go index eed711c580..effbe45e56 100644 --- a/services/webhook/deliver.go +++ b/services/webhook/deliver.go @@ -26,6 +26,7 @@ import ( "code.gitea.io/gitea/modules/proxy" "code.gitea.io/gitea/modules/queue" "code.gitea.io/gitea/modules/setting" + webhook_module "code.gitea.io/gitea/modules/webhook" "github.com/gobwas/glob" ) @@ -89,7 +90,7 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error { } case http.MethodPut: switch w.Type { - case webhook_model.MATRIX: + case webhook_module.MATRIX: txnID, err := getMatrixTxnID([]byte(t.PayloadContent)) if err != nil { return err @@ -189,9 +190,9 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error { // Update webhook last delivery status. if t.IsSucceed { - w.LastStatus = webhook_model.HookStatusSucceed + w.LastStatus = webhook_module.HookStatusSucceed } else { - w.LastStatus = webhook_model.HookStatusFail + w.LastStatus = webhook_module.HookStatusFail } if err = webhook_model.UpdateWebhookLastStatus(w); err != nil { log.Error("UpdateWebhookLastStatus: %v", err) diff --git a/services/webhook/deliver_test.go b/services/webhook/deliver_test.go index e7a042f4d2..ee63975ad3 100644 --- a/services/webhook/deliver_test.go +++ b/services/webhook/deliver_test.go @@ -16,6 +16,7 @@ import ( webhook_model "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" "github.com/stretchr/testify/assert" ) @@ -62,14 +63,14 @@ func TestWebhookDeliverAuthorizationHeader(t *testing.T) { URL: s.URL + "/webhook", ContentType: webhook_model.ContentTypeJSON, IsActive: true, - Type: webhook_model.GITEA, + Type: webhook_module.GITEA, } err := hook.SetHeaderAuthorization("Bearer s3cr3t-t0ken") assert.NoError(t, err) assert.NoError(t, webhook_model.CreateWebhook(db.DefaultContext, hook)) db.GetEngine(db.DefaultContext).NoAutoTime().DB().Logger.ShowSQL(true) - hookTask := &webhook_model.HookTask{HookID: hook.ID, EventType: webhook_model.HookEventPush, Payloader: &api.PushPayload{}} + hookTask := &webhook_model.HookTask{HookID: hook.ID, EventType: webhook_module.HookEventPush, Payloader: &api.PushPayload{}} hookTask, err = webhook_model.CreateHookTask(db.DefaultContext, hookTask) assert.NoError(t, err) diff --git a/services/webhook/dingtalk.go b/services/webhook/dingtalk.go index 7cb1fb75fc..99ee6e4d19 100644 --- a/services/webhook/dingtalk.go +++ b/services/webhook/dingtalk.go @@ -8,11 +8,11 @@ import ( "net/url" "strings" - webhook_model "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/json" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" + webhook_module "code.gitea.io/gitea/modules/webhook" dingtalk "gitea.com/lunny/dingtalk_webhook" ) @@ -129,7 +129,7 @@ func (d *DingtalkPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, } // Review implements PayloadConvertor Review method -func (d *DingtalkPayload) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) { +func (d *DingtalkPayload) Review(p *api.PullRequestPayload, event webhook_module.HookEventType) (api.Payloader, error) { var text, title string switch p.Action { case api.HookIssueReviewed: @@ -190,6 +190,6 @@ func createDingtalkPayload(title, text, singleTitle, singleURL string) *Dingtalk } // GetDingtalkPayload converts a ding talk webhook into a DingtalkPayload -func GetDingtalkPayload(p api.Payloader, event webhook_model.HookEventType, meta string) (api.Payloader, error) { +func GetDingtalkPayload(p api.Payloader, event webhook_module.HookEventType, _ string) (api.Payloader, error) { return convertPayloader(new(DingtalkPayload), p, event) } diff --git a/services/webhook/dingtalk_test.go b/services/webhook/dingtalk_test.go index 89b5f9d219..e3122d2f36 100644 --- a/services/webhook/dingtalk_test.go +++ b/services/webhook/dingtalk_test.go @@ -7,8 +7,8 @@ import ( "net/url" "testing" - webhook_model "code.gitea.io/gitea/models/webhook" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -162,7 +162,7 @@ func TestDingTalkPayload(t *testing.T) { p.Action = api.HookIssueReviewed d := new(DingtalkPayload) - pl, err := d.Review(p, webhook_model.HookEventPullRequestReviewApproved) + pl, err := d.Review(p, webhook_module.HookEventPullRequestReviewApproved) require.NoError(t, err) require.NotNil(t, pl) require.IsType(t, &DingtalkPayload{}, pl) diff --git a/services/webhook/discord.go b/services/webhook/discord.go index c9fdc95320..ed44fef404 100644 --- a/services/webhook/discord.go +++ b/services/webhook/discord.go @@ -17,6 +17,7 @@ import ( "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" + webhook_module "code.gitea.io/gitea/modules/webhook" ) type ( @@ -190,7 +191,7 @@ func (d *DiscordPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, } // Review implements PayloadConvertor Review method -func (d *DiscordPayload) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) { +func (d *DiscordPayload) Review(p *api.PullRequestPayload, event webhook_module.HookEventType) (api.Payloader, error) { var text, title string var color int switch p.Action { @@ -204,11 +205,11 @@ func (d *DiscordPayload) Review(p *api.PullRequestPayload, event webhook_model.H text = p.Review.Content switch event { - case webhook_model.HookEventPullRequestReviewApproved: + case webhook_module.HookEventPullRequestReviewApproved: color = greenColor - case webhook_model.HookEventPullRequestReviewRejected: + case webhook_module.HookEventPullRequestReviewRejected: color = redColor - case webhook_model.HookEventPullRequestComment: + case webhook_module.HookEventPullRequestComment: color = greyColor default: color = yellowColor @@ -256,7 +257,7 @@ func (d *DiscordPayload) Release(p *api.ReleasePayload) (api.Payloader, error) { } // GetDiscordPayload converts a discord webhook into a DiscordPayload -func GetDiscordPayload(p api.Payloader, event webhook_model.HookEventType, meta string) (api.Payloader, error) { +func GetDiscordPayload(p api.Payloader, event webhook_module.HookEventType, meta string) (api.Payloader, error) { s := new(DiscordPayload) discord := &DiscordMeta{} @@ -269,14 +270,14 @@ func GetDiscordPayload(p api.Payloader, event webhook_model.HookEventType, meta return convertPayloader(s, p, event) } -func parseHookPullRequestEventType(event webhook_model.HookEventType) (string, error) { +func parseHookPullRequestEventType(event webhook_module.HookEventType) (string, error) { switch event { - case webhook_model.HookEventPullRequestReviewApproved: + case webhook_module.HookEventPullRequestReviewApproved: return "approved", nil - case webhook_model.HookEventPullRequestReviewRejected: + case webhook_module.HookEventPullRequestReviewRejected: return "rejected", nil - case webhook_model.HookEventPullRequestComment: + case webhook_module.HookEventPullRequestComment: return "comment", nil default: diff --git a/services/webhook/discord_test.go b/services/webhook/discord_test.go index df3cdc15bd..624d53446a 100644 --- a/services/webhook/discord_test.go +++ b/services/webhook/discord_test.go @@ -6,9 +6,9 @@ package webhook import ( "testing" - webhook_model "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -179,7 +179,7 @@ func TestDiscordPayload(t *testing.T) { p.Action = api.HookIssueReviewed d := new(DiscordPayload) - pl, err := d.Review(p, webhook_model.HookEventPullRequestReviewApproved) + pl, err := d.Review(p, webhook_module.HookEventPullRequestReviewApproved) require.NoError(t, err) require.NotNil(t, pl) require.IsType(t, &DiscordPayload{}, pl) diff --git a/services/webhook/feishu.go b/services/webhook/feishu.go index 58b6fff331..4fbf8f76a9 100644 --- a/services/webhook/feishu.go +++ b/services/webhook/feishu.go @@ -7,10 +7,10 @@ import ( "fmt" "strings" - webhook_model "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/json" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" ) type ( @@ -117,7 +117,7 @@ func (f *FeishuPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, e } // Review implements PayloadConvertor Review method -func (f *FeishuPayload) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) { +func (f *FeishuPayload) Review(p *api.PullRequestPayload, event webhook_module.HookEventType) (api.Payloader, error) { action, err := parseHookPullRequestEventType(event) if err != nil { return nil, err @@ -159,6 +159,6 @@ func (f *FeishuPayload) Release(p *api.ReleasePayload) (api.Payloader, error) { } // GetFeishuPayload converts a ding talk webhook into a FeishuPayload -func GetFeishuPayload(p api.Payloader, event webhook_model.HookEventType, meta string) (api.Payloader, error) { +func GetFeishuPayload(p api.Payloader, event webhook_module.HookEventType, _ string) (api.Payloader, error) { return convertPayloader(new(FeishuPayload), p, event) } diff --git a/services/webhook/feishu_test.go b/services/webhook/feishu_test.go index df44fd1f72..84549c1fa5 100644 --- a/services/webhook/feishu_test.go +++ b/services/webhook/feishu_test.go @@ -6,8 +6,8 @@ package webhook import ( "testing" - webhook_model "code.gitea.io/gitea/models/webhook" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -124,7 +124,7 @@ func TestFeishuPayload(t *testing.T) { p.Action = api.HookIssueReviewed d := new(FeishuPayload) - pl, err := d.Review(p, webhook_model.HookEventPullRequestReviewApproved) + pl, err := d.Review(p, webhook_module.HookEventPullRequestReviewApproved) require.NoError(t, err) require.NotNil(t, pl) require.IsType(t, &FeishuPayload{}, pl) diff --git a/services/webhook/general.go b/services/webhook/general.go index bec752cffe..1f7d204d1f 100644 --- a/services/webhook/general.go +++ b/services/webhook/general.go @@ -9,9 +9,11 @@ import ( "net/url" "strings" + webhook_model "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" + webhook_module "code.gitea.io/gitea/modules/webhook" ) type linkFormatter = func(string, string) string @@ -223,3 +225,36 @@ func getIssueCommentPayloadInfo(p *api.IssueCommentPayload, linkFormatter linkFo return text, issueTitle, 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) { + config := map[string]string{ + "url": w.URL, + "content_type": w.ContentType.Name(), + } + if w.Type == webhook_module.SLACK { + s := GetSlackHook(w) + config["channel"] = s.Channel + config["username"] = s.Username + config["icon_url"] = s.IconURL + config["color"] = s.Color + } + + authorizationHeader, err := w.HeaderAuthorization() + if err != nil { + return nil, err + } + + return &api.Hook{ + ID: w.ID, + Type: w.Type, + URL: fmt.Sprintf("%s/settings/hooks/%d", repoLink, w.ID), + Active: w.IsActive, + Config: config, + Events: w.EventsArray(), + AuthorizationHeader: authorizationHeader, + Updated: w.UpdatedUnix.AsTime(), + Created: w.CreatedUnix.AsTime(), + }, nil +} diff --git a/services/webhook/matrix.go b/services/webhook/matrix.go index bd3efd46b2..cf2b503cdc 100644 --- a/services/webhook/matrix.go +++ b/services/webhook/matrix.go @@ -20,6 +20,7 @@ import ( "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" + webhook_module "code.gitea.io/gitea/modules/webhook" ) const matrixPayloadSizeLimit = 1024 * 64 @@ -173,7 +174,7 @@ func (m *MatrixPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, e } // Review implements PayloadConvertor Review method -func (m *MatrixPayload) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) { +func (m *MatrixPayload) Review(p *api.PullRequestPayload, event webhook_module.HookEventType) (api.Payloader, error) { senderLink := MatrixLinkFormatter(setting.AppURL+url.PathEscape(p.Sender.UserName), p.Sender.UserName) title := fmt.Sprintf("#%d %s", p.Index, p.PullRequest.Title) titleLink := MatrixLinkFormatter(p.PullRequest.URL, title) @@ -210,7 +211,7 @@ func (m *MatrixPayload) Repository(p *api.RepositoryPayload) (api.Payloader, err } // GetMatrixPayload converts a Matrix webhook into a MatrixPayload -func GetMatrixPayload(p api.Payloader, event webhook_model.HookEventType, meta string) (api.Payloader, error) { +func GetMatrixPayload(p api.Payloader, event webhook_module.HookEventType, meta string) (api.Payloader, error) { s := new(MatrixPayload) matrix := &MatrixMeta{} diff --git a/services/webhook/matrix_test.go b/services/webhook/matrix_test.go index 754234eccf..8c71094228 100644 --- a/services/webhook/matrix_test.go +++ b/services/webhook/matrix_test.go @@ -6,8 +6,8 @@ package webhook import ( "testing" - webhook_model "code.gitea.io/gitea/models/webhook" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -133,7 +133,7 @@ func TestMatrixPayload(t *testing.T) { p.Action = api.HookIssueReviewed d := new(MatrixPayload) - pl, err := d.Review(p, webhook_model.HookEventPullRequestReviewApproved) + pl, err := d.Review(p, webhook_module.HookEventPullRequestReviewApproved) require.NoError(t, err) require.NotNil(t, pl) require.IsType(t, &MatrixPayload{}, pl) diff --git a/services/webhook/msteams.go b/services/webhook/msteams.go index ef8366f8d5..03d92821b9 100644 --- a/services/webhook/msteams.go +++ b/services/webhook/msteams.go @@ -8,11 +8,11 @@ import ( "net/url" "strings" - webhook_model "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/json" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" + webhook_module "code.gitea.io/gitea/modules/webhook" ) type ( @@ -205,7 +205,7 @@ func (m *MSTeamsPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, } // Review implements PayloadConvertor Review method -func (m *MSTeamsPayload) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) { +func (m *MSTeamsPayload) Review(p *api.PullRequestPayload, event webhook_module.HookEventType) (api.Payloader, error) { var text, title string var color int switch p.Action { @@ -219,11 +219,11 @@ func (m *MSTeamsPayload) Review(p *api.PullRequestPayload, event webhook_model.H text = p.Review.Content switch event { - case webhook_model.HookEventPullRequestReviewApproved: + case webhook_module.HookEventPullRequestReviewApproved: color = greenColor - case webhook_model.HookEventPullRequestReviewRejected: + case webhook_module.HookEventPullRequestReviewRejected: color = redColor - case webhook_model.HookEventPullRequestComment: + case webhook_module.HookEventPullRequestComment: color = greyColor default: color = yellowColor @@ -297,7 +297,7 @@ func (m *MSTeamsPayload) Release(p *api.ReleasePayload) (api.Payloader, error) { } // GetMSTeamsPayload converts a MSTeams webhook into a MSTeamsPayload -func GetMSTeamsPayload(p api.Payloader, event webhook_model.HookEventType, meta string) (api.Payloader, error) { +func GetMSTeamsPayload(p api.Payloader, event webhook_module.HookEventType, _ string) (api.Payloader, error) { return convertPayloader(new(MSTeamsPayload), p, event) } diff --git a/services/webhook/msteams_test.go b/services/webhook/msteams_test.go index 8daf99f867..4f378713cc 100644 --- a/services/webhook/msteams_test.go +++ b/services/webhook/msteams_test.go @@ -6,8 +6,8 @@ package webhook import ( "testing" - webhook_model "code.gitea.io/gitea/models/webhook" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -277,7 +277,7 @@ func TestMSTeamsPayload(t *testing.T) { p.Action = api.HookIssueReviewed d := new(MSTeamsPayload) - pl, err := d.Review(p, webhook_model.HookEventPullRequestReviewApproved) + pl, err := d.Review(p, webhook_module.HookEventPullRequestReviewApproved) require.NoError(t, err) require.NotNil(t, pl) require.IsType(t, &MSTeamsPayload{}, pl) diff --git a/services/webhook/notifier.go b/services/webhook/notifier.go new file mode 100644 index 0000000000..ee80766032 --- /dev/null +++ b/services/webhook/notifier.go @@ -0,0 +1,860 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package webhook + +import ( + "context" + + issues_model "code.gitea.io/gitea/models/issues" + packages_model "code.gitea.io/gitea/models/packages" + "code.gitea.io/gitea/models/perm" + access_model "code.gitea.io/gitea/models/perm/access" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unit" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/notification" + "code.gitea.io/gitea/modules/notification/base" + "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/setting" + api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" + "code.gitea.io/gitea/services/convert" +) + +func init() { + notification.RegisterNotifier(&webhookNotifier{}) +} + +type webhookNotifier struct { + base.NullNotifier +} + +var _ base.Notifier = &webhookNotifier{} + +// NewNotifier create a new webhookNotifier notifier +func NewNotifier() base.Notifier { + return &webhookNotifier{} +} + +func (m *webhookNotifier) NotifyIssueClearLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) { + if err := issue.LoadPoster(ctx); err != nil { + log.Error("LoadPoster: %v", err) + return + } + + if err := issue.LoadRepo(ctx); err != nil { + log.Error("LoadRepo: %v", err) + return + } + + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) + var err error + if issue.IsPull { + if err = issue.LoadPullRequest(ctx); err != nil { + log.Error("LoadPullRequest: %v", err) + return + } + + err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequestLabel, &api.PullRequestPayload{ + Action: api.HookIssueLabelCleared, + Index: issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil), + Repository: convert.ToRepo(ctx, issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + }) + } else { + err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueLabel, &api.IssuePayload{ + Action: api.HookIssueLabelCleared, + Index: issue.Index, + Issue: convert.ToAPIIssue(ctx, issue), + Repository: convert.ToRepo(ctx, issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + }) + } + if err != nil { + log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) + } +} + +func (m *webhookNotifier) NotifyForkRepository(ctx context.Context, doer *user_model.User, oldRepo, repo *repo_model.Repository) { + oldMode, _ := access_model.AccessLevel(ctx, doer, oldRepo) + mode, _ := access_model.AccessLevel(ctx, doer, repo) + + // forked webhook + if err := PrepareWebhooks(ctx, EventSource{Repository: oldRepo}, webhook_module.HookEventFork, &api.ForkPayload{ + Forkee: convert.ToRepo(ctx, oldRepo, oldMode), + Repo: convert.ToRepo(ctx, repo, mode), + Sender: convert.ToUser(doer, nil), + }); err != nil { + log.Error("PrepareWebhooks [repo_id: %d]: %v", oldRepo.ID, err) + } + + u := repo.MustOwner(ctx) + + // Add to hook queue for created repo after session commit. + if u.IsOrganization() { + if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventRepository, &api.RepositoryPayload{ + Action: api.HookRepoCreated, + Repository: convert.ToRepo(ctx, repo, perm.AccessModeOwner), + Organization: convert.ToUser(u, nil), + Sender: convert.ToUser(doer, nil), + }); err != nil { + log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err) + } + } +} + +func (m *webhookNotifier) NotifyCreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { + // Add to hook queue for created repo after session commit. + if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventRepository, &api.RepositoryPayload{ + Action: api.HookRepoCreated, + Repository: convert.ToRepo(ctx, repo, perm.AccessModeOwner), + Organization: convert.ToUser(u, nil), + Sender: convert.ToUser(doer, nil), + }); err != nil { + log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err) + } +} + +func (m *webhookNotifier) NotifyDeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) { + if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventRepository, &api.RepositoryPayload{ + Action: api.HookRepoDeleted, + Repository: convert.ToRepo(ctx, repo, perm.AccessModeOwner), + Organization: convert.ToUser(repo.MustOwner(ctx), nil), + Sender: convert.ToUser(doer, nil), + }); err != nil { + log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err) + } +} + +func (m *webhookNotifier) NotifyMigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { + // Add to hook queue for created repo after session commit. + if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventRepository, &api.RepositoryPayload{ + Action: api.HookRepoCreated, + Repository: convert.ToRepo(ctx, repo, perm.AccessModeOwner), + Organization: convert.ToUser(u, nil), + Sender: convert.ToUser(doer, nil), + }); err != nil { + log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err) + } +} + +func (m *webhookNotifier) NotifyIssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { + if issue.IsPull { + mode, _ := access_model.AccessLevelUnit(ctx, doer, issue.Repo, unit.TypePullRequests) + + if err := issue.LoadPullRequest(ctx); err != nil { + log.Error("LoadPullRequest failed: %v", err) + return + } + issue.PullRequest.Issue = issue + apiPullRequest := &api.PullRequestPayload{ + Index: issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil), + Repository: convert.ToRepo(ctx, issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + } + if removed { + apiPullRequest.Action = api.HookIssueUnassigned + } else { + apiPullRequest.Action = api.HookIssueAssigned + } + // Assignee comment triggers a webhook + if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequestAssign, apiPullRequest); err != nil { + log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err) + return + } + } else { + mode, _ := access_model.AccessLevelUnit(ctx, doer, issue.Repo, unit.TypeIssues) + apiIssue := &api.IssuePayload{ + Index: issue.Index, + Issue: convert.ToAPIIssue(ctx, issue), + Repository: convert.ToRepo(ctx, issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + } + if removed { + apiIssue.Action = api.HookIssueUnassigned + } else { + apiIssue.Action = api.HookIssueAssigned + } + // Assignee comment triggers a webhook + if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueAssign, apiIssue); err != nil { + log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err) + return + } + } +} + +func (m *webhookNotifier) NotifyIssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) { + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) + var err error + if issue.IsPull { + if err = issue.LoadPullRequest(ctx); err != nil { + log.Error("LoadPullRequest failed: %v", err) + return + } + issue.PullRequest.Issue = issue + err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequest, &api.PullRequestPayload{ + Action: api.HookIssueEdited, + Index: issue.Index, + Changes: &api.ChangesPayload{ + Title: &api.ChangesFromPayload{ + From: oldTitle, + }, + }, + PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil), + Repository: convert.ToRepo(ctx, issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + }) + } else { + err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssues, &api.IssuePayload{ + Action: api.HookIssueEdited, + Index: issue.Index, + Changes: &api.ChangesPayload{ + Title: &api.ChangesFromPayload{ + From: oldTitle, + }, + }, + Issue: convert.ToAPIIssue(ctx, issue), + Repository: convert.ToRepo(ctx, issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + }) + } + + if err != nil { + log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) + } +} + +func (m *webhookNotifier) NotifyIssueChangeStatus(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) + var err error + if issue.IsPull { + if err = issue.LoadPullRequest(ctx); err != nil { + log.Error("LoadPullRequest: %v", err) + return + } + // Merge pull request calls issue.changeStatus so we need to handle separately. + apiPullRequest := &api.PullRequestPayload{ + Index: issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil), + Repository: convert.ToRepo(ctx, issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + } + if isClosed { + apiPullRequest.Action = api.HookIssueClosed + } else { + apiPullRequest.Action = api.HookIssueReOpened + } + err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequest, apiPullRequest) + } else { + apiIssue := &api.IssuePayload{ + Index: issue.Index, + Issue: convert.ToAPIIssue(ctx, issue), + Repository: convert.ToRepo(ctx, issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + } + if isClosed { + apiIssue.Action = api.HookIssueClosed + } else { + apiIssue.Action = api.HookIssueReOpened + } + err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssues, apiIssue) + } + if err != nil { + log.Error("PrepareWebhooks [is_pull: %v, is_closed: %v]: %v", issue.IsPull, isClosed, err) + } +} + +func (m *webhookNotifier) NotifyNewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) { + if err := issue.LoadRepo(ctx); err != nil { + log.Error("issue.LoadRepo: %v", err) + return + } + if err := issue.LoadPoster(ctx); err != nil { + log.Error("issue.LoadPoster: %v", err) + return + } + + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) + if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssues, &api.IssuePayload{ + Action: api.HookIssueOpened, + Index: issue.Index, + Issue: convert.ToAPIIssue(ctx, issue), + Repository: convert.ToRepo(ctx, issue.Repo, mode), + Sender: convert.ToUser(issue.Poster, nil), + }); err != nil { + log.Error("PrepareWebhooks: %v", err) + } +} + +func (m *webhookNotifier) NotifyNewPullRequest(ctx context.Context, pull *issues_model.PullRequest, mentions []*user_model.User) { + if err := pull.LoadIssue(ctx); err != nil { + log.Error("pull.LoadIssue: %v", err) + return + } + if err := pull.Issue.LoadRepo(ctx); err != nil { + log.Error("pull.Issue.LoadRepo: %v", err) + return + } + if err := pull.Issue.LoadPoster(ctx); err != nil { + log.Error("pull.Issue.LoadPoster: %v", err) + return + } + + mode, _ := access_model.AccessLevel(ctx, pull.Issue.Poster, pull.Issue.Repo) + if err := PrepareWebhooks(ctx, EventSource{Repository: pull.Issue.Repo}, webhook_module.HookEventPullRequest, &api.PullRequestPayload{ + Action: api.HookIssueOpened, + Index: pull.Issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, pull, nil), + Repository: convert.ToRepo(ctx, pull.Issue.Repo, mode), + Sender: convert.ToUser(pull.Issue.Poster, nil), + }); err != nil { + log.Error("PrepareWebhooks: %v", err) + } +} + +func (m *webhookNotifier) NotifyIssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldContent string) { + if err := issue.LoadRepo(ctx); err != nil { + log.Error("LoadRepo: %v", err) + return + } + + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) + var err error + if issue.IsPull { + issue.PullRequest.Issue = issue + err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequest, &api.PullRequestPayload{ + Action: api.HookIssueEdited, + Index: issue.Index, + Changes: &api.ChangesPayload{ + Body: &api.ChangesFromPayload{ + From: oldContent, + }, + }, + PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil), + Repository: convert.ToRepo(ctx, issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + }) + } else { + err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssues, &api.IssuePayload{ + Action: api.HookIssueEdited, + Index: issue.Index, + Changes: &api.ChangesPayload{ + Body: &api.ChangesFromPayload{ + From: oldContent, + }, + }, + Issue: convert.ToAPIIssue(ctx, issue), + Repository: convert.ToRepo(ctx, issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + }) + } + if err != nil { + log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) + } +} + +func (m *webhookNotifier) NotifyUpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) { + if err := c.LoadPoster(ctx); err != nil { + log.Error("LoadPoster: %v", err) + return + } + if err := c.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) + return + } + + if err := c.Issue.LoadAttributes(ctx); err != nil { + log.Error("LoadAttributes: %v", err) + return + } + + var eventType webhook_module.HookEventType + if c.Issue.IsPull { + eventType = webhook_module.HookEventPullRequestComment + } else { + eventType = webhook_module.HookEventIssueComment + } + + mode, _ := access_model.AccessLevel(ctx, doer, c.Issue.Repo) + if err := PrepareWebhooks(ctx, EventSource{Repository: c.Issue.Repo}, eventType, &api.IssueCommentPayload{ + Action: api.HookIssueCommentEdited, + Issue: convert.ToAPIIssue(ctx, c.Issue), + Comment: convert.ToComment(c), + Changes: &api.ChangesPayload{ + Body: &api.ChangesFromPayload{ + From: oldContent, + }, + }, + Repository: convert.ToRepo(ctx, c.Issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + IsPull: c.Issue.IsPull, + }); err != nil { + log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err) + } +} + +func (m *webhookNotifier) NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, + issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User, +) { + var eventType webhook_module.HookEventType + if issue.IsPull { + eventType = webhook_module.HookEventPullRequestComment + } else { + eventType = webhook_module.HookEventIssueComment + } + + mode, _ := access_model.AccessLevel(ctx, doer, repo) + if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, eventType, &api.IssueCommentPayload{ + Action: api.HookIssueCommentCreated, + Issue: convert.ToAPIIssue(ctx, issue), + Comment: convert.ToComment(comment), + Repository: convert.ToRepo(ctx, repo, mode), + Sender: convert.ToUser(doer, nil), + IsPull: issue.IsPull, + }); err != nil { + log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) + } +} + +func (m *webhookNotifier) NotifyDeleteComment(ctx context.Context, doer *user_model.User, comment *issues_model.Comment) { + var err error + + if err = comment.LoadPoster(ctx); err != nil { + log.Error("LoadPoster: %v", err) + return + } + if err = comment.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) + return + } + + if err = comment.Issue.LoadAttributes(ctx); err != nil { + log.Error("LoadAttributes: %v", err) + return + } + + var eventType webhook_module.HookEventType + if comment.Issue.IsPull { + eventType = webhook_module.HookEventPullRequestComment + } else { + eventType = webhook_module.HookEventIssueComment + } + + mode, _ := access_model.AccessLevel(ctx, doer, comment.Issue.Repo) + if err := PrepareWebhooks(ctx, EventSource{Repository: comment.Issue.Repo}, eventType, &api.IssueCommentPayload{ + Action: api.HookIssueCommentDeleted, + Issue: convert.ToAPIIssue(ctx, comment.Issue), + Comment: convert.ToComment(comment), + Repository: convert.ToRepo(ctx, comment.Issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + IsPull: comment.Issue.IsPull, + }); err != nil { + log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) + } +} + +func (m *webhookNotifier) NotifyNewWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { + // Add to hook queue for created wiki page. + if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventWiki, &api.WikiPayload{ + Action: api.HookWikiCreated, + Repository: convert.ToRepo(ctx, repo, perm.AccessModeOwner), + Sender: convert.ToUser(doer, nil), + Page: page, + Comment: comment, + }); err != nil { + log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err) + } +} + +func (m *webhookNotifier) NotifyEditWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) { + // Add to hook queue for edit wiki page. + if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventWiki, &api.WikiPayload{ + Action: api.HookWikiEdited, + Repository: convert.ToRepo(ctx, repo, perm.AccessModeOwner), + Sender: convert.ToUser(doer, nil), + Page: page, + Comment: comment, + }); err != nil { + log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err) + } +} + +func (m *webhookNotifier) NotifyDeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page string) { + // Add to hook queue for edit wiki page. + if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventWiki, &api.WikiPayload{ + Action: api.HookWikiDeleted, + Repository: convert.ToRepo(ctx, repo, perm.AccessModeOwner), + Sender: convert.ToUser(doer, nil), + Page: page, + }); err != nil { + log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err) + } +} + +func (m *webhookNotifier) NotifyIssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, + addedLabels, removedLabels []*issues_model.Label, +) { + var err error + + if err = issue.LoadRepo(ctx); err != nil { + log.Error("LoadRepo: %v", err) + return + } + + if err = issue.LoadPoster(ctx); err != nil { + log.Error("LoadPoster: %v", err) + return + } + + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) + if issue.IsPull { + if err = issue.LoadPullRequest(ctx); err != nil { + log.Error("loadPullRequest: %v", err) + return + } + if err = issue.PullRequest.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) + return + } + err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequestLabel, &api.PullRequestPayload{ + Action: api.HookIssueLabelUpdated, + Index: issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil), + Repository: convert.ToRepo(ctx, issue.Repo, perm.AccessModeNone), + Sender: convert.ToUser(doer, nil), + }) + } else { + err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueLabel, &api.IssuePayload{ + Action: api.HookIssueLabelUpdated, + Index: issue.Index, + Issue: convert.ToAPIIssue(ctx, issue), + Repository: convert.ToRepo(ctx, issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + }) + } + if err != nil { + log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) + } +} + +func (m *webhookNotifier) NotifyIssueChangeMilestone(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) { + var hookAction api.HookIssueAction + var err error + if issue.MilestoneID > 0 { + hookAction = api.HookIssueMilestoned + } else { + hookAction = api.HookIssueDemilestoned + } + + if err = issue.LoadAttributes(ctx); err != nil { + log.Error("issue.LoadAttributes failed: %v", err) + return + } + + mode, _ := access_model.AccessLevel(ctx, doer, issue.Repo) + if issue.IsPull { + err = issue.PullRequest.LoadIssue(ctx) + if err != nil { + log.Error("LoadIssue: %v", err) + return + } + err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequestMilestone, &api.PullRequestPayload{ + Action: hookAction, + Index: issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil), + Repository: convert.ToRepo(ctx, issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + }) + } else { + err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueMilestone, &api.IssuePayload{ + Action: hookAction, + Index: issue.Index, + Issue: convert.ToAPIIssue(ctx, issue), + Repository: convert.ToRepo(ctx, issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + }) + } + if err != nil { + log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) + } +} + +func (m *webhookNotifier) NotifyPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { + apiPusher := convert.ToUser(pusher, nil) + apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo.RepoPath(), repo.HTMLURL()) + if err != nil { + log.Error("commits.ToAPIPayloadCommits failed: %v", err) + return + } + + if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{ + Ref: opts.RefFullName, + Before: opts.OldCommitID, + After: opts.NewCommitID, + CompareURL: setting.AppURL + commits.CompareURL, + Commits: apiCommits, + TotalCommits: commits.Len, + HeadCommit: apiHeadCommit, + Repo: convert.ToRepo(ctx, repo, perm.AccessModeOwner), + Pusher: apiPusher, + Sender: apiPusher, + }); err != nil { + log.Error("PrepareWebhooks: %v", err) + } +} + +func (m *webhookNotifier) NotifyAutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + // just redirect to the NotifyMergePullRequest + m.NotifyMergePullRequest(ctx, doer, pr) +} + +func (*webhookNotifier) NotifyMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + // Reload pull request information. + if err := pr.LoadAttributes(ctx); err != nil { + log.Error("LoadAttributes: %v", err) + return + } + + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) + return + } + + if err := pr.Issue.LoadRepo(ctx); err != nil { + log.Error("pr.Issue.LoadRepo: %v", err) + return + } + + mode, err := access_model.AccessLevel(ctx, doer, pr.Issue.Repo) + if err != nil { + log.Error("models.AccessLevel: %v", err) + return + } + + // Merge pull request calls issue.changeStatus so we need to handle separately. + apiPullRequest := &api.PullRequestPayload{ + Index: pr.Issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, pr, nil), + Repository: convert.ToRepo(ctx, pr.Issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + Action: api.HookIssueClosed, + } + + if err := PrepareWebhooks(ctx, EventSource{Repository: pr.Issue.Repo}, webhook_module.HookEventPullRequest, apiPullRequest); err != nil { + log.Error("PrepareWebhooks: %v", err) + } +} + +func (m *webhookNotifier) NotifyPullRequestChangeTargetBranch(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) { + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) + return + } + + issue := pr.Issue + + mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo) + if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequest, &api.PullRequestPayload{ + Action: api.HookIssueEdited, + Index: issue.Index, + Changes: &api.ChangesPayload{ + Ref: &api.ChangesFromPayload{ + From: oldBranch, + }, + }, + PullRequest: convert.ToAPIPullRequest(ctx, pr, nil), + Repository: convert.ToRepo(ctx, issue.Repo, mode), + Sender: convert.ToUser(doer, nil), + }); err != nil { + log.Error("PrepareWebhooks [pr: %d]: %v", pr.ID, err) + } +} + +func (m *webhookNotifier) NotifyPullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) { + var reviewHookType webhook_module.HookEventType + + switch review.Type { + case issues_model.ReviewTypeApprove: + reviewHookType = webhook_module.HookEventPullRequestReviewApproved + case issues_model.ReviewTypeComment: + reviewHookType = webhook_module.HookEventPullRequestComment + case issues_model.ReviewTypeReject: + reviewHookType = webhook_module.HookEventPullRequestReviewRejected + default: + // unsupported review webhook type here + log.Error("Unsupported review webhook type") + return + } + + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) + return + } + + mode, err := access_model.AccessLevel(ctx, review.Issue.Poster, review.Issue.Repo) + if err != nil { + log.Error("models.AccessLevel: %v", err) + return + } + if err := PrepareWebhooks(ctx, EventSource{Repository: review.Issue.Repo}, reviewHookType, &api.PullRequestPayload{ + Action: api.HookIssueReviewed, + Index: review.Issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, pr, nil), + Repository: convert.ToRepo(ctx, review.Issue.Repo, mode), + Sender: convert.ToUser(review.Reviewer, nil), + Review: &api.ReviewPayload{ + Type: string(reviewHookType), + Content: review.Content, + }, + }); err != nil { + log.Error("PrepareWebhooks: %v", err) + } +} + +func (m *webhookNotifier) NotifyCreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { + apiPusher := convert.ToUser(pusher, nil) + apiRepo := convert.ToRepo(ctx, repo, perm.AccessModeNone) + refName := git.RefEndName(refFullName) + + if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventCreate, &api.CreatePayload{ + Ref: refName, + Sha: refID, + RefType: refType, + Repo: apiRepo, + Sender: apiPusher, + }); err != nil { + log.Error("PrepareWebhooks: %v", err) + } +} + +func (m *webhookNotifier) NotifyPullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) + return + } + if err := pr.Issue.LoadAttributes(ctx); err != nil { + log.Error("LoadAttributes: %v", err) + return + } + + if err := PrepareWebhooks(ctx, EventSource{Repository: pr.Issue.Repo}, webhook_module.HookEventPullRequestSync, &api.PullRequestPayload{ + Action: api.HookIssueSynchronized, + Index: pr.Issue.Index, + PullRequest: convert.ToAPIPullRequest(ctx, pr, nil), + Repository: convert.ToRepo(ctx, pr.Issue.Repo, perm.AccessModeNone), + Sender: convert.ToUser(doer, nil), + }); err != nil { + log.Error("PrepareWebhooks [pull_id: %v]: %v", pr.ID, err) + } +} + +func (m *webhookNotifier) NotifyDeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { + apiPusher := convert.ToUser(pusher, nil) + apiRepo := convert.ToRepo(ctx, repo, perm.AccessModeNone) + refName := git.RefEndName(refFullName) + + if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventDelete, &api.DeletePayload{ + Ref: refName, + RefType: refType, + PusherType: api.PusherTypeUser, + Repo: apiRepo, + Sender: apiPusher, + }); err != nil { + log.Error("PrepareWebhooks.(delete %s): %v", refType, err) + } +} + +func sendReleaseHook(ctx context.Context, doer *user_model.User, rel *repo_model.Release, action api.HookReleaseAction) { + if err := rel.LoadAttributes(ctx); err != nil { + log.Error("LoadAttributes: %v", err) + return + } + + mode, _ := access_model.AccessLevel(ctx, doer, rel.Repo) + if err := PrepareWebhooks(ctx, EventSource{Repository: rel.Repo}, webhook_module.HookEventRelease, &api.ReleasePayload{ + Action: action, + Release: convert.ToRelease(rel), + Repository: convert.ToRepo(ctx, rel.Repo, mode), + Sender: convert.ToUser(doer, nil), + }); err != nil { + log.Error("PrepareWebhooks: %v", err) + } +} + +func (m *webhookNotifier) NotifyNewRelease(ctx context.Context, rel *repo_model.Release) { + sendReleaseHook(ctx, rel.Publisher, rel, api.HookReleasePublished) +} + +func (m *webhookNotifier) NotifyUpdateRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { + sendReleaseHook(ctx, doer, rel, api.HookReleaseUpdated) +} + +func (m *webhookNotifier) NotifyDeleteRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) { + sendReleaseHook(ctx, doer, rel, api.HookReleaseDeleted) +} + +func (m *webhookNotifier) NotifySyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { + apiPusher := convert.ToUser(pusher, nil) + apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo.RepoPath(), repo.HTMLURL()) + if err != nil { + log.Error("commits.ToAPIPayloadCommits failed: %v", err) + return + } + + if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{ + Ref: opts.RefFullName, + Before: opts.OldCommitID, + After: opts.NewCommitID, + CompareURL: setting.AppURL + commits.CompareURL, + Commits: apiCommits, + TotalCommits: commits.Len, + HeadCommit: apiHeadCommit, + Repo: convert.ToRepo(ctx, repo, perm.AccessModeOwner), + Pusher: apiPusher, + Sender: apiPusher, + }); err != nil { + log.Error("PrepareWebhooks: %v", err) + } +} + +func (m *webhookNotifier) NotifySyncCreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { + m.NotifyCreateRef(ctx, pusher, repo, refType, refFullName, refID) +} + +func (m *webhookNotifier) NotifySyncDeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName string) { + m.NotifyDeleteRef(ctx, pusher, repo, refType, refFullName) +} + +func (m *webhookNotifier) NotifyPackageCreate(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { + notifyPackage(ctx, doer, pd, api.HookPackageCreated) +} + +func (m *webhookNotifier) NotifyPackageDelete(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) { + notifyPackage(ctx, doer, pd, api.HookPackageDeleted) +} + +func notifyPackage(ctx context.Context, sender *user_model.User, pd *packages_model.PackageDescriptor, action api.HookPackageAction) { + source := EventSource{ + Repository: pd.Repository, + Owner: pd.Owner, + } + + apiPackage, err := convert.ToPackage(ctx, pd, sender) + if err != nil { + log.Error("Error converting package: %v", err) + return + } + + if err := PrepareWebhooks(ctx, source, webhook_module.HookEventPackage, &api.PackagePayload{ + Action: action, + Package: apiPackage, + Sender: convert.ToUser(sender, nil), + }); err != nil { + log.Error("PrepareWebhooks: %v", err) + } +} diff --git a/services/webhook/packagist.go b/services/webhook/packagist.go index 815e1a93e9..e47e7d3285 100644 --- a/services/webhook/packagist.go +++ b/services/webhook/packagist.go @@ -10,6 +10,7 @@ import ( "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" ) type ( @@ -20,7 +21,7 @@ type ( } `json:"repository"` } - // PackagistMeta contains the meta data for the webhook + // PackagistMeta contains the metadata for the webhook PackagistMeta struct { Username string `json:"username"` APIToken string `json:"api_token"` @@ -49,62 +50,62 @@ func (f *PackagistPayload) JSONPayload() ([]byte, error) { var _ PayloadConvertor = &PackagistPayload{} // Create implements PayloadConvertor Create method -func (f *PackagistPayload) Create(p *api.CreatePayload) (api.Payloader, error) { +func (f *PackagistPayload) Create(_ *api.CreatePayload) (api.Payloader, error) { return nil, nil } // Delete implements PayloadConvertor Delete method -func (f *PackagistPayload) Delete(p *api.DeletePayload) (api.Payloader, error) { +func (f *PackagistPayload) Delete(_ *api.DeletePayload) (api.Payloader, error) { return nil, nil } // Fork implements PayloadConvertor Fork method -func (f *PackagistPayload) Fork(p *api.ForkPayload) (api.Payloader, error) { +func (f *PackagistPayload) Fork(_ *api.ForkPayload) (api.Payloader, error) { return nil, nil } // Push implements PayloadConvertor Push method -func (f *PackagistPayload) Push(p *api.PushPayload) (api.Payloader, error) { +func (f *PackagistPayload) Push(_ *api.PushPayload) (api.Payloader, error) { return f, nil } // Issue implements PayloadConvertor Issue method -func (f *PackagistPayload) Issue(p *api.IssuePayload) (api.Payloader, error) { +func (f *PackagistPayload) Issue(_ *api.IssuePayload) (api.Payloader, error) { return nil, nil } // IssueComment implements PayloadConvertor IssueComment method -func (f *PackagistPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) { +func (f *PackagistPayload) IssueComment(_ *api.IssueCommentPayload) (api.Payloader, error) { return nil, nil } // PullRequest implements PayloadConvertor PullRequest method -func (f *PackagistPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, error) { +func (f *PackagistPayload) PullRequest(_ *api.PullRequestPayload) (api.Payloader, error) { return nil, nil } // Review implements PayloadConvertor Review method -func (f *PackagistPayload) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) { +func (f *PackagistPayload) Review(_ *api.PullRequestPayload, _ webhook_module.HookEventType) (api.Payloader, error) { return nil, nil } // Repository implements PayloadConvertor Repository method -func (f *PackagistPayload) Repository(p *api.RepositoryPayload) (api.Payloader, error) { +func (f *PackagistPayload) Repository(_ *api.RepositoryPayload) (api.Payloader, error) { return nil, nil } // Wiki implements PayloadConvertor Wiki method -func (f *PackagistPayload) Wiki(p *api.WikiPayload) (api.Payloader, error) { +func (f *PackagistPayload) Wiki(_ *api.WikiPayload) (api.Payloader, error) { return nil, nil } // Release implements PayloadConvertor Release method -func (f *PackagistPayload) Release(p *api.ReleasePayload) (api.Payloader, error) { +func (f *PackagistPayload) Release(_ *api.ReleasePayload) (api.Payloader, error) { return nil, nil } // GetPackagistPayload converts a packagist webhook into a PackagistPayload -func GetPackagistPayload(p api.Payloader, event webhook_model.HookEventType, meta string) (api.Payloader, error) { +func GetPackagistPayload(p api.Payloader, event webhook_module.HookEventType, meta string) (api.Payloader, error) { s := new(PackagistPayload) packagist := &PackagistMeta{} diff --git a/services/webhook/packagist_test.go b/services/webhook/packagist_test.go index 4941ae3f01..932b56fe9b 100644 --- a/services/webhook/packagist_test.go +++ b/services/webhook/packagist_test.go @@ -6,8 +6,8 @@ package webhook import ( "testing" - webhook_model "code.gitea.io/gitea/models/webhook" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -101,7 +101,7 @@ func TestPackagistPayload(t *testing.T) { p.Action = api.HookIssueReviewed d := new(PackagistPayload) - pl, err := d.Review(p, webhook_model.HookEventPullRequestReviewApproved) + pl, err := d.Review(p, webhook_module.HookEventPullRequestReviewApproved) require.NoError(t, err) require.Nil(t, pl) }) diff --git a/services/webhook/payloader.go b/services/webhook/payloader.go index 7b04f1dd36..9eff25628b 100644 --- a/services/webhook/payloader.go +++ b/services/webhook/payloader.go @@ -4,8 +4,8 @@ package webhook import ( - webhook_model "code.gitea.io/gitea/models/webhook" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" ) // PayloadConvertor defines the interface to convert system webhook payload to external payload @@ -18,40 +18,40 @@ type PayloadConvertor interface { IssueComment(*api.IssueCommentPayload) (api.Payloader, error) Push(*api.PushPayload) (api.Payloader, error) PullRequest(*api.PullRequestPayload) (api.Payloader, error) - Review(*api.PullRequestPayload, webhook_model.HookEventType) (api.Payloader, error) + Review(*api.PullRequestPayload, webhook_module.HookEventType) (api.Payloader, error) Repository(*api.RepositoryPayload) (api.Payloader, error) Release(*api.ReleasePayload) (api.Payloader, error) Wiki(*api.WikiPayload) (api.Payloader, error) } -func convertPayloader(s PayloadConvertor, p api.Payloader, event webhook_model.HookEventType) (api.Payloader, error) { +func convertPayloader(s PayloadConvertor, p api.Payloader, event webhook_module.HookEventType) (api.Payloader, error) { switch event { - case webhook_model.HookEventCreate: + case webhook_module.HookEventCreate: return s.Create(p.(*api.CreatePayload)) - case webhook_model.HookEventDelete: + case webhook_module.HookEventDelete: return s.Delete(p.(*api.DeletePayload)) - case webhook_model.HookEventFork: + case webhook_module.HookEventFork: return s.Fork(p.(*api.ForkPayload)) - case webhook_model.HookEventIssues, webhook_model.HookEventIssueAssign, webhook_model.HookEventIssueLabel, webhook_model.HookEventIssueMilestone: + case webhook_module.HookEventIssues, webhook_module.HookEventIssueAssign, webhook_module.HookEventIssueLabel, webhook_module.HookEventIssueMilestone: return s.Issue(p.(*api.IssuePayload)) - case webhook_model.HookEventIssueComment, webhook_model.HookEventPullRequestComment: + case webhook_module.HookEventIssueComment, webhook_module.HookEventPullRequestComment: pl, ok := p.(*api.IssueCommentPayload) if ok { return s.IssueComment(pl) } return s.PullRequest(p.(*api.PullRequestPayload)) - case webhook_model.HookEventPush: + case webhook_module.HookEventPush: return s.Push(p.(*api.PushPayload)) - case webhook_model.HookEventPullRequest, webhook_model.HookEventPullRequestAssign, webhook_model.HookEventPullRequestLabel, - webhook_model.HookEventPullRequestMilestone, webhook_model.HookEventPullRequestSync: + case webhook_module.HookEventPullRequest, webhook_module.HookEventPullRequestAssign, webhook_module.HookEventPullRequestLabel, + webhook_module.HookEventPullRequestMilestone, webhook_module.HookEventPullRequestSync: return s.PullRequest(p.(*api.PullRequestPayload)) - case webhook_model.HookEventPullRequestReviewApproved, webhook_model.HookEventPullRequestReviewRejected, webhook_model.HookEventPullRequestReviewComment: + case webhook_module.HookEventPullRequestReviewApproved, webhook_module.HookEventPullRequestReviewRejected, webhook_module.HookEventPullRequestReviewComment: return s.Review(p.(*api.PullRequestPayload), event) - case webhook_model.HookEventRepository: + case webhook_module.HookEventRepository: return s.Repository(p.(*api.RepositoryPayload)) - case webhook_model.HookEventRelease: + case webhook_module.HookEventRelease: return s.Release(p.(*api.ReleasePayload)) - case webhook_model.HookEventWiki: + case webhook_module.HookEventWiki: return s.Wiki(p.(*api.WikiPayload)) } return s, nil diff --git a/services/webhook/slack.go b/services/webhook/slack.go index 1814361a1c..c2d4a7731e 100644 --- a/services/webhook/slack.go +++ b/services/webhook/slack.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" ) // SlackMeta contains the slack metadata @@ -231,7 +232,7 @@ func (s *SlackPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, er } // Review implements PayloadConvertor Review method -func (s *SlackPayload) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) { +func (s *SlackPayload) Review(p *api.PullRequestPayload, event webhook_module.HookEventType) (api.Payloader, error) { senderLink := SlackLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName) title := fmt.Sprintf("#%d %s", p.Index, p.PullRequest.Title) titleLink := fmt.Sprintf("%s/pulls/%d", p.Repository.HTMLURL, p.Index) @@ -278,7 +279,7 @@ func (s *SlackPayload) createPayload(text string, attachments []SlackAttachment) } // GetSlackPayload converts a slack webhook into a SlackPayload -func GetSlackPayload(p api.Payloader, event webhook_model.HookEventType, meta string) (api.Payloader, error) { +func GetSlackPayload(p api.Payloader, event webhook_module.HookEventType, meta string) (api.Payloader, error) { s := new(SlackPayload) slack := &SlackMeta{} diff --git a/services/webhook/slack_test.go b/services/webhook/slack_test.go index db97b351c5..d9828f374f 100644 --- a/services/webhook/slack_test.go +++ b/services/webhook/slack_test.go @@ -6,8 +6,8 @@ package webhook import ( "testing" - webhook_model "code.gitea.io/gitea/models/webhook" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -124,7 +124,7 @@ func TestSlackPayload(t *testing.T) { p.Action = api.HookIssueReviewed d := new(SlackPayload) - pl, err := d.Review(p, webhook_model.HookEventPullRequestReviewApproved) + pl, err := d.Review(p, webhook_module.HookEventPullRequestReviewApproved) require.NoError(t, err) require.NotNil(t, pl) require.IsType(t, &SlackPayload{}, pl) diff --git a/services/webhook/telegram.go b/services/webhook/telegram.go index 8bc68490e5..e5c731fc92 100644 --- a/services/webhook/telegram.go +++ b/services/webhook/telegram.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" ) type ( @@ -140,7 +141,7 @@ func (t *TelegramPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, } // Review implements PayloadConvertor Review method -func (t *TelegramPayload) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) { +func (t *TelegramPayload) Review(p *api.PullRequestPayload, event webhook_module.HookEventType) (api.Payloader, error) { var text, attachmentText string switch p.Action { case api.HookIssueReviewed: @@ -185,7 +186,7 @@ func (t *TelegramPayload) Release(p *api.ReleasePayload) (api.Payloader, error) } // GetTelegramPayload converts a telegram webhook into a TelegramPayload -func GetTelegramPayload(p api.Payloader, event webhook_model.HookEventType, meta string) (api.Payloader, error) { +func GetTelegramPayload(p api.Payloader, event webhook_module.HookEventType, _ string) (api.Payloader, error) { return convertPayloader(new(TelegramPayload), p, event) } diff --git a/services/webhook/telegram_test.go b/services/webhook/telegram_test.go index b092f7e732..b42b0ccda8 100644 --- a/services/webhook/telegram_test.go +++ b/services/webhook/telegram_test.go @@ -6,8 +6,8 @@ package webhook import ( "testing" - webhook_model "code.gitea.io/gitea/models/webhook" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -124,7 +124,7 @@ func TestTelegramPayload(t *testing.T) { p.Action = api.HookIssueReviewed d := new(TelegramPayload) - pl, err := d.Review(p, webhook_model.HookEventPullRequestReviewApproved) + pl, err := d.Review(p, webhook_module.HookEventPullRequestReviewApproved) require.NoError(t, err) require.NotNil(t, pl) require.IsType(t, &TelegramPayload{}, pl) diff --git a/services/webhook/webhook.go b/services/webhook/webhook.go index 21173e7cd8..afd8e3c105 100644 --- a/services/webhook/webhook.go +++ b/services/webhook/webhook.go @@ -18,62 +18,58 @@ import ( "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" + webhook_module "code.gitea.io/gitea/modules/webhook" "github.com/gobwas/glob" ) type webhook struct { - name webhook_model.HookType - payloadCreator func(p api.Payloader, event webhook_model.HookEventType, meta string) (api.Payloader, error) + name webhook_module.HookType + payloadCreator func(p api.Payloader, event webhook_module.HookEventType, meta string) (api.Payloader, error) } -var webhooks = map[webhook_model.HookType]*webhook{ - webhook_model.SLACK: { - name: webhook_model.SLACK, +var webhooks = map[webhook_module.HookType]*webhook{ + webhook_module.SLACK: { + name: webhook_module.SLACK, payloadCreator: GetSlackPayload, }, - webhook_model.DISCORD: { - name: webhook_model.DISCORD, + webhook_module.DISCORD: { + name: webhook_module.DISCORD, payloadCreator: GetDiscordPayload, }, - webhook_model.DINGTALK: { - name: webhook_model.DINGTALK, + webhook_module.DINGTALK: { + name: webhook_module.DINGTALK, payloadCreator: GetDingtalkPayload, }, - webhook_model.TELEGRAM: { - name: webhook_model.TELEGRAM, + webhook_module.TELEGRAM: { + name: webhook_module.TELEGRAM, payloadCreator: GetTelegramPayload, }, - webhook_model.MSTEAMS: { - name: webhook_model.MSTEAMS, + webhook_module.MSTEAMS: { + name: webhook_module.MSTEAMS, payloadCreator: GetMSTeamsPayload, }, - webhook_model.FEISHU: { - name: webhook_model.FEISHU, + webhook_module.FEISHU: { + name: webhook_module.FEISHU, payloadCreator: GetFeishuPayload, }, - webhook_model.MATRIX: { - name: webhook_model.MATRIX, + webhook_module.MATRIX: { + name: webhook_module.MATRIX, payloadCreator: GetMatrixPayload, }, - webhook_model.WECHATWORK: { - name: webhook_model.WECHATWORK, + webhook_module.WECHATWORK: { + name: webhook_module.WECHATWORK, payloadCreator: GetWechatworkPayload, }, - webhook_model.PACKAGIST: { - name: webhook_model.PACKAGIST, + webhook_module.PACKAGIST: { + name: webhook_module.PACKAGIST, payloadCreator: GetPackagistPayload, }, } -// RegisterWebhook registers a webhook -func RegisterWebhook(name string, webhook *webhook) { - webhooks[name] = webhook -} - // IsValidHookTaskType returns true if a webhook registered func IsValidHookTaskType(name string) bool { - if name == webhook_model.GITEA || name == webhook_model.GOGS { + if name == webhook_module.GITEA || name == webhook_module.GOGS { return true } _, ok := webhooks[name] @@ -157,7 +153,7 @@ func checkBranch(w *webhook_model.Webhook, branch string) bool { } // PrepareWebhook creates a hook task and enqueues it for processing -func PrepareWebhook(ctx context.Context, w *webhook_model.Webhook, event webhook_model.HookEventType, p api.Payloader) error { +func PrepareWebhook(ctx context.Context, w *webhook_model.Webhook, event webhook_module.HookEventType, p api.Payloader) error { // Skip sending if webhooks are disabled. if setting.DisableWebhooks { return nil @@ -176,7 +172,7 @@ func PrepareWebhook(ctx context.Context, w *webhook_model.Webhook, event webhook // Avoid sending "0 new commits" to non-integration relevant webhooks (e.g. slack, discord, etc.). // Integration webhooks (e.g. drone) still receive the required data. if pushEvent, ok := p.(*api.PushPayload); ok && - w.Type != webhook_model.GITEA && w.Type != webhook_model.GOGS && + w.Type != webhook_module.GITEA && w.Type != webhook_module.GOGS && len(pushEvent.Commits) == 0 { return nil } @@ -215,7 +211,7 @@ func PrepareWebhook(ctx context.Context, w *webhook_model.Webhook, event webhook } // PrepareWebhooks adds new webhooks to task queue for given payload. -func PrepareWebhooks(ctx context.Context, source EventSource, event webhook_model.HookEventType, p api.Payloader) error { +func PrepareWebhooks(ctx context.Context, source EventSource, event webhook_module.HookEventType, p api.Payloader) error { owner := source.Owner var ws []*webhook_model.Webhook diff --git a/services/webhook/webhook_test.go b/services/webhook/webhook_test.go index a1f197d809..338b94360b 100644 --- a/services/webhook/webhook_test.go +++ b/services/webhook/webhook_test.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/models/unittest" webhook_model "code.gitea.io/gitea/models/webhook" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" "github.com/stretchr/testify/assert" ) @@ -32,12 +33,12 @@ func TestPrepareWebhooks(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) hookTasks := []*webhook_model.HookTask{ - {HookID: 1, EventType: webhook_model.HookEventPush}, + {HookID: 1, EventType: webhook_module.HookEventPush}, } for _, hookTask := range hookTasks { unittest.AssertNotExistsBean(t, hookTask) } - assert.NoError(t, PrepareWebhooks(db.DefaultContext, EventSource{Repository: repo}, webhook_model.HookEventPush, &api.PushPayload{Commits: []*api.PayloadCommit{{}}})) + assert.NoError(t, PrepareWebhooks(db.DefaultContext, EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{Commits: []*api.PayloadCommit{{}}})) for _, hookTask := range hookTasks { unittest.AssertExistsAndLoadBean(t, hookTask) } @@ -48,13 +49,13 @@ func TestPrepareWebhooksBranchFilterMatch(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) hookTasks := []*webhook_model.HookTask{ - {HookID: 4, EventType: webhook_model.HookEventPush}, + {HookID: 4, EventType: webhook_module.HookEventPush}, } for _, hookTask := range hookTasks { unittest.AssertNotExistsBean(t, hookTask) } // this test also ensures that * doesn't handle / in any special way (like shell would) - assert.NoError(t, PrepareWebhooks(db.DefaultContext, EventSource{Repository: repo}, webhook_model.HookEventPush, &api.PushPayload{Ref: "refs/heads/feature/7791", Commits: []*api.PayloadCommit{{}}})) + assert.NoError(t, PrepareWebhooks(db.DefaultContext, EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{Ref: "refs/heads/feature/7791", Commits: []*api.PayloadCommit{{}}})) for _, hookTask := range hookTasks { unittest.AssertExistsAndLoadBean(t, hookTask) } @@ -65,12 +66,12 @@ func TestPrepareWebhooksBranchFilterNoMatch(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) hookTasks := []*webhook_model.HookTask{ - {HookID: 4, EventType: webhook_model.HookEventPush}, + {HookID: 4, EventType: webhook_module.HookEventPush}, } for _, hookTask := range hookTasks { unittest.AssertNotExistsBean(t, hookTask) } - assert.NoError(t, PrepareWebhooks(db.DefaultContext, EventSource{Repository: repo}, webhook_model.HookEventPush, &api.PushPayload{Ref: "refs/heads/fix_weird_bug"})) + assert.NoError(t, PrepareWebhooks(db.DefaultContext, EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{Ref: "refs/heads/fix_weird_bug"})) for _, hookTask := range hookTasks { unittest.AssertNotExistsBean(t, hookTask) diff --git a/services/webhook/wechatwork.go b/services/webhook/wechatwork.go index a77d871dd7..dc8810c4a6 100644 --- a/services/webhook/wechatwork.go +++ b/services/webhook/wechatwork.go @@ -7,10 +7,10 @@ import ( "fmt" "strings" - webhook_model "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/json" api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" ) type ( @@ -135,7 +135,7 @@ func (f *WechatworkPayload) PullRequest(p *api.PullRequestPayload) (api.Payloade } // Review implements PayloadConvertor Review method -func (f *WechatworkPayload) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) { +func (f *WechatworkPayload) Review(p *api.PullRequestPayload, event webhook_module.HookEventType) (api.Payloader, error) { var text, title string switch p.Action { case api.HookIssueReviewed: @@ -180,6 +180,6 @@ func (f *WechatworkPayload) Release(p *api.ReleasePayload) (api.Payloader, error } // GetWechatworkPayload GetWechatworkPayload converts a ding talk webhook into a WechatworkPayload -func GetWechatworkPayload(p api.Payloader, event webhook_model.HookEventType, meta string) (api.Payloader, error) { +func GetWechatworkPayload(p api.Payloader, event webhook_module.HookEventType, _ string) (api.Payloader, error) { return convertPayloader(new(WechatworkPayload), p, event) } |