Fail cleanly when AppHost selection would require a prompt in non-interactive mode#18079
Conversation
…eractive mode When no AppHost is found in the current directory but other AppHosts are running on the system, commands like 'aspire describe --non-interactive' fell through to an interactive selection prompt, which threw and surfaced as 'An unexpected error occurred' with a generic exit code. AppHostConnectionResolver now checks ICliHostEnvironment.SupportsInteractiveInput before prompting: - Only out-of-scope AppHosts running: returns the command's standard not-found error with CliExitCodes.FailedToFindProject. - Multiple in-scope AppHosts: returns a new actionable error telling the user to pass --apphost, also with FailedToFindProject. Fixes microsoft#17619 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 18079Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 18079" |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR adds non-interactive mode handling to the AppHostConnectionResolver, ensuring that when the CLI runs in non-interactive mode (e.g., in CI/CD pipelines or scripts), it returns clear, actionable error messages instead of attempting interactive prompts that would fail.
Changes:
- Added
ICliHostEnvironmentdependency toAppHostConnectionResolverandCommonCommandServicesto detect non-interactive mode - Added early-return error paths in
ResolveConnectionAsyncwhen multiple AppHosts require user selection but interactive input is unavailable - Added new localized resource string
MultipleAppHostsNonInteractivewith translations across all supported languages
Reviewed changes
Copilot reviewed 29 out of 30 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/Aspire.Cli/Backchannel/AppHostConnectionResolver.cs | Core logic: adds non-interactive guards before interactive prompts |
| src/Aspire.Cli/Commands/CommonCommandServices.cs | Adds ICliHostEnvironment as a service property |
| src/Aspire.Cli/Commands/*.cs (11 files) | Pass services.HostEnvironment to AppHostConnectionResolver |
| src/Aspire.Cli/Resources/SharedCommandStrings.resx | New resource string for the non-interactive error |
| src/Aspire.Cli/Resources/xlf/*.xlf (12 files) | Localization entries for the new string |
| tests/Aspire.Cli.Tests/Backchannel/AppHostConnectionResolverTests.cs | New tests for non-interactive scenarios; updates existing tests with new parameter |
| tests/Aspire.Cli.Tests/NuGet/NuGetPackagePrefetcherTests.cs | Updates CommonCommandServices constructor calls with extra null! |
Files not reviewed (1)
- src/Aspire.Cli/Resources/SharedCommandStrings.Designer.cs: Language not supported
| // get a clean error and exit code instead of an unexpected prompt failure. | ||
| return new AppHostConnectionResult | ||
| { | ||
| ErrorMessage = notFoundMessage, |
There was a problem hiding this comment.
According to the test this displays AppHostNotRunning resource string (No running AppHost found. Use 'aspire run' to start one first.)
I think a message like "No running AppHost found in the current scope. Pass --apphost to specify an AppHost running outside the current scope." would be more useful. Maybe even include the scope in the error message.
I think the most likely situation here is there is a running app host that someone wants to get information from, but describe wasn't called in the right directory or with the right options to get data from it.
Description
Fixes #17619
When no AppHost is found in the current directory but other AppHosts are running on the system,
aspire describe --non-interactive(and the other commands that resolve a running AppHost: logs, stop, wait, export, telemetry, mcp) fell through to the interactive "Select from all running AppHosts" prompt. The prompt guard then threw, surfacing as:with the generic unexpected-error exit code, which is not diagnosable from CI scripts.
AppHostConnectionResolvernow checksICliHostEnvironment.SupportsInteractiveInputbefore either selection prompt:The AppHost is not running.) withCliExitCodes.FailedToFindProject.FailedToFindProject.Interactive behavior is unchanged. To give the resolver access to the host environment,
ICliHostEnvironmentwas added toCommonCommandServices(DI-provided) and passed through at each construction site.Testing
ResolveConnectionAsync_NonInteractiveWithOnlyOutOfScopeAppHosts_ReturnsNotFoundErrorandResolveConnectionAsync_NonInteractiveWithMultipleInScopeAppHosts_ReturnsActionableErrordotnet test --project tests/Aspire.Cli.Tests -- --filter-class "*AppHostConnectionResolverTests" --filter-class "*DescribeCommandTests" --filter-class "*StopCommandTests" --filter-class "*WaitCommandTests" --filter-class "*ExportCommandTests": 79/79 passing locally🤖 Generated with Claude Code