Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
66e0e1e
models/fixtures: remove test data from webhook.yml, use code to inser…
Copilot Apr 25, 2026
8bb79e7
models/webhook: use db.Insert in tests, merge fixture setup into prep…
Copilot Apr 25, 2026
d3341cf
models/webhook: address review feedback - add RepoID to hookOwner3, u…
Copilot Apr 25, 2026
502c76e
fix
wxiaoguang Apr 25, 2026
e07cf5b
fix lint
wxiaoguang Apr 25, 2026
9147c35
fine tune
wxiaoguang Apr 25, 2026
a6bfda0
fix test
wxiaoguang Apr 25, 2026
9553fae
clean up
wxiaoguang Apr 25, 2026
17cca5c
fix
wxiaoguang Apr 25, 2026
7a1f463
don't send request to example.com
wxiaoguang Apr 25, 2026
363daae
unify path init
wxiaoguang Apr 25, 2026
9abb18c
fix test
wxiaoguang Apr 25, 2026
3359227
fix test
wxiaoguang Apr 25, 2026
5204ef9
fine tune
wxiaoguang Apr 25, 2026
54d3e43
fix test
wxiaoguang Apr 25, 2026
398b47f
debug
wxiaoguang Apr 25, 2026
a973269
debug
wxiaoguang Apr 25, 2026
11f910c
debug
wxiaoguang Apr 25, 2026
1591c06
debug
wxiaoguang Apr 25, 2026
18795df
debug
wxiaoguang Apr 25, 2026
888f4da
debug
wxiaoguang Apr 25, 2026
f310b1c
debug
wxiaoguang Apr 25, 2026
81fcfab
fix
wxiaoguang Apr 25, 2026
0b7aee8
fix
wxiaoguang Apr 25, 2026
e86d62e
clean up
wxiaoguang Apr 25, 2026
9294e96
fix test
wxiaoguang Apr 25, 2026
1d6a95f
fix test
wxiaoguang Apr 25, 2026
09cf004
clean up paths
wxiaoguang Apr 25, 2026
b6831e0
fine tune comments
wxiaoguang Apr 25, 2026
632765f
Apply suggestion from @silverwind
silverwind Apr 25, 2026
6dd7f76
Apply suggestion from @silverwind
silverwind Apr 25, 2026
675ad20
Apply suggestion from @silverwind
silverwind Apr 25, 2026
aee8bfc
Apply suggestion from @silverwind
silverwind Apr 25, 2026
adb8895
Merge branch 'main' into copilot/remove-text-fixtures-webhook-yml
silverwind Apr 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 0 additions & 38 deletions cmd/cmd_test.go

This file was deleted.

237 changes: 237 additions & 0 deletions cmd/cmdtest/cmd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

// Tests here reload the config system multiple times with uncontrollable details.
// So they must be in a separate package, to avoid affecting other tests

package cmdtest

import (
"context"
"errors"
"fmt"
"io"
"path/filepath"
"strings"
"testing"

"code.gitea.io/gitea/cmd"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/util"

"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v3"
)

func TestMain(m *testing.M) {
unittest.MainTest(m)
}

func makePathOutput(workPath, customPath, customConf string) string {
return fmt.Sprintf("WorkPath=%s\nCustomPath=%s\nCustomConf=%s", workPath, customPath, customConf)
}

func newTestApp(testCmd cli.Command) *cli.Command {
app := cmd.NewMainApp(cmd.AppVersion{})
testCmd.Name = util.IfZero(testCmd.Name, "test-cmd")
cmd.PrepareSubcommandWithGlobalFlags(&testCmd)
app.Commands = append(app.Commands, &testCmd)
app.DefaultCommand = testCmd.Name
return app
}

type runResult struct {
Stdout string
Stderr string
ExitCode int
}

