CLI: Unify interactive input and output in Reporter - #41215
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR centralizes interactive input (prompting and optional echo masking) under the WSLC CLI Reporter, replacing ad hoc console handling in commands (notably wslc registry login). It introduces a new InputChannel abstraction and updates tests to validate prompt behavior and the stdout prompt-stream change.
Changes:
- Added
InputChanneland extendedReporterto supportIsInputInteractive(),ReadLine(), andPromptForLine()(with optional masking). - Updated
RegistryLoginCommandto useReporterfor username/password prompting and stdin password reads. - Added/updated unit and E2E tests, including a new
InputPipetest helper, and moved interactive prompt assertions from stderr to stdout.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/windows/wslc/WSLCCLITestHelpers.h | Adds InputPipe RAII helper to feed UTF-8 input into tests via a pipe and background writer thread. |
| test/windows/wslc/WSLCCLIReporterUnitTests.cpp | Adds InputChannel and Reporter prompt/read unit tests and a helper InputCaptureReporter. |
| test/windows/wslc/e2e/WSLCE2ERegistryTests.cpp | Updates interactive login prompt expectations from stderr to stdout. |
| src/windows/wslc/core/Reporter.h | Extends Reporter API to include input-related methods and stores an InputChannel. |
| src/windows/wslc/core/Reporter.cpp | Initializes InputChannel and implements Reporter::PromptForLine() with label + flush + read behavior. |
| src/windows/wslc/core/OutputChannel.h | Adds Flush() to ensure prompts are visible before blocking reads when output is redirected. |
| src/windows/wslc/core/OutputChannel.cpp | Implements OutputChannel::Flush() with best-effort logging on failure. |
| src/windows/wslc/core/InputChannel.h | New abstraction for line-oriented input with optional console echo masking and interactivity detection. |
| src/windows/wslc/core/InputChannel.cpp | Implements console-mode probing, echo masking via SetConsoleMode, and line reading via fgetwc. |
| src/windows/wslc/commands/RegistryCommand.cpp | Removes inline prompting logic and switches login to Reporter::PromptForLine() / Reporter::ReadLine(). |
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
src/windows/wslc/core/InputChannel.cpp:80
- InputChannel::ReadLine treats fgetwc() returning WEOF as end-of-input, but WEOF can also indicate a read/encoding error. Consider detecting ferror() and failing explicitly so unexpected input/encoding errors don’t get silently treated as EOF (which can lead to confusing empty credentials, etc.).
const wint_t ch = fgetwc(m_file);
if (ch == WEOF)
{
break;
}
src/windows/wslc/core/Reporter.cpp:72
- Reporter::PromptForLine computes willMask but calls InputChannel::ReadLine with the original mask flag. If the console-mode probe differs between the IsInteractive() call and the later ReadLine() call, the code can emit (or omit) the trailing newline inconsistently with whether echo was actually masked. Passing willMask into ReadLine keeps the newline behavior consistent with the masking decision.
const bool willMask = mask && m_in.IsInteractive();
auto line = m_in.ReadLine(mask);
dkbennett
marked this pull request as ready for review
July 31, 2026 05:37
ggarzia-MSFT
reviewed
Aug 3, 2026
ggarzia-MSFT
approved these changes
Aug 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary of the Pull Request
Unifies interactive user input with user-facing output under the WSLC CLI's
Reporter. PreviouslyReporteronly handled output, and interactive input (prompting, echo masking) was handled ad hoc inside commands likewslc registry login, where console handling does not belong. This moves that logic into a single, testable owner so commands can prompt consistently instead of reimplementing console handling, andregistry loginis simplified to just ask theReporterfor input. Prompts for input were changed from stderr to stdout intentionally (see detailed description for reasoning).Note that
Reporteris planned to be renamed in a follow-up PR to reflect that it now provides unified input/output management for the CLI; the current name is kept here to keep the diff focused and does not yet fully describe the expanded responsibility.Sample output from manual testing with stderr redirected to show prompts still function as expected consistent with other CLIs:

(note these commands failed expectedly but the purpose was to verify the input behavior on a real console; the tests verify the command)
PR Checklist
Detailed Description of the Pull Request / Additional comments
InputChannel: reads a line at a time from the console or a redirected file/pipe. On an interactive console it can mask echo (for password entry) and report whether input is interactive; it distinguishes an empty line from end of input.Reporternow owns an input channel alongside its output channels and exposes:IsInputInteractive()to check whether a prompt can be shown.ReadLine(mask)to read a single line, optionally masking echo.PromptForLine(label, mask)to write a label and read the response in one call.wslc registry loginnow usesPromptForLinefor the username and (masked) password prompts, replacing the previous inline prompting.Prompt default output stream
Interactive login prompts now write to stdout. Previously they were emitted at Info level, which routes to stderr; this PR moves them to stdout (
Level::Output). This is an intentional behavior change, not a regression.For most CLIs stderr is arguably the more correct target for prompts, since it keeps stdout clean for piped or captured output. Two practical reasons favor stdout here:
cli.Out()), containerd/nerdctl (cmd.OutOrStdout()), and Apple container all prompt there, so WSLC matches the tools its users expect.command 2> file) is common; with prompts on stderr that redirect would send the prompt to the file and leave the user at an apparently blank line. Keeping prompts on stdout avoids that.The interactive-login E2E assertions were updated from stderr to stdout to match.
Validation Steps Performed