From 66397054fa703ef7bc47823130238bdb1175358c Mon Sep 17 00:00:00 2001 From: Anuj Chaudhari Date: Tue, 6 Jan 2026 20:03:45 -0800 Subject: [PATCH] Update go-interact and fix keyboard interrupt handling - Upgrade go-interact from legacy version to v1.0.2 - Update keyboard interrupt detection to use io.EOF - Update tests to reflect new interrupt behavior --- go.mod | 3 +-- go.sum | 5 ++--- util/ui/prompt.go | 5 +++-- util/ui/prompt_test.go | 15 ++++++++------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index ded72670138..f6bea2f71a4 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( github.com/sajari/fuzzy v1.0.0 github.com/sirupsen/logrus v1.9.3 github.com/tedsuo/rata v1.0.1-0.20170830210128-07d200713958 - github.com/vito/go-interact v0.0.0-20171111012221-fa338ed9e9ec + github.com/vito/go-interact v1.0.2 golang.org/x/crypto v0.46.0 golang.org/x/net v0.48.0 golang.org/x/term v0.38.0 @@ -68,7 +68,6 @@ require ( github.com/google/pprof v0.0.0-20251213031049-b05bdaca462f // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kr/pty v1.1.8 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect diff --git a/go.sum b/go.sum index d0b124b7293..51491626484 100644 --- a/go.sum +++ b/go.sum @@ -57,7 +57,6 @@ github.com/cloudfoundry/bosh-utils v0.0.397/go.mod h1:FPZV+W2FecYFy2N5iWeDFYQvtk github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= github.com/cppforlife/go-patch v0.1.0 h1:I0fT+gFTSW4xWwvaTaUUVjr9xxjNXJ4naGc01BeQjwY= github.com/cppforlife/go-patch v0.1.0/go.mod h1:67a7aIi94FHDZdoeGSJRRFDp66l9MhaAG1yGxpUoFD8= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= @@ -263,8 +262,8 @@ github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhso github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/unrolled/secure v0.0.0-20180416205222-a1cf62cc2159/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA= -github.com/vito/go-interact v0.0.0-20171111012221-fa338ed9e9ec h1:Klu98tQ9Z1t23gvC7p7sCmvxkZxLhBHLNyrUPsWsYFg= -github.com/vito/go-interact v0.0.0-20171111012221-fa338ed9e9ec/go.mod h1:wPlfmglZmRWMYv/qJy3P+fK/UnoQB5ISk4txfNd9tDo= +github.com/vito/go-interact v1.0.2 h1:viJuANio3WH9utUG4rKbJC9V3JR5JgYNS+i0efeA+GU= +github.com/vito/go-interact v1.0.2/go.mod h1:s+y0jK9Z2etBYt5ZM6+DhpOsE5C7NNGC3jrJvW0BBpc= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/util/ui/prompt.go b/util/ui/prompt.go index 4049750bfaf..8c1815d740d 100644 --- a/util/ui/prompt.go +++ b/util/ui/prompt.go @@ -7,7 +7,6 @@ import ( "strconv" "github.com/vito/go-interact/interact" - "github.com/vito/go-interact/interact/terminal" ) const sigIntExitCode = 130 @@ -146,5 +145,7 @@ func contains(s []string, v string) bool { } func isInterrupt(err error) bool { - return err == interact.ErrKeyboardInterrupt || err == terminal.ErrKeyboardInterrupt + // In go-interact v1.0.1+, which uses golang.org/x/term, + // keyboard interrupts (Ctrl+C) result in io.EOF + return err == io.EOF } diff --git a/util/ui/prompt_test.go b/util/ui/prompt_test.go index 93823f3fbf5..46ac355aad8 100644 --- a/util/ui/prompt_test.go +++ b/util/ui/prompt_test.go @@ -1,6 +1,7 @@ package ui_test import ( + "io" "regexp" "code.cloudfoundry.org/cli/v9/util/configv3" @@ -9,7 +10,6 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gbytes" - "github.com/vito/go-interact/interact" ) var _ = Describe("Prompts", func() { @@ -379,7 +379,8 @@ var _ = Describe("Prompts", func() { BeforeEach(func() { fakeResolver = new(uifakes.FakeResolver) - fakeResolver.ResolveReturns(interact.ErrKeyboardInterrupt) + // In go-interact v1.0.1+, keyboard interrupts return io.EOF + fakeResolver.ResolveReturns(io.EOF) fakeExiter = new(uifakes.FakeExiter) fakeInteractor = new(uifakes.FakeInteractor) fakeInteractor.NewInteractionReturns(fakeResolver) @@ -391,7 +392,7 @@ var _ = Describe("Prompts", func() { _, err := ui.DisplayPasswordPrompt("App {{.AppName}} does not exist.", map[string]interface{}{ "AppName": "some-app", }) - Expect(err).To(MatchError("keyboard interrupt")) + Expect(err).To(MatchError(io.EOF)) Expect(fakeExiter.ExitCallCount()).To(Equal(1)) Expect(fakeExiter.ExitArgsForCall(0)).To(Equal(130)) }) @@ -400,7 +401,7 @@ var _ = Describe("Prompts", func() { _, err := ui.DisplayTextPrompt("App {{.AppName}} does not exist.", map[string]interface{}{ "AppName": "some-app", }) - Expect(err).To(MatchError("keyboard interrupt")) + Expect(err).To(MatchError(io.EOF)) Expect(fakeExiter.ExitCallCount()).To(Equal(1)) Expect(fakeExiter.ExitArgsForCall(0)).To(Equal(130)) }) @@ -409,14 +410,14 @@ var _ = Describe("Prompts", func() { _, err := ui.DisplayOptionalTextPrompt("some-default-value", "App {{.AppName}} does not exist.", map[string]interface{}{ "AppName": "some-app", }) - Expect(err).To(MatchError("keyboard interrupt")) + Expect(err).To(MatchError(io.EOF)) Expect(fakeExiter.ExitCallCount()).To(Equal(1)) Expect(fakeExiter.ExitArgsForCall(0)).To(Equal(130)) }) It("exits immediately from bool prompt", func() { _, err := ui.DisplayBoolPrompt(false, "some-prompt", nil) - Expect(err).To(MatchError("keyboard interrupt")) + Expect(err).To(MatchError(io.EOF)) Expect(fakeExiter.ExitCallCount()).To(Equal(1)) Expect(fakeExiter.ExitArgsForCall(0)).To(Equal(130)) }) @@ -425,7 +426,7 @@ var _ = Describe("Prompts", func() { choices := []string{"foo", "bar"} choice, err := ui.DisplayTextMenu(choices, "choose!") Expect(choice).To(Equal("")) - Expect(err).To(MatchError("keyboard interrupt")) + Expect(err).To(MatchError(io.EOF)) Expect(fakeExiter.ExitCallCount()).To(Equal(1)) Expect(fakeExiter.ExitArgsForCall(0)).To(Equal(130)) })