Skip to content

cmd/prompt: remove uses of github.com/AlecAivazis/survey/v2 - #14161

Open
thaJeztah wants to merge 1 commit into
docker:mainfrom
thaJeztah:rm_survey
Open

cmd/prompt: remove uses of github.com/AlecAivazis/survey/v2#14161
thaJeztah wants to merge 1 commit into
docker:mainfrom
thaJeztah:rm_survey

Conversation

@thaJeztah

@thaJeztah thaJeztah commented Sep 1, 2026

Copy link
Copy Markdown
Member

The github.com/AlecAivazis/survey/v2 module was archived and is no longer
maintained. Looking at the code, we didn't really use most of its features;
current callers already include the confirmation hint in the prompt
message, so survey mostly provided terminal input handling around a simple
yes/no question.

Replace the interactive confirmation implementation with
golang.org/x/term while keeping the exported prompt types and existing
non-terminal prompt behavior unchanged. Interactive prompts continue to
use raw terminal input so Ctrl+C is handled by the prompt instead of
requiring a second interrupt to terminate the process.

What I did

Related issue

(not mandatory) A picture of a cute animal, if possible in relation to what you did

@docker-agent docker-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assessment: 🟡 NEEDS ATTENTION

This PR cleanly removes the archived survey/v2 dependency and replaces it with a minimal local line-based implementation. The overall approach is sound. Two behavioral regressions in the new confirm() function are worth addressing before merge.

Comment thread cmd/prompt/prompt.go Outdated
}

func confirm(stdin *bufio.Reader, stdout io.Writer, message string, defaultValue bool) (bool, error) {
_, _ = fmt.Fprint(stdout, message)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] confirm() does not print [y/N] hint; behavioral regression from survey.Confirm

The new confirm() function writes message verbatim to stdout with no indication of valid responses or the current default:

_, _ = fmt.Fprint(stdout, message)

survey.Confirm automatically appended (y/N) or (Y/n) (depending on defaultValue) to every prompt. The new implementation omits this entirely. Unless every caller already embeds the hint in its own message string, users running in a terminal will see a bare prompt with no cue that y/n are the expected inputs or which value is the default.

Consider appending the hint in confirm() itself so callers don't have to know about this detail:

Suggested change
_, _ = fmt.Fprint(stdout, message)
if defaultValue {
_, _ = fmt.Fprintf(stdout, "%s [Y/n] ", message)
} else {
_, _ = fmt.Fprintf(stdout, "%s [y/N] ", message)
}
Confidence Score
🟡 moderate 70/100

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's already handled by callers, which include it, so we just print verbatim; e.g.;

msg := "\nDo you want to proceed with these variables? [Y/n]: "

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, thanks for the clarification. I see that both call sites in options.go already include the hint in their message strings (line 166 uses [Y/n] and line 290 uses [y/N]), so the verbatim printing is intentional and there's no regression here.

I should have checked all the callers before flagging this. Apologies for the noise!

Comment thread cmd/prompt/prompt.go Outdated

@glours glours left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I confirm the 2 catches made by @docker-agent and found a 3rd one

