From 23971a77a00d4970b7c209545c9f65db6351d509 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 1 Feb 2025 22:44:50 -0800 Subject: [PATCH] Add tests for webhook and fix some webhook bugs (#33396) (#33442) This PR created a mock webhook server in the tests and added integration tests for generic webhooks. It also fixes bugs in package webhooks and pull request comment webhooks. This also corrected an error on the package webhook. The previous implementation uses a `User` struct as an organization, now it has been corrected but it will not be consistent with the previous implementation, some fields which not belong to the organization have been removed. Backport #33396 Backport part of #33337 --- models/webhook/webhook.go | 6 + models/webhook/webhook_test.go | 2 +- modules/structs/hook.go | 60 +-- modules/webhook/structs.go | 1 + modules/webhook/type.go | 17 +- routers/api/v1/utils/hook.go | 2 + services/webhook/dingtalk.go | 4 + services/webhook/discord.go | 4 + services/webhook/feishu.go | 4 + services/webhook/general_test.go | 4 +- services/webhook/matrix.go | 4 + services/webhook/msteams.go | 4 + services/webhook/notifier.go | 13 +- services/webhook/packagist.go | 4 + services/webhook/slack.go | 4 + services/webhook/telegram.go | 4 + services/webhook/webhook.go | 16 +- services/webhook/wechatwork.go | 4 + tests/integration/api_repo_test.go | 15 +- tests/integration/api_wiki_test.go | 24 +- tests/integration/issue_test.go | 2 +- tests/integration/repo_webhook_test.go | 565 +++++++++++++++++++++++++ tests/mssql.ini.tmpl | 6 + tests/mysql.ini.tmpl | 6 + tests/pgsql.ini.tmpl | 6 + tests/sqlite.ini.tmpl | 6 + 26 files changed, 682 insertions(+), 105 deletions(-) diff --git a/models/webhook/webhook.go b/models/webhook/webhook.go index 894357e36a12d..a17582c0c9aa1 100644 --- a/models/webhook/webhook.go +++ b/models/webhook/webhook.go @@ -299,6 +299,11 @@ func (w *Webhook) HasPackageEvent() bool { (w.ChooseEvents && w.HookEvents.Package) } +func (w *Webhook) HasStatusEvent() bool { + return w.SendEverything || + (w.ChooseEvents && w.HookEvents.Status) +} + // HasPullRequestReviewRequestEvent returns true if hook enabled pull request review request event. func (w *Webhook) HasPullRequestReviewRequestEvent() bool { return w.SendEverything || @@ -337,6 +342,7 @@ func (w *Webhook) EventCheckers() []struct { {w.HasReleaseEvent, webhook_module.HookEventRelease}, {w.HasPackageEvent, webhook_module.HookEventPackage}, {w.HasPullRequestReviewRequestEvent, webhook_module.HookEventPullRequestReviewRequest}, + {w.HasStatusEvent, webhook_module.HookEventStatus}, } } diff --git a/models/webhook/webhook_test.go b/models/webhook/webhook_test.go index c6c3f40d46eff..5e135369e6c53 100644 --- a/models/webhook/webhook_test.go +++ b/models/webhook/webhook_test.go @@ -74,7 +74,7 @@ func TestWebhook_EventsArray(t *testing.T) { "pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone", "pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected", "pull_request_review_comment", "pull_request_sync", "wiki", "repository", "release", - "package", "pull_request_review_request", + "package", "pull_request_review_request", "status", }, (&Webhook{ HookEvent: &webhook_module.HookEvent{SendEverything: true}, diff --git a/modules/structs/hook.go b/modules/structs/hook.go index ce5742e5c7ce9..cef2dbd712912 100644 --- a/modules/structs/hook.go +++ b/modules/structs/hook.go @@ -116,14 +116,7 @@ var ( _ Payloader = &PackagePayload{} ) -// _________ __ -// \_ ___ \_______ ____ _____ _/ |_ ____ -// / \ \/\_ __ \_/ __ \\__ \\ __\/ __ \ -// \ \____| | \/\ ___/ / __ \| | \ ___/ -// \______ /|__| \___ >____ /__| \___ > -// \/ \/ \/ \/ - -// CreatePayload FIXME +// CreatePayload represents a payload information of create event. type CreatePayload struct { Sha string `json:"sha"` Ref string `json:"ref"` @@ -157,13 +150,6 @@ func ParseCreateHook(raw []byte) (*CreatePayload, error) { return hook, nil } -// ________ .__ __ -// \______ \ ____ | | _____/ |_ ____ -// | | \_/ __ \| | _/ __ \ __\/ __ \ -// | ` \ ___/| |_\ ___/| | \ ___/ -// /_______ /\___ >____/\___ >__| \___ > -// \/ \/ \/ \/ - // PusherType define the type to push type PusherType string @@ -186,13 +172,6 @@ func (p *DeletePayload) JSONPayload() ([]byte, error) { return json.MarshalIndent(p, "", " ") } -// ___________ __ -// \_ _____/__________| | __ -// | __)/ _ \_ __ \ |/ / -// | \( <_> ) | \/ < -// \___ / \____/|__| |__|_ \ -// \/ \/ - // ForkPayload represents fork payload type ForkPayload struct { Forkee *Repository `json:"forkee"` @@ -232,13 +211,6 @@ func (p *IssueCommentPayload) JSONPayload() ([]byte, error) { return json.MarshalIndent(p, "", " ") } -// __________ .__ -// \______ \ ____ | | ____ _____ ______ ____ -// | _// __ \| | _/ __ \\__ \ / ___// __ \ -// | | \ ___/| |_\ ___/ / __ \_\___ \\ ___/ -// |____|_ /\___ >____/\___ >____ /____ >\___ > -// \/ \/ \/ \/ \/ \/ - // HookReleaseAction defines hook release action type type HookReleaseAction string @@ -302,13 +274,6 @@ func (p *PushPayload) Branch() string { return strings.ReplaceAll(p.Ref, "refs/heads/", "") } -// .___ -// | | ______ ________ __ ____ -// | |/ ___// ___/ | \_/ __ \ -// | |\___ \ \___ \| | /\ ___/ -// |___/____ >____ >____/ \___ > -// \/ \/ \/ - // HookIssueAction FIXME type HookIssueAction string @@ -371,13 +336,6 @@ type ChangesPayload struct { Ref *ChangesFromPayload `json:"ref,omitempty"` } -// __________ .__ .__ __________ __ -// \______ \__ __| | | | \______ \ ____ ________ __ ____ _______/ |_ -// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\ -// | | | | / |_| |__ | | \ ___< <_| | | /\ ___/ \___ \ | | -// |____| |____/|____/____/ |____|_ /\___ >__ |____/ \___ >____ > |__| -// \/ \/ |__| \/ \/ - // PullRequestPayload represents a payload information of pull request event. type PullRequestPayload struct { Action HookIssueAction `json:"action"` @@ -402,13 +360,6 @@ type ReviewPayload struct { Content string `json:"content"` } -// __ __.__ __ .__ -// / \ / \__| | _|__| -// \ \/\/ / | |/ / | -// \ /| | <| | -// \__/\ / |__|__|_ \__| -// \/ \/ - // HookWikiAction an action that happens to a wiki page type HookWikiAction string @@ -435,13 +386,6 @@ func (p *WikiPayload) JSONPayload() ([]byte, error) { return json.MarshalIndent(p, "", " ") } -//__________ .__ __ -//\______ \ ____ ______ ____ _____|__|/ |_ ___________ ___.__. -// | _// __ \\____ \ / _ \/ ___/ \ __\/ _ \_ __ < | | -// | | \ ___/| |_> > <_> )___ \| || | ( <_> ) | \/\___ | -// |____|_ /\___ > __/ \____/____ >__||__| \____/|__| / ____| -// \/ \/|__| \/ \/ - // HookRepoAction an action that happens to a repo type HookRepoAction string @@ -480,7 +424,7 @@ type PackagePayload struct { Action HookPackageAction `json:"action"` Repository *Repository `json:"repository"` Package *Package `json:"package"` - Organization *User `json:"organization"` + Organization *Organization `json:"organization"` Sender *User `json:"sender"` } diff --git a/modules/webhook/structs.go b/modules/webhook/structs.go index 927a91a74c545..a9f8e33ae28f7 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"` + Status bool `json:"status"` } // HookEvent represents events that will delivery hook. diff --git a/modules/webhook/type.go b/modules/webhook/type.go index fbec8892722b7..281f7e653b2f6 100644 --- a/modules/webhook/type.go +++ b/modules/webhook/type.go @@ -38,14 +38,6 @@ const ( // Event returns the HookEventType as an event string func (h HookEventType) Event() string { switch h { - case HookEventCreate: - return "create" - case HookEventDelete: - return "delete" - case HookEventFork: - return "fork" - case HookEventPush: - return "push" case HookEventIssues, HookEventIssueAssign, HookEventIssueLabel, HookEventIssueMilestone: return "issues" case HookEventPullRequest, HookEventPullRequestAssign, HookEventPullRequestLabel, HookEventPullRequestMilestone, @@ -59,14 +51,9 @@ func (h HookEventType) Event() string { return "pull_request_rejected" case HookEventPullRequestReviewComment: return "pull_request_comment" - case HookEventWiki: - return "wiki" - case HookEventRepository: - return "repository" - case HookEventRelease: - return "release" + default: + return string(h) } - return "" } // HookType is the type of a webhook diff --git a/routers/api/v1/utils/hook.go b/routers/api/v1/utils/hook.go index 4328878e19613..8e91c2e0efcc7 100644 --- a/routers/api/v1/utils/hook.go +++ b/routers/api/v1/utils/hook.go @@ -205,6 +205,8 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, ownerID, repoI Wiki: util.SliceContainsString(form.Events, string(webhook_module.HookEventWiki), true), Repository: util.SliceContainsString(form.Events, string(webhook_module.HookEventRepository), true), Release: util.SliceContainsString(form.Events, string(webhook_module.HookEventRelease), true), + Package: util.SliceContainsString(form.Events, string(webhook_module.HookEventPackage), true), + Status: util.SliceContainsString(form.Events, string(webhook_module.HookEventStatus), true), }, BranchFilter: form.BranchFilter, }, diff --git a/services/webhook/dingtalk.go b/services/webhook/dingtalk.go index e382f5a9df732..992b8c566fad7 100644 --- a/services/webhook/dingtalk.go +++ b/services/webhook/dingtalk.go @@ -190,3 +190,7 @@ func newDingtalkRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_ var pc payloadConvertor[DingtalkPayload] = dingtalkConvertor{} return newJSONRequest(pc, w, t, true) } + +func init() { + RegisterWebhookRequester(webhook_module.DINGTALK, newDingtalkRequest) +} diff --git a/services/webhook/discord.go b/services/webhook/discord.go index c562d981680a8..30d930062eb4c 100644 --- a/services/webhook/discord.go +++ b/services/webhook/discord.go @@ -277,6 +277,10 @@ func newDiscordRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_m return newJSONRequest(pc, w, t, true) } +func init() { + RegisterWebhookRequester(webhook_module.DISCORD, newDiscordRequest) +} + func parseHookPullRequestEventType(event webhook_module.HookEventType) (string, error) { switch event { case webhook_module.HookEventPullRequestReviewApproved: diff --git a/services/webhook/feishu.go b/services/webhook/feishu.go index 7ca7d1cf5f369..4e6aebc39dc82 100644 --- a/services/webhook/feishu.go +++ b/services/webhook/feishu.go @@ -170,3 +170,7 @@ func newFeishuRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_mo var pc payloadConvertor[FeishuPayload] = feishuConvertor{} return newJSONRequest(pc, w, t, true) } + +func init() { + RegisterWebhookRequester(webhook_module.FEISHU, newFeishuRequest) +} diff --git a/services/webhook/general_test.go b/services/webhook/general_test.go index ef1ec7f324c82..ec735d785a524 100644 --- a/services/webhook/general_test.go +++ b/services/webhook/general_test.go @@ -319,8 +319,8 @@ func packageTestPayload() *api.PackagePayload { AvatarURL: "http://localhost:3000/user1/avatar", }, Repository: nil, - Organization: &api.User{ - UserName: "org1", + Organization: &api.Organization{ + Name: "org1", AvatarURL: "http://localhost:3000/org1/avatar", }, Package: &api.Package{ diff --git a/services/webhook/matrix.go b/services/webhook/matrix.go index 5e9f808d8b6cb..96dfa139aca46 100644 --- a/services/webhook/matrix.go +++ b/services/webhook/matrix.go @@ -24,6 +24,10 @@ import ( webhook_module "code.gitea.io/gitea/modules/webhook" ) +func init() { + RegisterWebhookRequester(webhook_module.MATRIX, newMatrixRequest) +} + func newMatrixRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) { meta := &MatrixMeta{} if err := json.Unmarshal([]byte(w.Meta), meta); err != nil { diff --git a/services/webhook/msteams.go b/services/webhook/msteams.go index 7ef96ffa2734c..1ae7c4f93155a 100644 --- a/services/webhook/msteams.go +++ b/services/webhook/msteams.go @@ -349,3 +349,7 @@ func newMSTeamsRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_m var pc payloadConvertor[MSTeamsPayload] = msteamsConvertor{} return newJSONRequest(pc, w, t, true) } + +func init() { + RegisterWebhookRequester(webhook_module.MSTEAMS, newMSTeamsRequest) +} diff --git a/services/webhook/notifier.go b/services/webhook/notifier.go index a3d5cb34b19d4..52a69d53b6960 100644 --- a/services/webhook/notifier.go +++ b/services/webhook/notifier.go @@ -8,6 +8,7 @@ import ( git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" + "code.gitea.io/gitea/models/organization" packages_model "code.gitea.io/gitea/models/packages" "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" @@ -924,10 +925,16 @@ func notifyPackage(ctx context.Context, sender *user_model.User, pd *packages_mo return } + var org *api.Organization + if pd.Owner.IsOrganization() { + org = convert.ToOrganization(ctx, organization.OrgFromUser(pd.Owner)) + } + if err := PrepareWebhooks(ctx, source, webhook_module.HookEventPackage, &api.PackagePayload{ - Action: action, - Package: apiPackage, - Sender: convert.ToUser(ctx, sender, nil), + Action: action, + Package: apiPackage, + Organization: org, + Sender: convert.ToUser(ctx, sender, nil), }); err != nil { log.Error("PrepareWebhooks: %v", err) } diff --git a/services/webhook/packagist.go b/services/webhook/packagist.go index 4d809ab3a6a5f..e66895832b922 100644 --- a/services/webhook/packagist.go +++ b/services/webhook/packagist.go @@ -120,3 +120,7 @@ func newPackagistRequest(_ context.Context, w *webhook_model.Webhook, t *webhook } return newJSONRequest(pc, w, t, true) } + +func init() { + RegisterWebhookRequester(webhook_module.PACKAGIST, newPackagistRequest) +} diff --git a/services/webhook/slack.go b/services/webhook/slack.go index c905e7a89f48f..e0e938d53db25 100644 --- a/services/webhook/slack.go +++ b/services/webhook/slack.go @@ -295,6 +295,10 @@ func newSlackRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_mod return newJSONRequest(pc, w, t, true) } +func init() { + RegisterWebhookRequester(webhook_module.SLACK, newSlackRequest) +} + var slackChannel = regexp.MustCompile(`^#?[a-z0-9_-]{1,80}$`) // IsValidSlackChannel validates a channel name conforms to what slack expects: diff --git a/services/webhook/telegram.go b/services/webhook/telegram.go index e54d6f2947d21..6fbf995801cbd 100644 --- a/services/webhook/telegram.go +++ b/services/webhook/telegram.go @@ -187,3 +187,7 @@ func newTelegramRequest(_ context.Context, w *webhook_model.Webhook, t *webhook_ var pc payloadConvertor[TelegramPayload] = telegramConvertor{} return newJSONRequest(pc, w, t, true) } + +func init() { + RegisterWebhookRequester(webhook_module.TELEGRAM, newTelegramRequest) +} diff --git a/services/webhook/webhook.go b/services/webhook/webhook.go index e0e8fa2fc19b5..b5e0864f15dee 100644 --- a/services/webhook/webhook.go +++ b/services/webhook/webhook.go @@ -27,16 +27,12 @@ import ( "github.com/gobwas/glob" ) -var webhookRequesters = map[webhook_module.HookType]func(context.Context, *webhook_model.Webhook, *webhook_model.HookTask) (req *http.Request, body []byte, err error){ - webhook_module.SLACK: newSlackRequest, - webhook_module.DISCORD: newDiscordRequest, - webhook_module.DINGTALK: newDingtalkRequest, - webhook_module.TELEGRAM: newTelegramRequest, - webhook_module.MSTEAMS: newMSTeamsRequest, - webhook_module.FEISHU: newFeishuRequest, - webhook_module.MATRIX: newMatrixRequest, - webhook_module.WECHATWORK: newWechatworkRequest, - webhook_module.PACKAGIST: newPackagistRequest, +type Requester func(context.Context, *webhook_model.Webhook, *webhook_model.HookTask) (req *http.Request, body []byte, err error) + +var webhookRequesters = map[webhook_module.HookType]Requester{} + +func RegisterWebhookRequester(hookType webhook_module.HookType, requester Requester) { + webhookRequesters[hookType] = requester } // IsValidHookTaskType returns true if a webhook registered diff --git a/services/webhook/wechatwork.go b/services/webhook/wechatwork.go index 1d8c1d7dacd83..44e0ff7de51e5 100644 --- a/services/webhook/wechatwork.go +++ b/services/webhook/wechatwork.go @@ -179,3 +179,7 @@ func newWechatworkRequest(_ context.Context, w *webhook_model.Webhook, t *webhoo var pc payloadConvertor[WechatworkPayload] = wechatworkConvertor{} return newJSONRequest(pc, w, t, true) } + +func init() { + RegisterWebhookRequester(webhook_module.WECHATWORK, newWechatworkRequest) +} diff --git a/tests/integration/api_repo_test.go b/tests/integration/api_repo_test.go index 122afbfa08fb1..aae038d51e406 100644 --- a/tests/integration/api_repo_test.go +++ b/tests/integration/api_repo_test.go @@ -471,6 +471,15 @@ func TestAPIMirrorSyncNonMirrorRepo(t *testing.T) { assert.Equal(t, "Repository is not a mirror", errRespJSON["message"]) } +func testAPIOrgCreateRepo(t *testing.T, session *TestSession, orgName, repoName string, status int) { + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization, auth_model.AccessTokenScopeWriteRepository) + + req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/org/%s/repos", orgName), &api.CreateRepoOption{ + Name: repoName, + }).AddTokenAuth(token) + MakeRequest(t, req, status) +} + func TestAPIOrgRepoCreate(t *testing.T) { testCases := []struct { ctxUserID int64 @@ -488,11 +497,7 @@ func TestAPIOrgRepoCreate(t *testing.T) { for _, testCase := range testCases { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: testCase.ctxUserID}) session := loginUser(t, user.Name) - token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization, auth_model.AccessTokenScopeWriteRepository) - req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/org/%s/repos", testCase.orgName), &api.CreateRepoOption{ - Name: testCase.repoName, - }).AddTokenAuth(token) - MakeRequest(t, req, testCase.expectedStatus) + testAPIOrgCreateRepo(t, session, testCase.orgName, testCase.repoName, testCase.expectedStatus) } } diff --git a/tests/integration/api_wiki_test.go b/tests/integration/api_wiki_test.go index 05d90fc4e371d..8e5f67e2822bc 100644 --- a/tests/integration/api_wiki_test.go +++ b/tests/integration/api_wiki_test.go @@ -172,6 +172,19 @@ func TestAPIListWikiPages(t *testing.T) { assert.Equal(t, dummymeta, meta) } +func testAPICreateWikiPage(t *testing.T, session *TestSession, userName, repoName, title string, status int) { + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) + + urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/new", userName, repoName) + + req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateWikiPageOptions{ + Title: title, + ContentBase64: base64.StdEncoding.EncodeToString([]byte("Wiki page content for API unit tests")), + Message: "", + }).AddTokenAuth(token) + MakeRequest(t, req, status) +} + func TestAPINewWikiPage(t *testing.T) { for _, title := range []string{ "New page", @@ -180,16 +193,7 @@ func TestAPINewWikiPage(t *testing.T) { defer tests.PrepareTestEnv(t)() username := "user2" session := loginUser(t, username) - token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) - - urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/new", username, "repo1") - - req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateWikiPageOptions{ - Title: title, - ContentBase64: base64.StdEncoding.EncodeToString([]byte("Wiki page content for API unit tests")), - Message: "", - }).AddTokenAuth(token) - MakeRequest(t, req, http.StatusCreated) + testAPICreateWikiPage(t, session, username, "repo1", title, http.StatusCreated) } } diff --git a/tests/integration/issue_test.go b/tests/integration/issue_test.go index 4617c5f89a149..bd0cedd300baf 100644 --- a/tests/integration/issue_test.go +++ b/tests/integration/issue_test.go @@ -174,7 +174,7 @@ func testIssueAddComment(t *testing.T, session *TestSession, issueURL, content, htmlDoc = NewHTMLParser(t, resp.Body) - val := htmlDoc.doc.Find(".comment-list .comment .render-content p").Eq(commentCount).Text() + val := strings.TrimSpace(htmlDoc.doc.Find(".comment-list .comment .render-content").Eq(commentCount).Text()) assert.Equal(t, content, val) idAttr, has := htmlDoc.doc.Find(".comment-list .comment").Eq(commentCount).Attr("id") diff --git a/tests/integration/repo_webhook_test.go b/tests/integration/repo_webhook_test.go index ef44a9e2d0fb4..5a50d7d4914f1 100644 --- a/tests/integration/repo_webhook_test.go +++ b/tests/integration/repo_webhook_test.go @@ -4,10 +4,23 @@ package integration import ( + "context" + "fmt" + "io" "net/http" + "net/http/httptest" + "net/url" "strings" "testing" + auth_model "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unittest" + "code.gitea.io/gitea/models/webhook" + "code.gitea.io/gitea/modules/gitrepo" + "code.gitea.io/gitea/modules/json" + api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" "code.gitea.io/gitea/tests" "github.com/PuerkitoBio/goquery" @@ -39,3 +52,555 @@ func TestNewWebHookLink(t *testing.T) { }) } } + +func testAPICreateWebhookForRepo(t *testing.T, session *TestSession, userName, repoName, url, event string) { + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAll) + req := NewRequestWithJSON(t, "POST", "/api/v1/repos/"+userName+"/"+repoName+"/hooks", api.CreateHookOption{ + Type: "gitea", + Config: api.CreateHookOptionConfig{ + "content_type": "json", + "url": url, + }, + Events: []string{event}, + Active: true, + }).AddTokenAuth(token) + MakeRequest(t, req, http.StatusCreated) +} + +func testCreateWebhookForRepo(t *testing.T, session *TestSession, webhookType, userName, repoName, url, eventKind string) { + csrf := GetUserCSRFToken(t, session) + req := NewRequestWithValues(t, "POST", "/"+userName+"/"+repoName+"/settings/hooks/"+webhookType+"/new", map[string]string{ + "_csrf": csrf, + "payload_url": url, + "events": eventKind, + "active": "true", + "content_type": fmt.Sprintf("%d", webhook.ContentTypeJSON), + "http_method": "POST", + }) + session.MakeRequest(t, req, http.StatusSeeOther) +} + +func testAPICreateWebhookForOrg(t *testing.T, session *TestSession, userName, url, event string) { + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAll) + req := NewRequestWithJSON(t, "POST", "/api/v1/orgs/"+userName+"/hooks", api.CreateHookOption{ + Type: "gitea", + Config: api.CreateHookOptionConfig{ + "content_type": "json", + "url": url, + }, + Events: []string{event}, + Active: true, + }).AddTokenAuth(token) + MakeRequest(t, req, http.StatusCreated) +} + +type mockWebhookProvider struct { + server *httptest.Server +} + +func newMockWebhookProvider(callback func(r *http.Request), status int) *mockWebhookProvider { + m := &mockWebhookProvider{} + m.server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + callback(r) + w.WriteHeader(status) + })) + return m +} + +func (m *mockWebhookProvider) URL() string { + if m.server == nil { + return "" + } + return m.server.URL +} + +// Close closes the mock webhook http server +func (m *mockWebhookProvider) Close() { + if m.server != nil { + m.server.Close() + m.server = nil + } +} + +func Test_WebhookCreate(t *testing.T) { + var payloads []api.CreatePayload + var triggeredEvent string + provider := newMockWebhookProvider(func(r *http.Request) { + content, _ := io.ReadAll(r.Body) + var payload api.CreatePayload + err := json.Unmarshal(content, &payload) + assert.NoError(t, err) + payloads = append(payloads, payload) + triggeredEvent = string(webhook_module.HookEventCreate) + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // 1. create a new webhook with special webhook for repo1 + session := loginUser(t, "user2") + + testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "create") + + // 2. trigger the webhook + testAPICreateBranch(t, session, "user2", "repo1", "master", "master2", http.StatusCreated) + + // 3. validate the webhook is triggered + assert.Len(t, payloads, 1) + assert.EqualValues(t, string(webhook_module.HookEventCreate), triggeredEvent) + assert.EqualValues(t, "repo1", payloads[0].Repo.Name) + assert.EqualValues(t, "user2/repo1", payloads[0].Repo.FullName) + assert.EqualValues(t, "master2", payloads[0].Ref) + assert.EqualValues(t, "branch", payloads[0].RefType) + }) +} + +func Test_WebhookDelete(t *testing.T) { + var payloads []api.DeletePayload + var triggeredEvent string + provider := newMockWebhookProvider(func(r *http.Request) { + content, _ := io.ReadAll(r.Body) + var payload api.DeletePayload + err := json.Unmarshal(content, &payload) + assert.NoError(t, err) + payloads = append(payloads, payload) + triggeredEvent = "delete" + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // 1. create a new webhook with special webhook for repo1 + session := loginUser(t, "user2") + + testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "delete") + + // 2. trigger the webhook + testAPICreateBranch(t, session, "user2", "repo1", "master", "master2", http.StatusCreated) + testAPIDeleteBranch(t, "master2", http.StatusNoContent) + + // 3. validate the webhook is triggered + assert.EqualValues(t, "delete", triggeredEvent) + assert.Len(t, payloads, 1) + assert.EqualValues(t, "repo1", payloads[0].Repo.Name) + assert.EqualValues(t, "user2/repo1", payloads[0].Repo.FullName) + assert.EqualValues(t, "master2", payloads[0].Ref) + assert.EqualValues(t, "branch", payloads[0].RefType) + }) +} + +func Test_WebhookFork(t *testing.T) { + var payloads []api.ForkPayload + var triggeredEvent string + provider := newMockWebhookProvider(func(r *http.Request) { + content, _ := io.ReadAll(r.Body) + var payload api.ForkPayload + err := json.Unmarshal(content, &payload) + assert.NoError(t, err) + payloads = append(payloads, payload) + triggeredEvent = "fork" + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // 1. create a new webhook with special webhook for repo1 + session := loginUser(t, "user1") + + testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "fork") + + // 2. trigger the webhook + testRepoFork(t, session, "user2", "repo1", "user1", "repo1-fork", "master") + + // 3. validate the webhook is triggered + assert.EqualValues(t, "fork", triggeredEvent) + assert.Len(t, payloads, 1) + assert.EqualValues(t, "repo1-fork", payloads[0].Repo.Name) + assert.EqualValues(t, "user1/repo1-fork", payloads[0].Repo.FullName) + assert.EqualValues(t, "repo1", payloads[0].Forkee.Name) + assert.EqualValues(t, "user2/repo1", payloads[0].Forkee.FullName) + }) +} + +func Test_WebhookIssueComment(t *testing.T) { + var payloads []api.IssueCommentPayload + var triggeredEvent string + provider := newMockWebhookProvider(func(r *http.Request) { + content, _ := io.ReadAll(r.Body) + var payload api.IssueCommentPayload + err := json.Unmarshal(content, &payload) + assert.NoError(t, err) + payloads = append(payloads, payload) + triggeredEvent = "issue_comment" + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // 1. create a new webhook with special webhook for repo1 + session := loginUser(t, "user2") + + testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "issue_comment") + + // 2. trigger the webhook + issueURL := testNewIssue(t, session, "user2", "repo1", "Title2", "Description2") + testIssueAddComment(t, session, issueURL, "issue title2 comment1", "") + + // 3. validate the webhook is triggered + assert.EqualValues(t, "issue_comment", triggeredEvent) + assert.Len(t, payloads, 1) + assert.EqualValues(t, "created", payloads[0].Action) + assert.EqualValues(t, "repo1", payloads[0].Issue.Repo.Name) + assert.EqualValues(t, "user2/repo1", payloads[0].Issue.Repo.FullName) + assert.EqualValues(t, "Title2", payloads[0].Issue.Title) + assert.EqualValues(t, "Description2", payloads[0].Issue.Body) + assert.EqualValues(t, "issue title2 comment1", payloads[0].Comment.Body) + }) +} + +func Test_WebhookRelease(t *testing.T) { + var payloads []api.ReleasePayload + var triggeredEvent string + provider := newMockWebhookProvider(func(r *http.Request) { + content, _ := io.ReadAll(r.Body) + var payload api.ReleasePayload + err := json.Unmarshal(content, &payload) + assert.NoError(t, err) + payloads = append(payloads, payload) + triggeredEvent = "release" + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // 1. create a new webhook with special webhook for repo1 + session := loginUser(t, "user2") + + testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "release") + + // 2. trigger the webhook + createNewRelease(t, session, "/user2/repo1", "v0.0.99", "v0.0.99", false, false) + + // 3. validate the webhook is triggered + assert.EqualValues(t, "release", triggeredEvent) + assert.Len(t, payloads, 1) + assert.EqualValues(t, "repo1", payloads[0].Repository.Name) + assert.EqualValues(t, "user2/repo1", payloads[0].Repository.FullName) + assert.EqualValues(t, "v0.0.99", payloads[0].Release.TagName) + assert.False(t, payloads[0].Release.IsDraft) + assert.False(t, payloads[0].Release.IsPrerelease) + }) +} + +func Test_WebhookPush(t *testing.T) { + var payloads []api.PushPayload + var triggeredEvent string + provider := newMockWebhookProvider(func(r *http.Request) { + content, _ := io.ReadAll(r.Body) + var payload api.PushPayload + err := json.Unmarshal(content, &payload) + assert.NoError(t, err) + payloads = append(payloads, payload) + triggeredEvent = "push" + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // 1. create a new webhook with special webhook for repo1 + session := loginUser(t, "user2") + + testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "push") + + // 2. trigger the webhook + testCreateFile(t, session, "user2", "repo1", "master", "test_webhook_push.md", "# a test file for webhook push") + + // 3. validate the webhook is triggered + assert.EqualValues(t, "push", triggeredEvent) + assert.Len(t, payloads, 1) + assert.EqualValues(t, "repo1", payloads[0].Repo.Name) + assert.EqualValues(t, "user2/repo1", payloads[0].Repo.FullName) + assert.Len(t, payloads[0].Commits, 1) + assert.EqualValues(t, []string{"test_webhook_push.md"}, payloads[0].Commits[0].Added) + }) +} + +func Test_WebhookIssue(t *testing.T) { + var payloads []api.IssuePayload + var triggeredEvent string + provider := newMockWebhookProvider(func(r *http.Request) { + content, _ := io.ReadAll(r.Body) + var payload api.IssuePayload + err := json.Unmarshal(content, &payload) + assert.NoError(t, err) + payloads = append(payloads, payload) + triggeredEvent = "issues" + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // 1. create a new webhook with special webhook for repo1 + session := loginUser(t, "user2") + + testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "issues") + + // 2. trigger the webhook + testNewIssue(t, session, "user2", "repo1", "Title1", "Description1") + + // 3. validate the webhook is triggered + assert.EqualValues(t, "issues", triggeredEvent) + assert.Len(t, payloads, 1) + assert.EqualValues(t, "opened", payloads[0].Action) + assert.EqualValues(t, "repo1", payloads[0].Issue.Repo.Name) + assert.EqualValues(t, "user2/repo1", payloads[0].Issue.Repo.FullName) + assert.EqualValues(t, "Title1", payloads[0].Issue.Title) + assert.EqualValues(t, "Description1", payloads[0].Issue.Body) + }) +} + +func Test_WebhookPullRequest(t *testing.T) { + var payloads []api.PullRequestPayload + var triggeredEvent string + provider := newMockWebhookProvider(func(r *http.Request) { + content, _ := io.ReadAll(r.Body) + var payload api.PullRequestPayload + err := json.Unmarshal(content, &payload) + assert.NoError(t, err) + payloads = append(payloads, payload) + triggeredEvent = "pull_request" + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // 1. create a new webhook with special webhook for repo1 + session := loginUser(t, "user2") + + testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "pull_request") + + testAPICreateBranch(t, session, "user2", "repo1", "master", "master2", http.StatusCreated) + // 2. trigger the webhook + repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1}) + testCreatePullToDefaultBranch(t, session, repo1, repo1, "master2", "first pull request") + + // 3. validate the webhook is triggered + assert.EqualValues(t, "pull_request", triggeredEvent) + assert.Len(t, payloads, 1) + assert.EqualValues(t, "repo1", payloads[0].PullRequest.Base.Repository.Name) + assert.EqualValues(t, "user2/repo1", payloads[0].PullRequest.Base.Repository.FullName) + assert.EqualValues(t, "repo1", payloads[0].PullRequest.Head.Repository.Name) + assert.EqualValues(t, "user2/repo1", payloads[0].PullRequest.Head.Repository.FullName) + assert.EqualValues(t, 0, payloads[0].PullRequest.Additions) + }) +} + +func Test_WebhookPullRequestComment(t *testing.T) { + var payloads []api.IssueCommentPayload + var triggeredEvent string + provider := newMockWebhookProvider(func(r *http.Request) { + content, _ := io.ReadAll(r.Body) + var payload api.IssueCommentPayload + err := json.Unmarshal(content, &payload) + assert.NoError(t, err) + payloads = append(payloads, payload) + triggeredEvent = "pull_request_comment" + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // 1. create a new webhook with special webhook for repo1 + session := loginUser(t, "user2") + + testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "pull_request_comment") + + // 2. trigger the webhook + testAPICreateBranch(t, session, "user2", "repo1", "master", "master2", http.StatusCreated) + repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1}) + prID := testCreatePullToDefaultBranch(t, session, repo1, repo1, "master2", "first pull request") + + testIssueAddComment(t, session, "/user2/repo1/pulls/"+prID, "pull title2 comment1", "") + + // 3. validate the webhook is triggered + assert.EqualValues(t, "pull_request_comment", triggeredEvent) + assert.Len(t, payloads, 1) + assert.EqualValues(t, "created", payloads[0].Action) + assert.EqualValues(t, "repo1", payloads[0].Issue.Repo.Name) + assert.EqualValues(t, "user2/repo1", payloads[0].Issue.Repo.FullName) + assert.EqualValues(t, "first pull request", payloads[0].Issue.Title) + assert.EqualValues(t, "", payloads[0].Issue.Body) + assert.EqualValues(t, "pull title2 comment1", payloads[0].Comment.Body) + }) +} + +func Test_WebhookWiki(t *testing.T) { + var payloads []api.WikiPayload + var triggeredEvent string + provider := newMockWebhookProvider(func(r *http.Request) { + content, _ := io.ReadAll(r.Body) + var payload api.WikiPayload + err := json.Unmarshal(content, &payload) + assert.NoError(t, err) + payloads = append(payloads, payload) + triggeredEvent = "wiki" + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // 1. create a new webhook with special webhook for repo1 + session := loginUser(t, "user2") + + testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "wiki") + + // 2. trigger the webhook + testAPICreateWikiPage(t, session, "user2", "repo1", "Test Wiki Page", http.StatusCreated) + + // 3. validate the webhook is triggered + assert.EqualValues(t, "wiki", triggeredEvent) + assert.Len(t, payloads, 1) + assert.EqualValues(t, "created", payloads[0].Action) + assert.EqualValues(t, "repo1", payloads[0].Repository.Name) + assert.EqualValues(t, "user2/repo1", payloads[0].Repository.FullName) + assert.EqualValues(t, "Test-Wiki-Page", payloads[0].Page) + }) +} + +func Test_WebhookRepository(t *testing.T) { + var payloads []api.RepositoryPayload + var triggeredEvent string + provider := newMockWebhookProvider(func(r *http.Request) { + content, _ := io.ReadAll(r.Body) + var payload api.RepositoryPayload + err := json.Unmarshal(content, &payload) + assert.NoError(t, err) + payloads = append(payloads, payload) + triggeredEvent = "repository" + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // 1. create a new webhook with special webhook for repo1 + session := loginUser(t, "user1") + + testAPICreateWebhookForOrg(t, session, "org3", provider.URL(), "repository") + + // 2. trigger the webhook + testAPIOrgCreateRepo(t, session, "org3", "repo_new", http.StatusCreated) + + // 3. validate the webhook is triggered + assert.EqualValues(t, "repository", triggeredEvent) + assert.Len(t, payloads, 1) + assert.EqualValues(t, "created", payloads[0].Action) + assert.EqualValues(t, "org3", payloads[0].Organization.UserName) + assert.EqualValues(t, "repo_new", payloads[0].Repository.Name) + assert.EqualValues(t, "org3/repo_new", payloads[0].Repository.FullName) + }) +} + +func Test_WebhookPackage(t *testing.T) { + var payloads []api.PackagePayload + var triggeredEvent string + provider := newMockWebhookProvider(func(r *http.Request) { + content, _ := io.ReadAll(r.Body) + var payload api.PackagePayload + err := json.Unmarshal(content, &payload) + assert.NoError(t, err) + payloads = append(payloads, payload) + triggeredEvent = "package" + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // 1. create a new webhook with special webhook for repo1 + session := loginUser(t, "user1") + + testAPICreateWebhookForOrg(t, session, "org3", provider.URL(), "package") + + // 2. trigger the webhook + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAll) + url := fmt.Sprintf("/api/packages/%s/generic/%s/%s", "org3", "gitea", "v1.24.0") + req := NewRequestWithBody(t, "PUT", url+"/gitea", strings.NewReader("This is a dummy file")). + AddTokenAuth(token) + MakeRequest(t, req, http.StatusCreated) + + // 3. validate the webhook is triggered + assert.EqualValues(t, "package", triggeredEvent) + assert.Len(t, payloads, 1) + assert.EqualValues(t, "created", payloads[0].Action) + assert.EqualValues(t, "gitea", payloads[0].Package.Name) + assert.EqualValues(t, "generic", payloads[0].Package.Type) + assert.EqualValues(t, "org3", payloads[0].Organization.UserName) + assert.EqualValues(t, "v1.24.0", payloads[0].Package.Version) + }) +} + +func Test_WebhookStatus(t *testing.T) { + var payloads []api.CommitStatusPayload + var triggeredEvent string + provider := newMockWebhookProvider(func(r *http.Request) { + assert.Contains(t, r.Header["X-Github-Event-Type"], "status", "X-GitHub-Event-Type should contain status") + assert.Contains(t, r.Header["X-Gitea-Event-Type"], "status", "X-Gitea-Event-Type should contain status") + assert.Contains(t, r.Header["X-Gogs-Event-Type"], "status", "X-Gogs-Event-Type should contain status") + assert.Contains(t, r.Header["X-Github-Event"], "status", "X-GitHub-Event should contain status") + assert.Contains(t, r.Header["X-Gitea-Event"], "status", "X-Gitea-Event should contain status") + assert.Contains(t, r.Header["X-Gogs-Event"], "status", "X-Gogs-Event should contain status") + content, _ := io.ReadAll(r.Body) + var payload api.CommitStatusPayload + err := json.Unmarshal(content, &payload) + assert.NoError(t, err) + payloads = append(payloads, payload) + triggeredEvent = "status" + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // 1. create a new webhook with special webhook for repo1 + session := loginUser(t, "user2") + + testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "status") + + repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1}) + + gitRepo1, err := gitrepo.OpenRepository(context.Background(), repo1) + assert.NoError(t, err) + commitID, err := gitRepo1.GetBranchCommitID(repo1.DefaultBranch) + assert.NoError(t, err) + + // 2. trigger the webhook + testCtx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeAll) + + // update a status for a commit via API + doAPICreateCommitStatus(testCtx, commitID, api.CreateStatusOption{ + State: api.CommitStatusSuccess, + TargetURL: "http://test.ci/", + Description: "", + Context: "testci", + })(t) + + // 3. validate the webhook is triggered + assert.EqualValues(t, "status", triggeredEvent) + assert.Len(t, payloads, 1) + assert.EqualValues(t, commitID, payloads[0].Commit.ID) + assert.EqualValues(t, "repo1", payloads[0].Repo.Name) + assert.EqualValues(t, "user2/repo1", payloads[0].Repo.FullName) + assert.EqualValues(t, "testci", payloads[0].Context) + assert.EqualValues(t, commitID, payloads[0].SHA) + }) +} + +func Test_WebhookStatus_NoWrongTrigger(t *testing.T) { + var trigger string + provider := newMockWebhookProvider(func(r *http.Request) { + assert.NotContains(t, r.Header["X-Github-Event-Type"], "status", "X-GitHub-Event-Type should not contain status") + assert.NotContains(t, r.Header["X-Gitea-Event-Type"], "status", "X-Gitea-Event-Type should not contain status") + assert.NotContains(t, r.Header["X-Gogs-Event-Type"], "status", "X-Gogs-Event-Type should not contain status") + trigger = "push" + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // 1. create a new webhook with special webhook for repo1 + session := loginUser(t, "user2") + + // create a push_only webhook from web UI + testCreateWebhookForRepo(t, session, "gitea", "user2", "repo1", provider.URL(), "push_only") + + // 2. trigger the webhook with a push action + testCreateFile(t, session, "user2", "repo1", "master", "test_webhook_push.md", "# a test file for webhook push") + + // 3. validate the webhook is triggered with right event + assert.EqualValues(t, "push", trigger) + }) +} diff --git a/tests/mssql.ini.tmpl b/tests/mssql.ini.tmpl index 77c969e813611..8b1593a396f9e 100644 --- a/tests/mssql.ini.tmpl +++ b/tests/mssql.ini.tmpl @@ -26,6 +26,9 @@ TYPE = immediate [queue.push_update] TYPE = immediate +[queue.webhook_sender] +TYPE = immediate + [repository] ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/gitea-repositories @@ -112,3 +115,6 @@ ENABLED = true [actions] ENABLED = true + +[webhook] +ALLOWED_HOST_LIST = 127.0.0.1 diff --git a/tests/mysql.ini.tmpl b/tests/mysql.ini.tmpl index 0fddde46de69e..8cafba9591382 100644 --- a/tests/mysql.ini.tmpl +++ b/tests/mysql.ini.tmpl @@ -28,6 +28,9 @@ TYPE = immediate [queue.push_update] TYPE = immediate +[queue.webhook_sender] +TYPE = immediate + [repository] ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/gitea-repositories @@ -119,3 +122,6 @@ REPLY_TO_ADDRESS = incoming+%{token}@localhost [actions] ENABLED = true + +[webhook] +ALLOWED_HOST_LIST = 127.0.0.1 diff --git a/tests/pgsql.ini.tmpl b/tests/pgsql.ini.tmpl index 695662c2e9d2e..fb881d411c7ad 100644 --- a/tests/pgsql.ini.tmpl +++ b/tests/pgsql.ini.tmpl @@ -27,6 +27,9 @@ TYPE = immediate [queue.push_update] TYPE = immediate +[queue.webhook_sender] +TYPE = immediate + [repository] ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/gitea-repositories @@ -128,3 +131,6 @@ ENABLED = true [actions] ENABLED = true + +[webhook] +ALLOWED_HOST_LIST = 127.0.0.1 diff --git a/tests/sqlite.ini.tmpl b/tests/sqlite.ini.tmpl index 1cbcd8b2e591a..c0b3e1c85979c 100644 --- a/tests/sqlite.ini.tmpl +++ b/tests/sqlite.ini.tmpl @@ -22,6 +22,9 @@ TYPE = immediate [queue.push_update] TYPE = immediate +[queue.webhook_sender] +TYPE = immediate + [repository] ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/gitea-repositories @@ -117,3 +120,6 @@ RENDER_CONTENT_MODE=sanitized [actions] ENABLED = true + +[webhook] +ALLOWED_HOST_LIST = 127.0.0.1