mirror of
https://gitea.com/gitea/tea.git
synced 2026-10-26 11:01:25 +01:00
feat!: rebuild tea on Cobra with explicit noun/verb commands (#1126)
- **switch tea to the Cobra command tree:** `internal/app` wires the packages from parts 1–4 into explicit noun/verb commands with `--repo`, `--json` / `--jq`, `--sudo` and `--debug`; `main.go` points at it. Build, release and docs tooling (`tools/cli-docs`, Makefile, goreleaser, snap, CI) and README / CONTRIBUTING are updated. - **remove the urfave/cli command tree:** deletes `cmd/`, `modules/`, the old integration tests, contrib completion scripts and the generated `docs/CLI.md`, and drops their dependencies. This commit only deletes. ## Breaking changes This is a breaking release. It requires Gitea 28 or newer; configuration moves to separate `config.yml` and `hosts.yml` files and requires fresh authentication, and command names, aliases, flags and output formats change. `docs/migration-1.0.md` maps every old command, flag and environment variable to its replacement. ## Issues fixes #1118 fixes #1116 fixes #1115 fixes #1094 fixes #1091 fixes #1073 fixes #1052 fixes #1032 fixes #1023 fixes #966 fixes #908 fixes #833 fixes #831 fixes #817 fixes #804 fixes #779 fixes #770 fixes #737 fixes #697 fixes #726 fixes #677 fixes #672 fixes #633 fixes #632 fixes #560 fixes #556 fixes #523 fixes #516 fixes #510 fixes #504 fixes #500 fixes #482 fixes #406 fixes #403 fixes #373 fixes #351 fixes #344 fixes #326 fixes #325 fixes #323 fixes #246 fixes #240 fixes #232 fixes #197 fixes #172 fixes #141 fixes #69 fixes #1110 fixes #569 fixes #480 fixes #666 fixes #670 fixes #457 fixes #643 fixes #498 fixes #490 fixes #1069 fixes #834 fixes #602 fixes #328 fixes #417 fixes #571 fixes #1029 fixes #489 fixes #1050 fixes #162 fixes #430 fixes #1087 fixes #683 Reviewed-on: https://gitea.com/gitea/tea/pulls/1126 Reviewed-by: TheFox0x7 <95654+thefox0x7@noreply.gitea.com>
This commit is contained in:
1 parent
12e415a7a7
commit
f02245449b
456 files changed
+18892
-34015
No files matched your search
@@ -1,365 +0,0 @@
|
||||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package webhooks
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gitea.dev/sdk"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func TestValidateWebhookType(t *testing.T) {
|
||||
validTypes := []string{"gitea", "gogs", "slack", "discord", "dingtalk", "telegram", "msteams", "feishu", "wechatwork", "packagist"}
|
||||
|
||||
for _, validType := range validTypes {
|
||||
t.Run("Valid_"+validType, func(t *testing.T) {
|
||||
hookType := gitea.HookType(validType)
|
||||
assert.NotEmpty(t, string(hookType))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseWebhookEvents(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
name: "Single event",
|
||||
input: "push",
|
||||
expected: []string{"push"},
|
||||
},
|
||||
{
|
||||
name: "Multiple events",
|
||||
input: "push,pull_request,issues",
|
||||
expected: []string{"push", "pull_request", "issues"},
|
||||
},
|
||||
{
|
||||
name: "Events with spaces",
|
||||
input: "push, pull_request , issues",
|
||||
expected: []string{"push", "pull_request", "issues"},
|
||||
},
|
||||
{
|
||||
name: "Empty event",
|
||||
input: "",
|
||||
expected: []string{""},
|
||||
},
|
||||
{
|
||||
name: "Single comma",
|
||||
input: ",",
|
||||
expected: []string{"", ""},
|
||||
},
|
||||
{
|
||||
name: "Complex events",
|
||||
input: "pull_request,pull_request_review_approved,pull_request_sync",
|
||||
expected: []string{"pull_request", "pull_request_review_approved", "pull_request_sync"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
eventsList := strings.Split(tt.input, ",")
|
||||
events := make([]string, len(eventsList))
|
||||
for i, event := range eventsList {
|
||||
events[i] = strings.TrimSpace(event)
|
||||
}
|
||||
|
||||
assert.Equal(t, tt.expected, events)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebhookConfigConstruction(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
secret string
|
||||
expectedKeys []string
|
||||
expectedValues map[string]string
|
||||
}{
|
||||
{
|
||||
name: "Basic config",
|
||||
url: "https://example.com/webhook",
|
||||
expectedKeys: []string{"url", "http_method", "content_type"},
|
||||
expectedValues: map[string]string{
|
||||
"url": "https://example.com/webhook",
|
||||
"http_method": "post",
|
||||
"content_type": "json",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Config with secret",
|
||||
url: "https://example.com/webhook",
|
||||
secret: "my-secret",
|
||||
expectedKeys: []string{"url", "http_method", "content_type", "secret"},
|
||||
expectedValues: map[string]string{
|
||||
"url": "https://example.com/webhook",
|
||||
"http_method": "post",
|
||||
"content_type": "json",
|
||||
"secret": "my-secret",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Complete config",
|
||||
url: "https://example.com/webhook",
|
||||
secret: "secret123",
|
||||
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",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
config := map[string]string{
|
||||
"url": tt.url,
|
||||
"http_method": "post",
|
||||
"content_type": "json",
|
||||
}
|
||||
|
||||
if tt.secret != "" {
|
||||
config["secret"] = tt.secret
|
||||
}
|
||||
|
||||
// Check all expected keys exist
|
||||
for _, key := range tt.expectedKeys {
|
||||
assert.Contains(t, config, key, "Expected key %s not found", key)
|
||||
}
|
||||
|
||||
// Check expected values
|
||||
for key, expectedValue := range tt.expectedValues {
|
||||
assert.Equal(t, expectedValue, config[key], "Value mismatch for key %s", key)
|
||||
}
|
||||
|
||||
// Check no unexpected keys
|
||||
assert.Len(t, config, len(tt.expectedKeys), "Config has unexpected keys")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebhookCreateOptions(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
webhookType string
|
||||
events []string
|
||||
active bool
|
||||
config map[string]string
|
||||
branchFilter string
|
||||
authHeader string
|
||||
}{
|
||||
{
|
||||
name: "Gitea webhook",
|
||||
webhookType: "gitea",
|
||||
events: []string{"push", "pull_request"},
|
||||
active: true,
|
||||
config: map[string]string{
|
||||
"url": "https://example.com/webhook",
|
||||
"http_method": "post",
|
||||
"content_type": "json",
|
||||
},
|
||||
branchFilter: "main",
|
||||
authHeader: "X-Token: abc",
|
||||
},
|
||||
{
|
||||
name: "Slack webhook",
|
||||
webhookType: "slack",
|
||||
events: []string{"push"},
|
||||
active: true,
|
||||
config: map[string]string{
|
||||
"url": "https://hooks.slack.com/services/xxx",
|
||||
"http_method": "post",
|
||||
"content_type": "json",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Discord webhook",
|
||||
webhookType: "discord",
|
||||
events: []string{"pull_request", "pull_request_review_approved"},
|
||||
active: false,
|
||||
config: map[string]string{
|
||||
"url": "https://discord.com/api/webhooks/xxx",
|
||||
"http_method": "post",
|
||||
"content_type": "json",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
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,
|
||||
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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebhookURLValidation(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "Valid HTTPS URL",
|
||||
url: "https://example.com/webhook",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Valid HTTP URL",
|
||||
url: "http://localhost:8080/webhook",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Slack webhook URL",
|
||||
url: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Discord webhook URL",
|
||||
url: "https://discord.com/api/webhooks/123456789/abcdefgh",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Empty URL",
|
||||
url: "",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "Invalid URL scheme",
|
||||
url: "ftp://example.com/webhook",
|
||||
expectErr: false, // URL validation is handled by Gitea API
|
||||
},
|
||||
{
|
||||
name: "URL with path",
|
||||
url: "https://example.com/api/v1/webhook",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "URL with query params",
|
||||
url: "https://example.com/webhook?token=abc123",
|
||||
expectErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Basic URL validation - empty check
|
||||
if tt.url == "" && tt.expectErr {
|
||||
assert.Empty(t, tt.url, "Empty URL should be caught")
|
||||
} else if tt.url != "" {
|
||||
assert.NotEmpty(t, tt.url, "Non-empty URL should pass basic validation")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebhookEventValidation(t *testing.T) {
|
||||
validEvents := []string{
|
||||
"push",
|
||||
"pull_request",
|
||||
"pull_request_sync",
|
||||
"pull_request_comment",
|
||||
"pull_request_review_approved",
|
||||
"pull_request_review_rejected",
|
||||
"pull_request_assigned",
|
||||
"pull_request_label",
|
||||
"pull_request_milestone",
|
||||
"issues",
|
||||
"issue_comment",
|
||||
"issue_assign",
|
||||
"issue_label",
|
||||
"issue_milestone",
|
||||
"create",
|
||||
"delete",
|
||||
"fork",
|
||||
"release",
|
||||
"wiki",
|
||||
"repository",
|
||||
}
|
||||
|
||||
for _, event := range validEvents {
|
||||
t.Run("Event_"+event, func(t *testing.T) {
|
||||
assert.NotEmpty(t, event, "Event name should not be empty")
|
||||
assert.NotContains(t, event, " ", "Event name should not contain spaces")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateCommandFlags(t *testing.T) {
|
||||
cmd := &CmdWebhooksCreate
|
||||
|
||||
// Test flag existence
|
||||
expectedFlags := []string{
|
||||
"type",
|
||||
"secret",
|
||||
"events",
|
||||
"active",
|
||||
"branch-filter",
|
||||
"authorization-header",
|
||||
}
|
||||
|
||||
for _, flagName := range expectedFlags {
|
||||
found := false
|
||||
for _, flag := range cmd.Flags {
|
||||
if flag.Names()[0] == flagName {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.True(t, found, "Expected flag %s not found", flagName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateCommandMetadata(t *testing.T) {
|
||||
cmd := &CmdWebhooksCreate
|
||||
|
||||
assert.Equal(t, "create", cmd.Name)
|
||||
assert.Contains(t, cmd.Aliases, "c")
|
||||
assert.Equal(t, "Create a webhook", cmd.Usage)
|
||||
assert.Equal(t, "Create a webhook in repository, organization, or globally", cmd.Description)
|
||||
assert.Equal(t, "<webhook-url>", cmd.ArgsUsage)
|
||||
assert.NotNil(t, cmd.Action)
|
||||
}
|
||||
|
||||
func TestDefaultFlagValues(t *testing.T) {
|
||||
cmd := &CmdWebhooksCreate
|
||||
|
||||
// Find specific flags and test their defaults
|
||||
for _, flag := range cmd.Flags {
|
||||
switch f := flag.(type) {
|
||||
case *cli.StringFlag:
|
||||
switch f.Name {
|
||||
case "type":
|
||||
assert.Equal(t, "gitea", f.Value)
|
||||
case "events":
|
||||
assert.Equal(t, "push", f.Value)
|
||||
}
|
||||
case *cli.BoolFlag:
|
||||
switch f.Name {
|
||||
case "active":
|
||||
assert.True(t, f.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user