Skip to content

Commit 7f9debb

Browse files
committed
Merge branch 'feature/webhook-payload-optimization' of github.com:kerwin612/gitea into kerwin612-feature/webhook-payload-optimization
2 parents 90cb5f9 + 46c0824 commit 7f9debb

File tree

17 files changed

+876
-4
lines changed

17 files changed

+876
-4
lines changed

models/migrations/migrations.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,10 +390,10 @@ func prepareMigrationTasks() []*migration {
390390
newMigration(318, "Add anonymous_access_mode for repo_unit", v1_24.AddRepoUnitAnonymousAccessMode),
391391
newMigration(319, "Add ExclusiveOrder to Label table", v1_24.AddExclusiveOrderColumnToLabelTable),
392392
newMigration(320, "Migrate two_factor_policy to login_source table", v1_24.MigrateSkipTwoFactor),
393-
394393
// Gitea 1.24.0 ends at database version 321
395394
newMigration(321, "Use LONGTEXT for some columns and fix review_state.updated_files column", v1_25.UseLongTextInSomeColumnsAndFixBugs),
396395
newMigration(322, "Extend comment tree_path length limit", v1_25.ExtendCommentTreePathLength),
396+
newMigration(323, "Add webhook payload optimization JSON field", v1_25.AddWebhookPayloadOptimizationColumns),
397397
}
398398
return preparedMigrations
399399
}

models/migrations/v1_25/v323.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package v1_25
5+
6+
import (
7+
"xorm.io/xorm"
8+
)
9+
10+
func AddWebhookPayloadOptimizationColumns(x *xorm.Engine) error {
11+
type Webhook struct {
12+
MetaSettings string `xorm:"meta_settings TEXT"`
13+
}
14+
_, err := x.SyncWithOptions(
15+
xorm.SyncOptions{
16+
IgnoreConstrains: true,
17+
IgnoreIndices: true,
18+
},
19+
new(Webhook),
20+
)
21+
return err
22+
}

models/webhook/webhook.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,35 @@ import (
2222
"xorm.io/builder"
2323
)
2424