Comment thread cmd/prompt/prompt.go Outdated
func confirm(stdin *bufio.Reader, stdout io.Writer, message string, defaultValue bool) (bool, error) {
_, _ = fmt.Fprint(stdout, message)

answer, err := stdin.ReadString('\n')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This blocking read has no way to observe cancellation. Since AdaptCmd's SIGINT handler (cmd/compose/compose.go:112) now intercepts Ctrl+C to cancel the context instead of letting the OS kill the process, a single Ctrl+C at a prompt no longer aborts it, the read stays blocked here and a second Ctrl+C is needed to actually terminate.
survey's raw-mode reader handled this internally (ISIG disabled, Ctrl+C caught as a keypress).

@thaJeztah

Copy link
Copy Markdown
Member Author

Ah, yes, I need to look at this one; I thought I'd move this separate, but didn't look too closely yet 😂

@thaJeztah
thaJeztah force-pushed the rm_survey branch 2 times, most recently from bed0960 to e61e69a Compare September 5, 2026 12:09

@docker-agent docker-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assessment: 🟢 APPROVE

The PR correctly removes the archived github.com/AlecAivazis/survey/v2 dependency and replaces it with golang.org/x/term. The core Confirm implementation is structurally sound: SetRawTerminal / defer RestoreTerminal is safe, term.NewTerminal usage is idiomatic, the error propagation path is correct, and go.mod properly promotes golang.org/x/term from indirect to direct. The new tests cover the happy path, invalid-input retry, and Ctrl+C interruption.

Lower-confidence findings (not posted inline)

  • [medium → verified low] cmd/prompt/prompt.go:94 — Ctrl+C handling relies on term.ReadLine returning io.EOF on byte 0x03; if golang.org/x/term changes this behaviour in a future release the loop would spin indefinitely until the TTY is closed. Currently working as intended in v0.45.0 — the verifier assessed this as speculative/low, score 40/100 (🟠 weak). No action required now; worth a comment in the code or a version note in go.mod if the team wants to guard against it long-term.

@thaJeztah

Copy link
Copy Markdown
Member Author

if golang.org/x/term changes this behaviour in a future release the loop would spin indefinitely until the TTY is closed. Currently working as intended in v0.45.0

Yeah, not fixing that; we have tests, and they shouldn't break behavior.

@codecov

codecov Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 71.42857% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
cmd/prompt/prompt.go 71.42% 5 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

The github.com/AlecAivazis/survey/v2 module was archived and is no longer
maintained. Looking at the code, we didn't really use most of its features;
current callers already include the confirmation hint in the prompt
message, so survey mostly provided terminal input handling around a simple
yes/no question.

Replace the interactive confirmation implementation with
golang.org/x/term while keeping the exported prompt types and existing
non-terminal prompt behavior unchanged. Interactive prompts continue to
use raw terminal input so Ctrl+C is handled by the prompt instead of
requiring a second interrupt to terminate the process.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
@thaJeztah

Copy link
Copy Markdown
Member Author

Rebased; probably should be OK for review now 😅

@ndeloof ndeloof left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Legitimate change, worth landing: survey/v2 is archived, compose only used a yes/no out of it, and this drops five transitive dependencies while promoting an already-present x/term. Exported API intact, non-terminal Pipe path untouched, the pty-backed tests cover the right level, deferred RestoreTerminal covers error paths, and the retry/Enter-default semantics match survey.

One real compatibility regression and two smaller notes, inline. On top of those, one thing CI cannot tell us: the interactive path now goes through streams SetRawTerminal + x/term.Terminal on a Windows console, a different plumbing than survey's (go-colorable); the pty tests only exercise unix. Worth one manual check on Windows before merge, or a note in the description.

Comment thread cmd/prompt/prompt.go
@@ -74,17 +75,34 @@ func (s streamsFileReader) Fd() uintptr {

// Confirm asks for yes or no input
func (u User) Confirm(message string, defaultValue bool) (bool, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "(y/N)" hint survey auto-appended is lost, and three call sites relied on it — the description's "current callers already include the confirmation hint" holds for the two prompts in cmd/compose/options.go only. These don't carry any hint in their message:

  • pkg/compose/publish.go — "Are you ok to publish these bind mount declarations?" and "…these sensitive data?" (via confirmOrCancel);
  • pkg/bridge/convert.go — "Output directory … will be permanently deleted. Continue?".

After this change those render as a bare question: the user no longer sees the expected input format nor the default — on destructive confirmations. Minimal fix that preserves every caller at once: have Confirm append " [y/N]: " / " [Y/n]: " (per defaultValue) when the message doesn't already end with a hint; alternatively, fix the three messages in this same PR.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you go with option 2 (fixing individual messages rather than the centralized approach), don't miss two more call sites through the same Confirm with the same bare-question issue:

  • pkg/compose/publish.go:619buildEnvPromptMessage: "...Are you ok to publish these env declarations?"
  • pkg/compose/publish.go:629buildConfigContentPromptMessage: "...Are you ok to publish these config contents?"

Comment thread cmd/prompt/prompt.go
return false, err
}

switch strings.ToLower(answer) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: strings.ToLower without strings.TrimSpace — a y (stray whitespace) silently loops back to the prompt, where survey tolerated it. One-liner: switch strings.ToLower(strings.TrimSpace(answer)).

Comment thread cmd/prompt/prompt_test.go

select {
case err := <-done:
assert.ErrorIs(t, err, io.EOF)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Behavior note this test locks in: Ctrl+C now surfaces as io.EOF (that's x/term's mapping), where survey returned InterruptErr ("interrupt"). No compose caller special-cased InterruptErr (they all return err), so nothing breaks logically — but the user-facing failure message degrades to "EOF", and ^C becomes indistinguishable from ^D by construction. Non-blocking suggestion: intercept 0x03 in the wrapping Reader and return a dedicated error ("prompt interrupted by user"), which also keeps the door open for a proper exit 130 later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants