mirror of
https://gitea.com/gitea/gitea-mcp.git
synced 2026-08-27 02:27:45 +00:00
6744cab627
Add a GITEA_EXTRA_HEADERS environment variable that accepts a JSON object of header name/value pairs (e.g. Cloudflare Access credentials) and applies them to every outbound request to Gitea, both the raw pkg/gitea.DoJSON/DoBytes path and the SDK-backed pkg/gitea.NewClient path, without overriding Authorization, Content-Type, or Accept. Co-Authored-By: Codet <codet@commitgo.dev> (GPT-5-Codex)
150 lines
4.1 KiB
Go
150 lines
4.1 KiB
Go
package cmd
|
|
|
|
import (
|
|
"bytes"
|
|
"flag"
|
|
"maps"
|
|
"slices"
|
|
"strings"
|
|
"testing"
|
|
|
|
flagPkg "gitea.com/gitea/gitea-mcp/pkg/flag"
|
|
)
|
|
|
|
func TestInitFlagSetBind(t *testing.T) {
|
|
for _, test := range []struct {
|
|
name string
|
|
args []string
|
|
want string
|
|
}{
|
|
{name: "default is empty, meaning all interfaces", args: []string{}},
|
|
{name: "-b sets the address", args: []string{"-b", "127.0.0.1"}, want: "127.0.0.1"},
|
|
{name: "-bind sets an IPv6 literal", args: []string{"-bind", "::1"}, want: "::1"},
|
|
} {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
t.Cleanup(func() { flagPkg.Bind = "" })
|
|
fs := flag.NewFlagSet("test", flag.ContinueOnError)
|
|
initFlagSet(fs, test.args, func(string) string { return "" }, func(string) ([]byte, error) { return nil, nil }, &bytes.Buffer{})
|
|
if flagPkg.Bind != test.want {
|
|
t.Errorf("Bind = %q, want %q", flagPkg.Bind, test.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestInitFlagSetScopes(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
env map[string]string
|
|
want []string
|
|
}{
|
|
{
|
|
name: "no scope flag or env leaves AllowedScopes unset",
|
|
args: []string{},
|
|
want: nil,
|
|
},
|
|
{
|
|
name: "-S sets a single scope",
|
|
args: []string{"-S", "repository"},
|
|
want: []string{"repository"},
|
|
},
|
|
{
|
|
name: "-scope sets a comma-separated list",
|
|
args: []string{"-scope", "repository,file"},
|
|
want: []string{"file", "repository"},
|
|
},
|
|
{
|
|
name: "GITEA_SCOPES env sets the default",
|
|
args: []string{},
|
|
env: map[string]string{"GITEA_SCOPES": "issue,pull_request"},
|
|
want: []string{"issue", "pull_request"},
|
|
},
|
|
{
|
|
name: "-S flag takes precedence over GITEA_SCOPES env",
|
|
args: []string{"-S", "file"},
|
|
env: map[string]string{"GITEA_SCOPES": "issue"},
|
|
want: []string{"file"},
|
|
},
|
|
{
|
|
name: "normalizes case, whitespace, and hyphens/spaces to underscores",
|
|
args: []string{"-S", " Pull Request , pull-request , PULL_REQUEST "},
|
|
want: []string{"pull_request"},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
origScopes := flagPkg.AllowedScopes
|
|
t.Cleanup(func() {
|
|
flagPkg.AllowedScopes = origScopes
|
|
})
|
|
flagPkg.AllowedScopes = nil
|
|
|
|
getenv := func(key string) string { return tt.env[key] }
|
|
readFile := func(string) ([]byte, error) { return nil, nil }
|
|
fs := flag.NewFlagSet("test", flag.ContinueOnError)
|
|
var stderr bytes.Buffer
|
|
|
|
initFlagSet(fs, tt.args, getenv, readFile, &stderr)
|
|
|
|
got := slices.Sorted(maps.Keys(flagPkg.AllowedScopes))
|
|
want := slices.Clone(tt.want)
|
|
slices.Sort(want)
|
|
if !slices.Equal(got, want) {
|
|
t.Errorf("AllowedScopes = %v, want %v", got, want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestInitFlagSetExtraHeaders(t *testing.T) {
|
|
t.Cleanup(func() { flagPkg.ExtraHeaders = nil })
|
|
|
|
getenv := func(key string) string {
|
|
if key == "GITEA_EXTRA_HEADERS" {
|
|
return `{"CF-Access-Client-Id":"id","CF-Access-Client-Secret":"secret"}`
|
|
}
|
|
return ""
|
|
}
|
|
readFile := func(string) ([]byte, error) { return nil, nil }
|
|
fs := flag.NewFlagSet("test", flag.ContinueOnError)
|
|
var stderr bytes.Buffer
|
|
|
|
initFlagSet(fs, []string{}, getenv, readFile, &stderr)
|
|
|
|
if got := flagPkg.ExtraHeaders.Get("CF-Access-Client-Id"); got != "id" {
|
|
t.Errorf("ExtraHeaders[CF-Access-Client-Id] = %q, want %q", got, "id")
|
|
}
|
|
if got := flagPkg.ExtraHeaders.Get("CF-Access-Client-Secret"); got != "secret" {
|
|
t.Errorf("ExtraHeaders[CF-Access-Client-Secret] = %q, want %q", got, "secret")
|
|
}
|
|
}
|
|
|
|
func TestInitFlagSetExtraHeadersInvalidJSON(t *testing.T) {
|
|
t.Cleanup(func() { flagPkg.ExtraHeaders = nil })
|
|
|
|
origOsExit := osExit
|
|
var exitCode int
|
|
osExit = func(code int) { exitCode = code }
|
|
t.Cleanup(func() { osExit = origOsExit })
|
|
|
|
getenv := func(key string) string {
|
|
if key == "GITEA_EXTRA_HEADERS" {
|
|
return `not-json`
|
|
}
|
|
return ""
|
|
}
|
|
readFile := func(string) ([]byte, error) { return nil, nil }
|
|
fs := flag.NewFlagSet("test", flag.ContinueOnError)
|
|
var stderr bytes.Buffer
|
|
|
|
initFlagSet(fs, []string{}, getenv, readFile, &stderr)
|
|
|
|
if exitCode != 1 {
|
|
t.Errorf("exitCode = %d, want 1", exitCode)
|
|
}
|
|
if !strings.Contains(stderr.String(), "GITEA_EXTRA_HEADERS") {
|
|
t.Errorf("stderr = %q, want mention of GITEA_EXTRA_HEADERS", stderr.String())
|
|
}
|
|
}
|