watchpr: reject --max-wait with --once, test exit-code mapping
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful

This commit is contained in:
2026-10-05 22:05:09 +11:00
parent 639bcbda49
commit 00ba3df49c
2 changed files with 44 additions and 5 deletions
+14 -5
View File
@@ -47,12 +47,18 @@ var errTimedOut = errors.New("max-wait elapsed with no change")
func main() {
// cobra prints the error itself (SilenceErrors stays off); we only need to
// turn any command error into a non-zero exit.
if err := newRootCmd().Execute(); err != nil {
if errors.Is(err, errTimedOut) {
os.Exit(exitTimedOut)
}
os.Exit(1)
os.Exit(exitCode(newRootCmd().Execute()))
}
// exitCode maps a command result to the process exit status.
func exitCode(err error) int {
switch {
case err == nil:
return 0
case errors.Is(err, errTimedOut):
return exitTimedOut
}
return 1
}
// newRootCmd builds the watchpr command tree. It is separated from main so
@@ -86,6 +92,9 @@ func newRootCmd() *cobra.Command {
if err != nil {
return err
}
if once && maxWait > 0 {
return fmt.Errorf("--max-wait has no effect with --once")
}
refs := make([]agent.PRRef, 0, len(args))
for _, a := range args {
ref, err := agent.ParsePRRef(a)
+30
View File
@@ -336,6 +336,36 @@ func TestExecuteBadMaxWaitErrors(t *testing.T) {
}
}
func TestExecuteOnceWithMaxWaitErrors(t *testing.T) {
cmd := newRootCmd()
cmd.SetArgs([]string{"--once", "--max-wait", "5m", "unkin/repo#1"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
err := cmd.Execute()
if err == nil || !strings.Contains(err.Error(), "--once") {
t.Fatalf("Execute() = %v, want a --once/--max-wait conflict error", err)
}
if got := exitCode(err); got != 1 {
t.Fatalf("exitCode = %d, want 1", got)
}
}
func TestExitCode(t *testing.T) {
for _, tc := range []struct {
err error
want int
}{
{nil, 0},
{errTimedOut, exitTimedOut},
{fmt.Errorf("wrapped: %w", errTimedOut), exitTimedOut},
{errors.New("boom"), 1},
} {
if got := exitCode(tc.err); got != tc.want {
t.Errorf("exitCode(%v) = %d, want %d", tc.err, got, tc.want)
}
}
}
// Ticks pass through until the deadline fires; then the channel closes without
// waiting for another tick.
func TestUntilDeadline(t *testing.T) {