aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--modules/structs/hook.go60
-rw-r--r--routers/api/v1/utils/hook.go2
-rw-r--r--services/webhook/dingtalk.go4
-rw-r--r--services/webhook/discord.go4
-rw-r--r--services/webhook/feishu.go4
-rw-r--r--services/webhook/general_test.go4
-rw-r--r--services/webhook/matrix.go4
-rw-r--r--services/webhook/msteams.go4
-rw-r--r--services/webhook/notifier.go13
-rw-r--r--services/webhook/packagist.go4
-rw-r--r--services/webhook/slack.go4
-rw-r--r--services/webhook/telegram.go4
-rw-r--r--services/webhook/webhook.go16
-rw-r--r--services/webhook/wechatwork.go4
-rw-r--r--tests/integration/api_repo_test.go15
-rw-r--r--tests/integration/api_wiki_test.go24
-rw-r--r--tests/integration/issue_test.go2
-rw-r--r--tests/integration/repo_webhook_test.go523
-rw-r--r--tests/mssql.ini.tmpl6
-rw-r--r--tests/mysql.ini.tmpl6
-rw-r--r--tests/pgsql.ini.tmpl6
-rw-r--r--tests/sqlite.ini.tmpl6
22 files changed, 630 insertions, 89 deletions
diff --git a/modules/structs/hook.go b/modules/structs/hook.go
index ce5742e5c7..cef2dbd712 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/routers/api/v1/utils/hook.go b/routers/api/v1/utils/hook.go
index 148fe64992..2ad9eeb0ec 100644
--- a/routers/api/v1/utils/hook.go
+++ b/routers/api/v1/utils/hook.go
@@ -205,6 +205,7 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, ownerID, repoI
webhook_module.HookEventWiki: util.SliceContainsString(form.Events, string(webhook_module.HookEventWiki), true),
webhook_module.HookEventRepository: util.SliceContainsString(form.Events, string(webhook_module.HookEventRepository), true),
webhook_module.HookEventRelease: util.SliceContainsString(form.Events, string(webhook_module.HookEventRelease), true),
+ webhook_module.HookEventPackage: util.SliceContainsString(form.Events, string(webhook_module.HookEventPackage), true),
webhook_module.HookEventStatus: util.SliceContainsString(form.Events, string(webhook_module.HookEventStatus), true),
},
BranchFilter: form.BranchFilter,
@@ -384,6 +385,7 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *webhook.Webh
w.HookEvents[webhook_module.HookEventPullRequestAssign] = pullHook(form.Events, string(webhook_module.HookEventPullRequestAssign))
w.HookEvents[webhook_module.HookEventPullRequestLabel] = pullHook(form.Events, string(webhook_module.HookEventPullRequestLabel))
w.HookEvents[webhook_module.HookEventPullRequestMilestone] = pullHook(form.Events, string(webhook_module.HookEventPullRequestMilestone))
+ w.HookEvents[webhook_module.HookEventPullRequestComment] = pullHook(form.Events, string(webhook_module.HookEventPullRequestComment))
w.HookEvents[webhook_module.HookEventPullRequestReview] = pullHook(form.Events, "pull_request_review")
w.HookEvents[webhook_module.HookEventPullRequestReviewRequest] = pullHook(form.Events, string(webhook_module.HookEventPullRequestReviewRequest))
w.HookEvents[webhook_module.HookEventPullRequestSync] = pullHook(form.Events, string(webhook_module.HookEventPullRequestSync))
diff --git a/services/webhook/dingtalk.go b/services/webhook/dingtalk.go
index e382f5a9df..992b8c566f 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 c562d98168..30d930062e 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 7ca7d1cf5f..4e6aebc39d 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 ef1ec7f324..ec735d785a 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 5e9f808d8b..96dfa139ac 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 7ef96ffa27..1ae7c4f931 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 2fce4b351e..6c691c21f4 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"
@@ -920,10 +921,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 4d809ab3a6..e66895832b 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 2a49df2453..0371ee23e6 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 e54d6f2947..6fbf995801 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 b4609e8a51..182078b39d 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 1d8c1d7dac..44e0ff7de5 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 13dc90f8a7..22f26d87d4 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 05d90fc4e3..8e5f67e282 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 4617c5f89a..bd0cedd300 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 ef44a9e2d0..17905513c3 100644
--- a/tests/integration/repo_webhook_test.go
+++ b/tests/integration/repo_webhook_test.go
@@ -4,10 +4,22 @@
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/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 +51,514 @@ 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 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")
+ 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)
+ })
+}
diff --git a/tests/mssql.ini.tmpl b/tests/mssql.ini.tmpl
index b50816b2cd..ffba516ed3 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
@@ -111,3 +114,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 ec8307acc3..e2f2e1390a 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
@@ -118,3 +121,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 139ea9c2b7..483b9ed0cd 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
@@ -127,3 +130,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 2f7a3e8182..e837860c26 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
@@ -116,3 +119,6 @@ RENDER_CONTENT_MODE=sanitized
[actions]
ENABLED = true
+
+[webhook]
+ALLOWED_HOST_LIST = 127.0.0.1