func runTestApp(app *cli.Command, args ...string) (runResult, error) {
outBuf := new(strings.Builder)
errBuf := new(strings.Builder)
app.Writer = outBuf
app.ErrWriter = errBuf
exitCode := -1
defer test.MockVariableValue(&cli.ErrWriter, app.ErrWriter)()
defer test.MockVariableValue(&cli.OsExiter, func(code int) {
if exitCode == -1 {
exitCode = code // save the exit code once and then reset the writer (to simulate the exit)
app.Writer, app.ErrWriter, cli.ErrWriter = io.Discard, io.Discard, io.Discard
}
})()
err := cmd.RunMainApp(app, args...)
return runResult{outBuf.String(), errBuf.String(), exitCode}, err
}

func TestCliCmd(t *testing.T) {
defaultWorkPath := filepath.FromSlash("/tmp/mocked-work-path")
defaultCustomPath := filepath.Join(defaultWorkPath, "custom")
defaultCustomConf := filepath.Join(defaultCustomPath, "conf/app.ini")
defer setting.MockBuiltinPaths(defaultWorkPath, "", "")()

cli.CommandHelpTemplate = "(command help template)"
cli.RootCommandHelpTemplate = "(app help template)"
cli.SubcommandHelpTemplate = "(subcommand help template)"

cases := []struct {
env map[string]string
cmd string
exp string
}{
// help commands
{
cmd: "./gitea -h",
exp: "DEFAULT CONFIGURATION:",
},
{
cmd: "./gitea help",
exp: "DEFAULT CONFIGURATION:",
},

{
cmd: "./gitea -c /dev/null -h",
exp: "ConfigFile: /dev/null",
},

{
cmd: "./gitea -c /dev/null help",
exp: "ConfigFile: /dev/null",
},
{
cmd: "./gitea help -c /dev/null",
exp: "ConfigFile: /dev/null",
},

{
cmd: "./gitea -c /dev/null test-cmd -h",
exp: "ConfigFile: /dev/null",
},
{
cmd: "./gitea test-cmd -c /dev/null -h",
exp: "ConfigFile: /dev/null",
},
{
cmd: "./gitea test-cmd -h -c /dev/null",
exp: "ConfigFile: /dev/null",
},

{
cmd: "./gitea -c /dev/null test-cmd help",
exp: "ConfigFile: /dev/null",
},
{
cmd: "./gitea test-cmd -c /dev/null help",
exp: "ConfigFile: /dev/null",
},
{
cmd: "./gitea test-cmd help -c /dev/null",
exp: "ConfigFile: /dev/null",
},

// parse paths
{
cmd: "./gitea test-cmd",
exp: makePathOutput(defaultWorkPath, defaultCustomPath, defaultCustomConf),
},
{
cmd: "./gitea -c /tmp/app.ini test-cmd",
exp: makePathOutput(defaultWorkPath, defaultCustomPath, "/tmp/app.ini"),
},
{
cmd: "./gitea test-cmd -c /tmp/app.ini",
exp: makePathOutput(defaultWorkPath, defaultCustomPath, "/tmp/app.ini"),
},
{
env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
cmd: "./gitea test-cmd",
exp: makePathOutput("/tmp", "/tmp/custom", "/tmp/custom/conf/app.ini"),
},
{
env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
cmd: "./gitea test-cmd --work-path /tmp/other",
exp: makePathOutput("/tmp/other", "/tmp/other/custom", "/tmp/other/custom/conf/app.ini"),
},
{
env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
cmd: "./gitea test-cmd --config /tmp/app-other.ini",
exp: makePathOutput("/tmp", "/tmp/custom", "/tmp/app-other.ini"),
},
}

for _, c := range cases {
t.Run(c.cmd, func(t *testing.T) {
app := newTestApp(cli.Command{
Action: func(ctx context.Context, cmd *cli.Command) error {
_, _ = fmt.Fprint(cmd.Root().Writer, makePathOutput(setting.AppWorkPath, setting.CustomPath, setting.CustomConf))
return nil
},
})
for k, v := range c.env {
t.Setenv(k, v)
}
args := strings.Split(c.cmd, " ") // for test only, "split" is good enough
r, err := runTestApp(app, args...)
assert.NoError(t, err, c.cmd)
assert.NotEmpty(t, c.exp, c.cmd)
if !assert.Contains(t, r.Stdout, c.exp, c.cmd) {
t.Log("Full output:\n" + r.Stdout)
t.Log("Expected:\n" + c.exp)
}
})
}
}