25+
// MetaSettings represents the metadata settings for webhook
26+
type MetaSettings struct {
27+
PayloadConfig PayloadConfig `json:"payload_config"` // Payload configuration
28+
}
29+
30+
// PayloadConfig represents the configuration for webhook payload
31+
type PayloadConfig struct {
32+
Files PayloadConfigItem `json:"files"` // Files configuration
33+
Commits PayloadConfigItem `json:"commits"` // Commits configuration
34+
}
35+
36+
// PayloadConfigItem represents a single payload configuration item
37+
type PayloadConfigItem struct {
38+
Enable bool `json:"enable"` // Whether to enable this configuration
39+
Limit int `json:"limit"` // 0: trim all (none kept), >0: keep N items (forward order), <0: keep N items (reverse order)
40+
}
41+
42+
// DefaultMetaSettings returns the default webhook meta settings
43+
func DefaultMetaSettings() MetaSettings {
44+
return MetaSettings{
45+
PayloadConfig: DefaultPayloadConfig(),
46+
}
47+
}
48+
49+
// DefaultPayloadConfig returns the default payload configuration
50+
func DefaultPayloadConfig() PayloadConfig {
51+
return PayloadConfig{}
52+
}
53+
2554
// ErrWebhookNotExist represents a "WebhookNotExist" kind of error.
2655
type ErrWebhookNotExist struct {
2756
ID int64
@@ -139,6 +168,9 @@ type Webhook struct {
139168
// HeaderAuthorizationEncrypted should be accessed using HeaderAuthorization() and SetHeaderAuthorization()
140169
HeaderAuthorizationEncrypted string `xorm:"TEXT"`
141170

171+
// Webhook metadata settings (JSON format)
172+
MetaSettings string `xorm:"meta_settings TEXT"` // JSON: webhook metadata configuration
173+
142174
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
143175
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
144176
}
@@ -346,3 +378,83 @@ func DeleteWebhookByOwnerID(ctx context.Context, ownerID, id int64) error {
346378
}
347379
return DeleteWebhookByID(ctx, id)
348380
}
381+
382+
// GetMetaSettings returns the webhook meta settings
383+
func (w *Webhook) GetMetaSettings() MetaSettings {
384+
if w.MetaSettings == "" {
385+
return DefaultMetaSettings()
386+
}
387+
388+
var settings MetaSettings
389+
if err := json.Unmarshal([]byte(w.MetaSettings), &settings); err != nil {
390+
log.Error("Failed to unmarshal webhook meta settings: %v", err)
391+
return DefaultMetaSettings()
392+
}
393+
394+
return settings
395+
}
396+
397+
// GetPayloadConfig returns the payload configuration
398+
func (w *Webhook) GetPayloadConfig() PayloadConfig {
399+
return w.GetMetaSettings().PayloadConfig
400+
}
401+
402+
// SetMetaSettings sets the webhook meta settings
403+
func (w *Webhook) SetMetaSettings(settings MetaSettings) error {
404+
data, err := json.Marshal(settings)
405+
if err != nil {
406+
return fmt.Errorf("failed to marshal webhook meta settings: %w", err)
407+
}
408+
409+
w.MetaSettings = string(data)
410+
return nil
411+
}
412+
413+
// SetPayloadConfig sets the payload configuration
414+
func (w *Webhook) SetPayloadConfig(config PayloadConfig) error {
415+
settings := w.GetMetaSettings()
416+
settings.PayloadConfig = config
417+
return w.SetMetaSettings(settings)
418+
}
419+
420+
// IsPayloadConfigEnabled returns whether payload configuration is enabled
421+
func (w *Webhook) IsPayloadConfigEnabled() bool {
422+
config := w.GetPayloadConfig()
423+
return config.Files.Enable || config.Commits.Enable
424+
}
425+
426+
// GetPayloadConfigLimit returns the payload configuration limit
427+
func (w *Webhook) GetPayloadConfigLimit() int {
428+
config := w.GetPayloadConfig()
429+
if config.Files.Enable {
430+
return config.Files.Limit
431+
}
432+
if config.Commits.Enable {
433+
return config.Commits.Limit
434+
}
435+
return 0
436+
}
437+
438+
// IsFilesConfigEnabled returns whether files configuration is enabled
439+
func (w *Webhook) IsFilesConfigEnabled() bool {
440+
config := w.GetPayloadConfig()
441+
return config.Files.Enable
442+
}
443+
444+
// GetFilesConfigLimit returns the files configuration limit
445+
func (w *Webhook) GetFilesConfigLimit() int {
446+
config := w.GetPayloadConfig()
447+
return config.Files.Limit
448+
}
449+
450+
// IsCommitsConfigEnabled returns whether commits configuration is enabled
451+
func (w *Webhook) IsCommitsConfigEnabled() bool {
452+
config := w.GetPayloadConfig()
453+
return config.Commits.Enable
454+
}
455+
456+
// GetCommitsConfigLimit returns the commits configuration limit
457+
func (w *Webhook) GetCommitsConfigLimit() int {
458+
config := w.GetPayloadConfig()
459+
return config.Commits.Limit
460+
}

models/webhook/webhook_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,3 +330,63 @@ func TestCleanupHookTaskTable_OlderThan_LeavesTaskEarlierThanAgeToDelete(t *test
330330
assert.NoError(t, CleanupHookTaskTable(t.Context(), OlderThan, 168*time.Hour, 0))
331331
unittest.AssertExistsAndLoadBean(t, hookTask)
332332
}
333+
334+
func TestWebhookPayloadOptimization(t *testing.T) {
335+
webhook := &Webhook{}
336+
337+
// Test default configuration
338+
config := webhook.GetPayloadConfig()
339+
assert.False(t, config.Files.Enable)
340+
assert.Equal(t, 0, config.Files.Limit)
341+
assert.False(t, config.Commits.Enable)
342+
assert.Equal(t, 0, config.Commits.Limit)
343+
344+
// Test setting configuration via meta settings
345+
metaSettings := MetaSettings{
346+
PayloadConfig: PayloadConfig{
347+
Files: PayloadConfigItem{
348+
Enable: true,
349+
Limit: 5,
350+
},
351+
Commits: PayloadConfigItem{
352+
Enable: true,
353+
Limit: -3,
354+
},
355+
},
356+
}
357+
webhook.SetMetaSettings(metaSettings)
358+
359+
// Test getting configuration
360+
config = webhook.GetPayloadConfig()
361+
assert.True(t, config.Files.Enable)
362+
assert.Equal(t, 5, config.Files.Limit)
363+
assert.True(t, config.Commits.Enable)
364+
assert.Equal(t, -3, config.Commits.Limit)
365+
366+
// Test individual methods
367+
assert.True(t, webhook.IsFilesConfigEnabled())
368+
assert.Equal(t, 5, webhook.GetFilesConfigLimit())
369+
assert.True(t, webhook.IsCommitsConfigEnabled())
370+
assert.Equal(t, -3, webhook.GetCommitsConfigLimit())
371+
assert.True(t, webhook.IsPayloadConfigEnabled())
372+
373+
// Test backward compatibility with direct payload config setting
374+
newConfig := PayloadConfig{
375+
Files: PayloadConfigItem{
376+
Enable: false,
377+
Limit: 10,
378+
},
379+
Commits: PayloadConfigItem{
380+
Enable: false,
381+
Limit: 20,
382+
},
383+
}
384+
webhook.SetPayloadConfig(newConfig)
385+
386+
// Verify the config is properly set through meta settings
387+
config = webhook.GetPayloadConfig()
388+
assert.False(t, config.Files.Enable)
389+
assert.Equal(t, 10, config.Files.Limit)
390+
assert.False(t, config.Commits.Enable)
391+
assert.Equal(t, 20, config.Commits.Limit)
392+
}

