4 Commits

Author SHA1 Message Date
Lunny Xiao
465a6f01ee Merge branch 'main' into lunny/fix_webhook 2026-04-20 21:01:30 +00:00
Lunny Xiao
b43f36abd4 Merge branch 'main' into lunny/fix_webhook 2026-04-20 19:48:45 +00:00
Lunny Xiao
ab7dc97518 Fix lint 2026-04-20 12:34:52 -07:00
Lunny Xiao
469a6d3466 Fix webhook 2026-04-20 12:19:36 -07:00
6 changed files with 159 additions and 146 deletions

View File

@@ -89,30 +89,26 @@ func runWebhooksCreate(ctx stdctx.Context, cmd *cli.Command) error {
config["secret"] = secret
}
if branchFilter != "" {
config["branch_filter"] = branchFilter
}
if authHeader != "" {
config["authorization_header"] = authHeader
}
var hook *gitea.Hook
if c.IsGlobal {
return fmt.Errorf("global webhooks not yet supported in this version")
} else if len(c.Org) > 0 {
hook, _, err = client.CreateOrgHook(c.Org, gitea.CreateHookOption{
Type: webhookType,
Config: config,
Events: events,
Active: active,
Type: webhookType,
Config: config,
Events: events,
Active: active,
BranchFilter: branchFilter,
AuthorizationHeader: authHeader,
})
} else {
hook, _, err = client.CreateRepoHook(c.Owner, c.Repo, gitea.CreateHookOption{
Type: webhookType,
Config: config,
Events: events,
Active: active,
Type: webhookType,
Config: config,
Events: events,
Active: active,
BranchFilter: branchFilter,
AuthorizationHeader: authHeader,
})
}
if err != nil {

View File

@@ -79,8 +79,6 @@ func TestWebhookConfigConstruction(t *testing.T) {
name string
url string
secret string
branchFilter string
authHeader string
expectedKeys []string
expectedValues map[string]string
}{
@@ -106,44 +104,16 @@ func TestWebhookConfigConstruction(t *testing.T) {
"secret": "my-secret",
},
},
{
name: "Config with branch filter",
url: "https://example.com/webhook",
branchFilter: "main,develop",
expectedKeys: []string{"url", "http_method", "content_type", "branch_filter"},
expectedValues: map[string]string{
"url": "https://example.com/webhook",
"http_method": "post",
"content_type": "json",
"branch_filter": "main,develop",
},
},
{
name: "Config with auth header",
url: "https://example.com/webhook",
authHeader: "Bearer token123",
expectedKeys: []string{"url", "http_method", "content_type", "authorization_header"},
expectedValues: map[string]string{
"url": "https://example.com/webhook",
"http_method": "post",
"content_type": "json",
"authorization_header": "Bearer token123",
},
},
{
name: "Complete config",
url: "https://example.com/webhook",
secret: "secret123",
branchFilter: "main",
authHeader: "X-Token: abc",
expectedKeys: []string{"url", "http_method", "content_type", "secret", "branch_filter", "authorization_header"},
expectedKeys: []string{"url", "http_method", "content_type", "secret"},
expectedValues: map[string]string{
"url": "https://example.com/webhook",
"http_method": "post",
"content_type": "json",
"secret": "secret123",
"branch_filter": "main",
"authorization_header": "X-Token: abc",
"url": "https://example.com/webhook",
"http_method": "post",
"content_type": "json",
"secret": "secret123",
},
},
}
@@ -159,12 +129,6 @@ func TestWebhookConfigConstruction(t *testing.T) {
if tt.secret != "" {
config["secret"] = tt.secret
}
if tt.branchFilter != "" {
config["branch_filter"] = tt.branchFilter
}
if tt.authHeader != "" {
config["authorization_header"] = tt.authHeader
}
// Check all expected keys exist
for _, key := range tt.expectedKeys {
@@ -184,11 +148,13 @@ func TestWebhookConfigConstruction(t *testing.T) {
func TestWebhookCreateOptions(t *testing.T) {
tests := []struct {
name string
webhookType string
events []string
active bool
config map[string]string
name string
webhookType string
events []string
active bool
config map[string]string
branchFilter string
authHeader string
}{
{
name: "Gitea webhook",
@@ -200,6 +166,8 @@ func TestWebhookCreateOptions(t *testing.T) {
"http_method": "post",
"content_type": "json",
},
branchFilter: "main",
authHeader: "X-Token: abc",
},
{
name: "Slack webhook",
@@ -228,16 +196,20 @@ func TestWebhookCreateOptions(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
option := gitea.CreateHookOption{
Type: gitea.HookType(tt.webhookType),
Config: tt.config,
Events: tt.events,
Active: tt.active,
Type: gitea.HookType(tt.webhookType),
Config: tt.config,
Events: tt.events,
Active: tt.active,
BranchFilter: tt.branchFilter,
AuthorizationHeader: tt.authHeader,
}
assert.Equal(t, gitea.HookType(tt.webhookType), option.Type)
assert.Equal(t, tt.events, option.Events)
assert.Equal(t, tt.active, option.Active)
assert.Equal(t, tt.config, option.Config)
assert.Equal(t, tt.branchFilter, option.BranchFilter)
assert.Equal(t, tt.authHeader, option.AuthorizationHeader)
})
}
}

View File

@@ -97,11 +97,14 @@ func runWebhooksUpdate(ctx stdctx.Context, cmd *cli.Command) error {
if cmd.IsSet("secret") {
config["secret"] = cmd.String("secret")
}
branchFilter := hook.BranchFilter
if cmd.IsSet("branch-filter") {
config["branch_filter"] = cmd.String("branch-filter")
branchFilter = cmd.String("branch-filter")
}
authHeader := hook.AuthorizationHeader
if cmd.IsSet("authorization-header") {
config["authorization_header"] = cmd.String("authorization-header")
authHeader = cmd.String("authorization-header")
}
// Update events if specified
@@ -126,15 +129,19 @@ func runWebhooksUpdate(ctx stdctx.Context, cmd *cli.Command) error {
return fmt.Errorf("global webhooks not yet supported in this version")
} else if len(c.Org) > 0 {
_, err = client.EditOrgHook(c.Org, int64(webhookID), gitea.EditHookOption{
Config: config,
Events: events,
Active: &active,
Config: config,
Events: events,
Active: &active,
BranchFilter: branchFilter,
AuthorizationHeader: authHeader,
})
} else {
_, err = client.EditRepoHook(c.Owner, c.Repo, int64(webhookID), gitea.EditHookOption{
Config: config,
Events: events,
Active: &active,
Config: config,
Events: events,
Active: &active,
BranchFilter: branchFilter,
AuthorizationHeader: authHeader,
})
}
if err != nil {

View File

@@ -128,12 +128,10 @@ func TestUpdateActiveInactiveFlags(t *testing.T) {
func TestUpdateConfigPreservation(t *testing.T) {
// Test that existing configuration is preserved when not updated
originalConfig := map[string]string{
"url": "https://old.example.com/webhook",
"secret": "old-secret",
"branch_filter": "main",
"authorization_header": "Bearer old-token",
"http_method": "post",
"content_type": "json",
"url": "https://old.example.com/webhook",
"secret": "old-secret",
"http_method": "post",
"content_type": "json",
}
tests := []struct {
@@ -147,53 +145,32 @@ func TestUpdateConfigPreservation(t *testing.T) {
"url": "https://new.example.com/webhook",
},
expectedConfig: map[string]string{
"url": "https://new.example.com/webhook",
"secret": "old-secret",
"branch_filter": "main",
"authorization_header": "Bearer old-token",
"http_method": "post",
"content_type": "json",
"url": "https://new.example.com/webhook",
"secret": "old-secret",
"http_method": "post",
"content_type": "json",
},
},
{
name: "Update secret and auth header",
name: "Update secret",
updates: map[string]string{
"secret": "new-secret",
"authorization_header": "X-Token: new-token",
"secret": "new-secret",
},
expectedConfig: map[string]string{
"url": "https://old.example.com/webhook",
"secret": "new-secret",
"branch_filter": "main",
"authorization_header": "X-Token: new-token",
"http_method": "post",
"content_type": "json",
},
},
{
name: "Clear branch filter",
updates: map[string]string{
"branch_filter": "",
},
expectedConfig: map[string]string{
"url": "https://old.example.com/webhook",
"secret": "old-secret",
"branch_filter": "",
"authorization_header": "Bearer old-token",
"http_method": "post",
"content_type": "json",
"url": "https://old.example.com/webhook",
"secret": "new-secret",
"http_method": "post",
"content_type": "json",
},
},
{
name: "No updates",
updates: map[string]string{},
expectedConfig: map[string]string{
"url": "https://old.example.com/webhook",
"secret": "old-secret",
"branch_filter": "main",
"authorization_header": "Bearer old-token",
"http_method": "post",
"content_type": "json",
"url": "https://old.example.com/webhook",
"secret": "old-secret",
"http_method": "post",
"content_type": "json",
},
},
}
@@ -217,6 +194,61 @@ func TestUpdateConfigPreservation(t *testing.T) {
}
}
func TestUpdateBranchFilterAndAuthHeaderHandling(t *testing.T) {
tests := []struct {
name string
originalBranchFilter string
originalAuthHeader string
setBranchFilter bool
newBranchFilter string
setAuthorizationHeader bool
newAuthHeader string
expectedBranchFilter string
expectedAuthHeader string
}{
{
name: "Preserve values",
originalBranchFilter: "main",
originalAuthHeader: "Bearer old-token",
expectedBranchFilter: "main",
expectedAuthHeader: "Bearer old-token",
},
{
name: "Update branch filter",
originalBranchFilter: "main",
setBranchFilter: true,
newBranchFilter: "develop",
expectedBranchFilter: "develop",
expectedAuthHeader: "",
},
{
name: "Update authorization header",
originalAuthHeader: "Bearer old-token",
setAuthorizationHeader: true,
newAuthHeader: "X-Token: new-token",
expectedBranchFilter: "",
expectedAuthHeader: "X-Token: new-token",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
branchFilter := tt.originalBranchFilter
if tt.setBranchFilter {
branchFilter = tt.newBranchFilter
}
authHeader := tt.originalAuthHeader
if tt.setAuthorizationHeader {
authHeader = tt.newAuthHeader
}
assert.Equal(t, tt.expectedBranchFilter, branchFilter)
assert.Equal(t, tt.expectedAuthHeader, authHeader)
})
}
}
func TestUpdateEventsHandling(t *testing.T) {
tests := []struct {
name string

View File

@@ -67,13 +67,21 @@ func WebhookDetails(hook *gitea.Hook) {
if method, ok := hook.Config["http_method"]; ok {
fmt.Printf("- **HTTP Method**: %s\n", method)
}
if branchFilter, ok := hook.Config["branch_filter"]; ok && branchFilter != "" {
branchFilter := hook.BranchFilter
if branchFilter == "" {
branchFilter = hook.Config["branch_filter"]
}
if branchFilter != "" {
fmt.Printf("- **Branch Filter**: %s\n", branchFilter)
}
if _, hasSecret := hook.Config["secret"]; hasSecret {
fmt.Printf("- **Secret**: (configured)\n")
}
if _, hasAuth := hook.Config["authorization_header"]; hasAuth {
hasAuth := hook.AuthorizationHeader != ""
if !hasAuth {
_, hasAuth = hook.Config["authorization_header"]
}
if hasAuth {
fmt.Printf("- **Authorization Header**: (configured)\n")
}
}

View File

@@ -81,17 +81,17 @@ func TestWebhookDetails(t *testing.T) {
ID: 123,
Type: "gitea",
Config: map[string]string{
"url": "https://example.com/webhook",
"content_type": "json",
"http_method": "post",
"branch_filter": "main,develop",
"secret": "secret-value",
"authorization_header": "Bearer token123",
"url": "https://example.com/webhook",
"content_type": "json",
"http_method": "post",
"secret": "secret-value",
},
Events: []string{"push", "pull_request", "issues"},
Active: true,
Created: now.Add(-24 * time.Hour),
Updated: now,
BranchFilter: "main,develop",
AuthorizationHeader: "Bearer token123",
Events: []string{"push", "pull_request", "issues"},
Active: true,
Created: now.Add(-24 * time.Hour),
Updated: now,
},
},
{
@@ -238,16 +238,14 @@ func TestWebhookConfigHandling(t *testing.T) {
{
name: "Config with all fields",
config: map[string]string{
"url": "https://example.com/webhook",
"secret": "my-secret",
"authorization_header": "Bearer token",
"content_type": "json",
"http_method": "post",
"branch_filter": "main",
"url": "https://example.com/webhook",
"secret": "my-secret",
"content_type": "json",
"http_method": "post",
},
expectedURL: "https://example.com/webhook",
hasSecret: true,
hasAuthHeader: true,
hasAuthHeader: false,
},
{
name: "Config with minimal fields",
@@ -341,17 +339,17 @@ func TestWebhookDetailsFormatting(t *testing.T) {
ID: 123,
Type: "gitea",
Config: map[string]string{
"url": "https://example.com/webhook",
"content_type": "json",
"http_method": "post",
"branch_filter": "main,develop",
"secret": "secret-value",
"authorization_header": "Bearer token123",
"url": "https://example.com/webhook",
"content_type": "json",
"http_method": "post",
"secret": "secret-value",
},
Events: []string{"push", "pull_request", "issues"},
Active: true,
Created: now.Add(-24 * time.Hour),
Updated: now,
BranchFilter: "main,develop",
AuthorizationHeader: "Bearer token123",
Events: []string{"push", "pull_request", "issues"},
Active: true,
Created: now.Add(-24 * time.Hour),
Updated: now,
}
// Test that all expected fields are included in details
@@ -379,8 +377,8 @@ func TestWebhookDetailsFormatting(t *testing.T) {
assert.Equal(t, "https://example.com/webhook", hook.Config["url"])
assert.Equal(t, "json", hook.Config["content_type"])
assert.Equal(t, "post", hook.Config["http_method"])
assert.Equal(t, "main,develop", hook.Config["branch_filter"])
assert.Equal(t, "main,develop", hook.BranchFilter)
assert.Contains(t, hook.Config, "secret")
assert.Contains(t, hook.Config, "authorization_header")
assert.Equal(t, "Bearer token123", hook.AuthorizationHeader)
assert.Equal(t, []string{"push", "pull_request", "issues"}, hook.Events)
}