func TestCliCmdError(t *testing.T) {
app := newTestApp(cli.Command{Action: func(ctx context.Context, cmd *cli.Command) error { return errors.New("normal error") }})
r, err := runTestApp(app, "./gitea", "test-cmd")
assert.Error(t, err)
assert.Equal(t, 1, r.ExitCode)
assert.Empty(t, r.Stdout)
assert.Equal(t, "Command error: normal error\n", r.Stderr)

app = newTestApp(cli.Command{Action: func(ctx context.Context, cmd *cli.Command) error { return cli.Exit("exit error", 2) }})
r, err = runTestApp(app, "./gitea", "test-cmd")
assert.Error(t, err)
assert.Equal(t, 2, r.ExitCode)
assert.Empty(t, r.Stdout)
assert.Equal(t, "exit error\n", r.Stderr)

app = newTestApp(cli.Command{Action: func(ctx context.Context, cmd *cli.Command) error { return nil }})
r, err = runTestApp(app, "./gitea", "test-cmd", "--no-such")
assert.Error(t, err)
assert.Equal(t, 1, r.ExitCode)
assert.Empty(t, r.Stdout)
assert.Equal(t, "Incorrect Usage: flag provided but not defined: -no-such\n\n", r.Stderr)

app = newTestApp(cli.Command{Action: func(ctx context.Context, cmd *cli.Command) error { return nil }})
r, err = runTestApp(app, "./gitea", "test-cmd")
assert.NoError(t, err)
assert.Equal(t, -1, r.ExitCode) // the cli.OsExiter is not called
assert.Empty(t, r.Stdout)
assert.Empty(t, r.Stderr)
}

func TestCliCmdBefore(t *testing.T) {
ctxNew := context.WithValue(context.Background(), any("key"), "value")
configValues := map[string]string{}
setting.CustomConf = "/tmp/any.ini"
var actionCtx context.Context
app := newTestApp(cli.Command{
Before: func(context.Context, *cli.Command) (context.Context, error) {
configValues["before"] = setting.CustomConf
return ctxNew, nil
},
Action: func(ctx context.Context, cmd *cli.Command) error {
configValues["action"] = setting.CustomConf
actionCtx = ctx
return nil
},
})
_, err := runTestApp(app, "./gitea", "--config", "/dev/null", "test-cmd")
assert.NoError(t, err)
assert.Equal(t, ctxNew, actionCtx)
assert.Equal(t, "/tmp/any.ini", configValues["before"], "BeforeFunc must be called before preparing config")
assert.Equal(t, "/dev/null", configValues["action"])
}
File renamed without changes.
4 changes: 2 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ DEFAULT CONFIGURATION:
}
}

Comment thread
wxiaoguang marked this conversation as resolved.
func prepareSubcommandWithGlobalFlags(originCmd *cli.Command) {
func PrepareSubcommandWithGlobalFlags(originCmd *cli.Command) {
originBefore := originCmd.Before
originCmd.Before = func(ctxOrig context.Context, cmd *cli.Command) (ctx context.Context, err error) {
ctx = ctxOrig
Comment thread
wxiaoguang marked this conversation as resolved.
Expand Down Expand Up @@ -145,7 +145,7 @@ func NewMainApp(appVer AppVersion) *cli.Command {

app.Before = PrepareConsoleLoggerLevel(log.INFO)
for i := range subCmdWithConfig {
prepareSubcommandWithGlobalFlags(subCmdWithConfig[i])
PrepareSubcommandWithGlobalFlags(subCmdWithConfig[i])
}
app.Commands = append(app.Commands, subCmdWithConfig...)
app.Commands = append(app.Commands, subCmdStandalone...)
Expand Down
Loading
Loading