Skip to content

Commit 47c395d

Browse files
committed
refactor webhook payload optimization: switch from bool to limit number
1 parent 1915361 commit 47c395d

File tree

9 files changed

+125
-101
lines changed

9 files changed

+125
-101
lines changed

models/migrations/v1_24/v321.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import (
99

1010
func AddWebhookPayloadOptimizationColumns(x *xorm.Engine) error {
1111
type Webhook struct {
12-
ExcludeFiles bool `xorm:"exclude_files NOT NULL DEFAULT false"`
13-
ExcludeCommits bool `xorm:"exclude_commits NOT NULL DEFAULT false"`
12+
ExcludeFilesLimit int `xorm:"exclude_files_limit NOT NULL DEFAULT 0"`
13+
ExcludeCommitsLimit int `xorm:"exclude_commits_limit NOT NULL DEFAULT 0"`
1414
}
1515
_, err := x.SyncWithOptions(
1616
xorm.SyncOptions{

models/webhook/webhook.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ type Webhook struct {
140140
HeaderAuthorizationEncrypted string `xorm:"TEXT"`
141141

142142
// Payload size optimization options
143-
ExcludeFiles bool `xorm:"exclude_files"` // Exclude file changes from commit payloads
144-
ExcludeCommits bool `xorm:"exclude_commits"` // Exclude commits and head_commit from push payloads
143+
ExcludeFilesLimit int `xorm:"exclude_files_limit"` // Limit number of file changes in commit payloads, 0 means unlimited
144+
ExcludeCommitsLimit int `xorm:"exclude_commits_limit"` // Limit number of commits in push payloads, 0 means unlimited
145145

146146
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
147147
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`

models/webhook/webhook_test.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -335,15 +335,15 @@ func TestWebhookPayloadOptimization(t *testing.T) {
335335
assert.NoError(t, unittest.PrepareTestDatabase())
336336

337337
webhook := &Webhook{
338-
RepoID: 1,
339-
URL: "http://example.com/webhook",
340-
HTTPMethod: "POST",
341-
ContentType: ContentTypeJSON,
342-
Secret: "secret",
343-
IsActive: true,
344-
Type: webhook_module.GITEA,
345-
ExcludeFiles: true,
346-
ExcludeCommits: false,
338+
RepoID: 1,
339+
URL: "http://example.com/webhook",
340+
HTTPMethod: "POST",
341+
ContentType: ContentTypeJSON,
342+
Secret: "secret",
343+
IsActive: true,
344+
Type: webhook_module.GITEA,
345+
ExcludeFilesLimit: 1,
346+
ExcludeCommitsLimit: 0,
347347
HookEvent: &webhook_module.HookEvent{
348348
PushOnly: true,
349349
},
@@ -357,18 +357,18 @@ func TestWebhookPayloadOptimization(t *testing.T) {
357357
// Test retrieving webhook and checking payload optimization options
358358
retrievedWebhook, err := GetWebhookByID(db.DefaultContext, webhook.ID)
359359
assert.NoError(t, err)
360-
assert.True(t, retrievedWebhook.ExcludeFiles)
361-
assert.False(t, retrievedWebhook.ExcludeCommits)
360+
assert.Equal(t, 1, retrievedWebhook.ExcludeFilesLimit)
361+
assert.Equal(t, 0, retrievedWebhook.ExcludeCommitsLimit)
362362

363363
// Test updating webhook with different payload optimization options
364-
retrievedWebhook.ExcludeFiles = false
365-
retrievedWebhook.ExcludeCommits = true
364+
retrievedWebhook.ExcludeFilesLimit = 0
365+
retrievedWebhook.ExcludeCommitsLimit = 2
366366
err = UpdateWebhook(db.DefaultContext, retrievedWebhook)
367367
assert.NoError(t, err)
368368

369369
// Verify the update
370370
updatedWebhook, err := GetWebhookByID(db.DefaultContext, webhook.ID)
371371
assert.NoError(t, err)
372-
assert.False(t, updatedWebhook.ExcludeFiles)
373-
assert.True(t, updatedWebhook.ExcludeCommits)
372+
assert.Equal(t, 0, updatedWebhook.ExcludeFilesLimit)
373+
assert.Equal(t, 2, updatedWebhook.ExcludeCommitsLimit)
374374
}

options/locale/locale_en-US.ini

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2425,10 +2425,10 @@ settings.event_package_desc = Package created or deleted in a repository.
24252425
settings.branch_filter = Branch filter
24262426
settings.branch_filter_desc = Branch whitelist for push, branch creation and branch deletion events, specified as glob pattern. If empty or <code>*</code>, events for all branches are reported. See <a href="%[1]s">%[2]s</a> documentation for syntax. Examples: <code>master</code>, <code>{master,release*}</code>.
24272427
settings.payload_optimization = Payload Size Optimization
2428-
settings.exclude_files = Exclude file changes
2429-
settings.exclude_files_desc = Remove file information (added, removed, modified files) from commit payloads to reduce webhook size.
2430-
settings.exclude_commits = Exclude commits
2431-
settings.exclude_commits_desc = Remove commits and head_commit from push payloads, keeping only before, after and total_commits fields.
2428+
settings.exclude_files_limit = Limit file changes
2429+
settings.exclude_files_limit_desc = Limit the number of file changes (added, removed, modified) included in each commit payload. 0 means unlimited.
2430+
settings.exclude_commits_limit = Limit commits
2431+
settings.exclude_commits_limit_desc = Limit the number of commits included in push payloads. 0 means unlimited.
24322432
settings.authorization_header = Authorization Header
24332433
settings.authorization_header_desc = Will be included as authorization header for requests when present. Examples: %s.
24342434
settings.active = Active

routers/web/repo/setting/webhook.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -232,19 +232,19 @@ func createWebhook(ctx *context.Context, params webhookParams) {
232232
}
233233

234234
w := &webhook.Webhook{
235-
RepoID: orCtx.RepoID,
236-
URL: params.URL,
237-
HTTPMethod: params.HTTPMethod,
238-
ContentType: params.ContentType,
239-
Secret: params.WebhookForm.Secret,
240-
HookEvent: ParseHookEvent(params.WebhookForm),
241-
IsActive: params.WebhookForm.Active,
242-
Type: params.Type,
243-
Meta: string(meta),
244-
OwnerID: orCtx.OwnerID,
245-
IsSystemWebhook: orCtx.IsSystemWebhook,
246-
ExcludeFiles: params.WebhookForm.ExcludeFiles,
247-
ExcludeCommits: params.WebhookForm.ExcludeCommits,
235+
RepoID: orCtx.RepoID,
236+
URL: params.URL,
237+
HTTPMethod: params.HTTPMethod,
238+
ContentType: params.ContentType,
239+
Secret: params.WebhookForm.Secret,
240+
HookEvent: ParseHookEvent(params.WebhookForm),
241+
IsActive: params.WebhookForm.Active,
242+
Type: params.Type,
243+
Meta: string(meta),
244+
OwnerID: orCtx.OwnerID,
245+
IsSystemWebhook: orCtx.IsSystemWebhook,
246+
ExcludeFilesLimit: params.WebhookForm.ExcludeFilesLimit,
247+
ExcludeCommitsLimit: params.WebhookForm.ExcludeCommitsLimit,
248248
}
249249
err = w.SetHeaderAuthorization(params.WebhookForm.AuthorizationHeader)
250250
if err != nil {
@@ -296,8 +296,8 @@ func editWebhook(ctx *context.Context, params webhookParams) {
296296
w.IsActive = params.WebhookForm.Active
297297
w.HTTPMethod = params.HTTPMethod
298298
w.Meta = string(meta)
299-
w.ExcludeFiles = params.WebhookForm.ExcludeFiles
300-
w.ExcludeCommits = params.WebhookForm.ExcludeCommits
299+
w.ExcludeFilesLimit = params.WebhookForm.ExcludeFilesLimit
300+
w.ExcludeCommitsLimit = params.WebhookForm.ExcludeCommitsLimit
301301

302302
err = w.SetHeaderAuthorization(params.WebhookForm.AuthorizationHeader)
303303
if err != nil {

services/forms/repo_form.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,8 @@ type WebhookForm struct {
240240
AuthorizationHeader string
241241
Secret string
242242
// Payload size optimization options
243-
ExcludeFiles bool // Exclude file changes from commit payloads
244-
ExcludeCommits bool // Exclude commits and head_commit from push payloads
243+
ExcludeFilesLimit int // Limit number of file changes in commit payloads, 0 means unlimited
244+
ExcludeCommitsLimit int // Limit number of commits in push payloads, 0 means unlimited
245245
}
246246

247247
// PushOnly if the hook will be triggered when push
@@ -625,7 +625,7 @@ type UpdateAllowEditsForm struct {
625625
// | _// __ \| | _/ __ \\__ \ / ___// __ \
626626
// | | \ ___/| |_\ ___/ / __ \_\___ \\ ___/
627627
// |____|_ /\___ >____/\___ >____ /____ >\___ >
628-
// \/ \/ \/ \/ \/ \/
628+
// \/ \/ \/ \/ \/ \/
629629

630630
// NewReleaseForm form for creating release
631631
type NewReleaseForm struct {

services/webhook/notifier.go

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -657,38 +657,47 @@ func (m *webhookNotifier) applyWebhookPayloadOptimizations(ctx context.Context,
657657
}
658658

659659
// Check if any webhook has payload optimization options enabled
660-
hasExcludeFiles := false
661-
hasExcludeCommits := false
660+
hasFilesLimit := 0
661+
hasCommitsLimit := 0
662662
for _, webhook := range webhooks {
663663
if webhook.HasEvent(webhook_module.HookEventPush) {
664-
if webhook.ExcludeFiles {
665-
hasExcludeFiles = true
664+
if webhook.ExcludeFilesLimit > 0 && (hasFilesLimit == 0 || webhook.ExcludeFilesLimit < hasFilesLimit) {
665+
hasFilesLimit = webhook.ExcludeFilesLimit
666666
}
667-
if webhook.ExcludeCommits {
668-
hasExcludeCommits = true
667+
if webhook.ExcludeCommitsLimit > 0 && (hasCommitsLimit == 0 || webhook.ExcludeCommitsLimit < hasCommitsLimit) {
668+
hasCommitsLimit = webhook.ExcludeCommitsLimit
669669
}
670670
}
671671
}
672672

673673
// Apply payload optimizations based on webhook configurations
674-
if hasExcludeFiles {
675-
// Remove file information from commits
674+
if hasFilesLimit > 0 {
676675
for _, commit := range apiCommits {
677-
commit.Added = nil
678-
commit.Removed = nil
679-
commit.Modified = nil
676+
if commit.Added != nil && len(commit.Added) > hasFilesLimit {
677+
commit.Added = commit.Added[:hasFilesLimit]
678+
}
679+
if commit.Removed != nil && len(commit.Removed) > hasFilesLimit {
680+
commit.Removed = commit.Removed[:hasFilesLimit]
681+
}
682+
if commit.Modified != nil && len(commit.Modified) > hasFilesLimit {
683+
commit.Modified = commit.Modified[:hasFilesLimit]
684+
}
680685
}
681686
if apiHeadCommit != nil {
682-
apiHeadCommit.Added = nil
683-
apiHeadCommit.Removed = nil
684-
apiHeadCommit.Modified = nil
687+
if apiHeadCommit.Added != nil && len(apiHeadCommit.Added) > hasFilesLimit {
688+
apiHeadCommit.Added = apiHeadCommit.Added[:hasFilesLimit]
689+
}
690+
if apiHeadCommit.Removed != nil && len(apiHeadCommit.Removed) > hasFilesLimit {
691+
apiHeadCommit.Removed = apiHeadCommit.Removed[:hasFilesLimit]
692+
}
693+
if apiHeadCommit.Modified != nil && len(apiHeadCommit.Modified) > hasFilesLimit {
694+
apiHeadCommit.Modified = apiHeadCommit.Modified[:hasFilesLimit]
695+
}
685696
}
686697
}
687698

688-
if hasExcludeCommits {
689-
// Exclude commits and head_commit from payload
690-
apiCommits = nil
691-
apiHeadCommit = nil
699+
if hasCommitsLimit > 0 && len(apiCommits) > hasCommitsLimit {
700+
apiCommits = apiCommits[:hasCommitsLimit]
692701
}
693702

694703
return apiCommits, apiHeadCommit

services/webhook/webhook_test.go

Lines changed: 51 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -95,27 +95,33 @@ func TestWebhookUserMail(t *testing.T) {
9595
func TestWebhookPayloadOptimization(t *testing.T) {
9696
assert.NoError(t, unittest.PrepareTestDatabase())
9797

98+
var optimizedCommits []*api.PayloadCommit
99+
var optimizedHeadCommit *api.PayloadCommit
100+
98101
// Create a test repository
99102
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
100103

101-
// Create a webhook with payload optimization enabled
104+
// Create a webhook with file limit = 1
102105
webhook := &webhook_model.Webhook{
103-
RepoID: repo.ID,
104-
URL: "http://example.com/webhook",
105-
HTTPMethod: "POST",
106-
ContentType: webhook_model.ContentTypeJSON,
107-
Secret: "secret",
108-
IsActive: true,
109-
Type: webhook_module.GITEA,
110-
ExcludeFiles: true,
111-
ExcludeCommits: false,
106+
RepoID: repo.ID,
107+
URL: "http://example.com/webhook",
108+
HTTPMethod: "POST",
109+
ContentType: webhook_model.ContentTypeJSON,
110+
Secret: "secret",
111+
IsActive: true,
112+
Type: webhook_module.GITEA,
113+
ExcludeFilesLimit: 1,
114+
ExcludeCommitsLimit: 0,
112115
HookEvent: &webhook_module.HookEvent{
113116
PushOnly: true,
114117
},
115118
}
116119

117-
err := webhook_model.CreateWebhook(db.DefaultContext, webhook)
120+
err := webhook.UpdateEvent()
121+
assert.NoError(t, err)
122+
err = webhook_model.CreateWebhook(db.DefaultContext, webhook)
118123
assert.NoError(t, err)
124+
assert.NotZero(t, webhook.ID)
119125

120126
// Create test commits with file information
121127
apiCommits := []*api.PayloadCommit{
@@ -143,30 +149,43 @@ func TestWebhookPayloadOptimization(t *testing.T) {
143149
Modified: []string{"file1.txt"},
144150
}
145151

146-
// Test payload optimization
152+
// Test payload optimization: should truncate to 1 file per field
147153
notifier := &webhookNotifier{}
148-
optimizedCommits, optimizedHeadCommit := notifier.applyWebhookPayloadOptimizations(db.DefaultContext, repo, apiCommits, apiHeadCommit)
149-
150-
// Verify that file information was removed when ExcludeFiles is true
151-
assert.Nil(t, optimizedCommits[0].Added)
152-
assert.Nil(t, optimizedCommits[0].Removed)
153-
assert.Nil(t, optimizedCommits[0].Modified)
154-
assert.Nil(t, optimizedCommits[1].Added)
155-
assert.Nil(t, optimizedCommits[1].Removed)
156-
assert.Nil(t, optimizedCommits[1].Modified)
157-
assert.Nil(t, optimizedHeadCommit.Added)
158-
assert.Nil(t, optimizedHeadCommit.Removed)
159-
assert.Nil(t, optimizedHeadCommit.Modified)
160-
161-
// Test with ExcludeCommits enabled
162-
webhook.ExcludeFiles = false
163-
webhook.ExcludeCommits = true
154+
optimizedCommits, _ = notifier.applyWebhookPayloadOptimizations(db.DefaultContext, repo, apiCommits, apiHeadCommit)
155+
assert.Equal(t, []string{"file1.txt"}, optimizedCommits[0].Added)
156+
assert.Equal(t, []string{"oldfile.txt"}, optimizedCommits[0].Removed)
157+
assert.Equal(t, []string{"modified.txt"}, optimizedCommits[0].Modified)
158+
assert.Equal(t, []string{"file3.txt"}, optimizedCommits[1].Added)
159+
assert.Equal(t, []string{}, optimizedCommits[1].Removed)
160+
assert.Equal(t, []string{"file1.txt"}, optimizedCommits[1].Modified)
161+
162+
_, optimizedHeadCommit = notifier.applyWebhookPayloadOptimizations(db.DefaultContext, repo, apiCommits, apiHeadCommit)
163+
assert.Equal(t, []string{"file3.txt"}, optimizedHeadCommit.Added)
164+
assert.Equal(t, []string{}, optimizedHeadCommit.Removed)
165+
assert.Equal(t, []string{"file1.txt"}, optimizedHeadCommit.Modified)
166+
167+
// Test with commit limit = 1
168+
webhook.ExcludeFilesLimit = 0
169+
webhook.ExcludeCommitsLimit = 1
164170
err = webhook_model.UpdateWebhook(db.DefaultContext, webhook)
165171
assert.NoError(t, err)
172+
optimizedCommits, _ = notifier.applyWebhookPayloadOptimizations(db.DefaultContext, repo, apiCommits, apiHeadCommit)
173+
assert.Len(t, optimizedCommits, 1)
174+
assert.Equal(t, "abc123", optimizedCommits[0].ID)
166175

176+
// Test with no limits (0 means unlimited)
177+
webhook.ExcludeFilesLimit = 0
178+
webhook.ExcludeCommitsLimit = 0
179+
err = webhook_model.UpdateWebhook(db.DefaultContext, webhook)
180+
assert.NoError(t, err)
167181
optimizedCommits, optimizedHeadCommit = notifier.applyWebhookPayloadOptimizations(db.DefaultContext, repo, apiCommits, apiHeadCommit)
168-
169-
// Verify that commits and head_commit were excluded
170-
assert.Nil(t, optimizedCommits)
171-
assert.Nil(t, optimizedHeadCommit)
182+
assert.Equal(t, []string{"file1.txt", "file2.txt"}, optimizedCommits[0].Added)
183+
assert.Equal(t, []string{"oldfile.txt"}, optimizedCommits[0].Removed)
184+
assert.Equal(t, []string{"modified.txt"}, optimizedCommits[0].Modified)
185+
assert.Equal(t, []string{"file3.txt"}, optimizedCommits[1].Added)
186+
assert.Equal(t, []string{}, optimizedCommits[1].Removed)
187+
assert.Equal(t, []string{"file1.txt"}, optimizedCommits[1].Modified)
188+
assert.Equal(t, []string{"file3.txt"}, optimizedHeadCommit.Added)
189+
assert.Equal(t, []string{}, optimizedHeadCommit.Removed)
190+
assert.Equal(t, []string{"file1.txt"}, optimizedHeadCommit.Modified)
172191
}

templates/repo/settings/webhook/settings.tmpl

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,14 @@
5151
<div class="field">
5252
<h4>{{ctx.Locale.Tr "repo.settings.payload_optimization"}}</h4>
5353
<div class="field">
54-
<div class="ui checkbox">
55-
<input name="exclude_files" type="checkbox" {{if .Webhook.ExcludeFiles}}checked{{end}}>
56-
<label>{{ctx.Locale.Tr "repo.settings.exclude_files"}}</label>
57-
<span class="help">{{ctx.Locale.Tr "repo.settings.exclude_files_desc"}}</span>
58-
</div>
54+
<label>{{ctx.Locale.Tr "repo.settings.exclude_files_limit"}}</label>
55+
<input name="exclude_files_limit" type="number" min="0" value="{{.Webhook.ExcludeFilesLimit}}" placeholder="0">
56+
<span class="help">{{ctx.Locale.Tr "repo.settings.exclude_files_limit_desc"}}</span>
5957
</div>
6058
<div class="field">
61-
<div class="ui checkbox">
62-
<input name="exclude_commits" type="checkbox" {{if .Webhook.ExcludeCommits}}checked{{end}}>
63-
<label>{{ctx.Locale.Tr "repo.settings.exclude_commits"}}</label>
64-
<span class="help">{{ctx.Locale.Tr "repo.settings.exclude_commits_desc"}}</span>
65-
</div>
59+
<label>{{ctx.Locale.Tr "repo.settings.exclude_commits_limit"}}</label>
60+
<input name="exclude_commits_limit" type="number" min="0" value="{{.Webhook.ExcludeCommitsLimit}}" placeholder="0">
61+
<span class="help">{{ctx.Locale.Tr "repo.settings.exclude_commits_limit_desc"}}</span>
6662
</div>
6763
</div>
6864

0 commit comments

Comments
 (0)