modules/structs/hook.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ type Hook struct {
3333
AuthorizationHeader string `json:"authorization_header"`
3434
// Whether the webhook is active and will be triggered
3535
Active bool `json:"active"`
36+
// MetaSettings webhook metadata settings including payload optimization
37+
MetaSettings map[string]any `json:"meta_settings"`
3638
// swagger:strfmt date-time
3739
// The date and time when the webhook was last updated
3840
Updated time.Time `json:"updated_at"`
@@ -63,6 +65,8 @@ type CreateHookOption struct {
6365
BranchFilter string `json:"branch_filter" binding:"GlobPattern"`
6466
// Authorization header to include in webhook requests
6567
AuthorizationHeader string `json:"authorization_header"`
68+
// Webhook metadata settings including payload optimization
69+
MetaSettings map[string]any `json:"meta_settings"` // {"payload_config": {"files": {"enable": bool, "limit": int}, "commits": {"enable": bool, "limit": int}}}
6670
// default: false
6771
// Whether the webhook should be active upon creation
6872
Active bool `json:"active"`
@@ -78,6 +82,8 @@ type EditHookOption struct {
7882
BranchFilter string `json:"branch_filter" binding:"GlobPattern"`
7983
// Authorization header to include in webhook requests
8084
AuthorizationHeader string `json:"authorization_header"`
85+
// Webhook metadata settings including payload optimization
86+
MetaSettings *map[string]any `json:"meta_settings"` // {"payload_config": {"files": {"enable": bool, "limit": int}, "commits": {"enable": bool, "limit": int}}}
8187
// Whether the webhook is active and will be triggered
8288
Active *bool `json:"active"`
8389
}

options/locale/locale_en-US.ini

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2434,6 +2434,13 @@ settings.event_package = Package
24342434
settings.event_package_desc = Package created or deleted in a repository.
24352435
settings.branch_filter = Branch filter
24362436
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>.
2437+
settings.payload_optimization = Payload Size Optimization
2438+
settings.payload_optimization_files = Files
2439+
settings.payload_optimization_commits = Commits
2440+
settings.payload_optimization_enable = Enable optimization
2441+
settings.payload_optimization_enable_desc = Enable payload size optimization for this item
2442+
settings.payload_optimization_limit = Limit
2443+
settings.payload_optimization_limit_desc = 0: trim all (none kept), >0: keep N items (forward order), <0: keep N items (reverse order)
24372444
settings.authorization_header = Authorization Header
24382445
settings.authorization_header_desc = Will be included as authorization header for requests when present. Examples: %s.
24392446
settings.active = Active
@@ -3297,7 +3304,7 @@ auths.tip.github = Register a new OAuth application on %s
32973304
auths.tip.gitlab_new = Register a new application on %s
32983305
auths.tip.google_plus = Obtain OAuth2 client credentials from the Google API console at %s
32993306
auths.tip.openid_connect = Use the OpenID Connect Discovery URL "https://{server}/.well-known/openid-configuration" to specify the endpoints
3300-
auths.tip.twitter = Go to %s, create an application and ensure that the Allow this application to be used to Sign in with Twitter option is enabled
3307+
auths.tip.twitter = Go to %s, create an application and ensure that the "Allow this application to be used to Sign in with Twitter" option is enabled
33013308
auths.tip.discord = Register a new application on %s
33023309
auths.tip.gitea = Register a new OAuth2 application. Guide can be found at %s
33033310
auths.tip.yandex = Create a new application at %s. Select following permissions from the "Yandex.Passport API" section: "Access to email address", "Access to user avatar" and "Access to username, first name and surname, gender"

0 commit comments

Comments
 (0)