diff --git a/src/Aspire.Cli/Commands/AgentInitCommand.cs b/src/Aspire.Cli/Commands/AgentInitCommand.cs index 8e3a8307669..cdd140c8f70 100644 --- a/src/Aspire.Cli/Commands/AgentInitCommand.cs +++ b/src/Aspire.Cli/Commands/AgentInitCommand.cs @@ -62,7 +62,47 @@ internal Task ExecuteCommandAsync(ParseResult parseResult, CancellationToke return ExecuteAsync(parseResult, cancellationToken); } + /// + /// Prompts the user to run agent init after a successful command, then chains into agent init if accepted. + /// Used by commands (e.g. aspire init, aspire new) to offer agent init as a follow-up step. + /// + internal async Task PromptAndChainAsync( + ICliHostEnvironment hostEnvironment, + IInteractionService interactionService, + int previousResultExitCode, + DirectoryInfo workspaceRoot, + CancellationToken cancellationToken) + { + if (previousResultExitCode != ExitCodeConstants.Success) + { + return previousResultExitCode; + } + + if (!hostEnvironment.SupportsInteractiveInput) + { + return ExitCodeConstants.Success; + } + + var runAgentInit = await interactionService.ConfirmAsync( + SharedCommandStrings.PromptRunAgentInit, + defaultValue: true, + cancellationToken: cancellationToken); + + if (runAgentInit) + { + return await ExecuteAgentInitAsync(workspaceRoot, cancellationToken); + } + + return ExitCodeConstants.Success; + } + protected override async Task ExecuteAsync(ParseResult parseResult, CancellationToken cancellationToken) + { + var workspaceRoot = await PromptForWorkspaceRootAsync(cancellationToken); + return await ExecuteAgentInitAsync(workspaceRoot, cancellationToken); + } + + private async Task PromptForWorkspaceRootAsync(CancellationToken cancellationToken) { // Try to discover the git repository root to use as the default workspace root var gitRoot = await _gitRepository.GetRootAsync(cancellationToken); @@ -89,8 +129,11 @@ protected override async Task ExecuteAsync(ParseResult parseResult, Cancell directory: true, cancellationToken: cancellationToken); - var workspaceRoot = new DirectoryInfo(workspaceRootPath); + return new DirectoryInfo(workspaceRootPath); + } + private async Task ExecuteAgentInitAsync(DirectoryInfo workspaceRoot, CancellationToken cancellationToken) + { var context = new AgentEnvironmentScanContext { WorkingDirectory = ExecutionContext.WorkingDirectory, diff --git a/src/Aspire.Cli/Commands/InitCommand.cs b/src/Aspire.Cli/Commands/InitCommand.cs index 0cb27fe5fe9..ef796959a6d 100644 --- a/src/Aspire.Cli/Commands/InitCommand.cs +++ b/src/Aspire.Cli/Commands/InitCommand.cs @@ -39,6 +39,8 @@ internal sealed class InitCommand : BaseCommand, IPackageMetaPrefetchingCommand private readonly ILanguageService _languageService; private readonly ILanguageDiscovery _languageDiscovery; private readonly IScaffoldingService _scaffoldingService; + private readonly AgentInitCommand _agentInitCommand; + private readonly ICliHostEnvironment _hostEnvironment; private static readonly Option s_sourceOption = new("--source", "-s") { @@ -80,7 +82,9 @@ public InitCommand( IConfigurationService configurationService, ILanguageService languageService, ILanguageDiscovery languageDiscovery, - IScaffoldingService scaffoldingService) + IScaffoldingService scaffoldingService, + AgentInitCommand agentInitCommand, + ICliHostEnvironment hostEnvironment) : base("init", InitCommandStrings.Description, features, updateNotifier, executionContext, interactionService, telemetry) { _runner = runner; @@ -96,6 +100,8 @@ public InitCommand( _languageService = languageService; _languageDiscovery = languageDiscovery; _scaffoldingService = scaffoldingService; + _agentInitCommand = agentInitCommand; + _hostEnvironment = hostEnvironment; Options.Add(s_sourceOption); Options.Add(s_versionOption); @@ -140,7 +146,8 @@ protected override async Task ExecuteAsync(ParseResult parseResult, Cancell InteractionService.DisplayEmptyLine(); InteractionService.DisplayMessage(KnownEmojis.Information, $"Creating {languageInfo.DisplayName} AppHost..."); InteractionService.DisplayEmptyLine(); - return await CreatePolyglotAppHostAsync(languageInfo, cancellationToken); + var polyglotResult = await CreatePolyglotAppHostAsync(languageInfo, cancellationToken); + return await _agentInitCommand.PromptAndChainAsync(_hostEnvironment, InteractionService, polyglotResult, _executionContext.WorkingDirectory, cancellationToken); } // For C#, we need the .NET SDK @@ -155,20 +162,26 @@ protected override async Task ExecuteAsync(ParseResult parseResult, Cancell // Use SolutionLocator to find solution files, walking up the directory tree initContext.SelectedSolutionFile = await _solutionLocator.FindSolutionFileAsync(_executionContext.WorkingDirectory, cancellationToken); + int initResult; + DirectoryInfo workspaceRoot; if (initContext.SelectedSolutionFile is not null) { InteractionService.DisplayEmptyLine(); InteractionService.DisplayMessage(KnownEmojis.Information, string.Format(CultureInfo.CurrentCulture, InitCommandStrings.SolutionDetected, initContext.SelectedSolutionFile.Name)); InteractionService.DisplayEmptyLine(); - return await InitializeExistingSolutionAsync(initContext, parseResult, cancellationToken); + initResult = await InitializeExistingSolutionAsync(initContext, parseResult, cancellationToken); + workspaceRoot = initContext.SolutionDirectory ?? _executionContext.WorkingDirectory; } else { InteractionService.DisplayEmptyLine(); InteractionService.DisplayMessage(KnownEmojis.Information, InitCommandStrings.NoSolutionFoundCreatingSingleFileAppHost); InteractionService.DisplayEmptyLine(); - return await CreateEmptyAppHostAsync(parseResult, cancellationToken); + initResult = await CreateEmptyAppHostAsync(parseResult, cancellationToken); + workspaceRoot = _executionContext.WorkingDirectory; } + + return await _agentInitCommand.PromptAndChainAsync(_hostEnvironment, InteractionService, initResult, workspaceRoot, cancellationToken); } private async Task InitializeExistingSolutionAsync(InitContext initContext, ParseResult parseResult, CancellationToken cancellationToken) diff --git a/src/Aspire.Cli/Commands/NewCommand.cs b/src/Aspire.Cli/Commands/NewCommand.cs index 71788647e96..105c9d27335 100644 --- a/src/Aspire.Cli/Commands/NewCommand.cs +++ b/src/Aspire.Cli/Commands/NewCommand.cs @@ -28,6 +28,8 @@ internal sealed class NewCommand : BaseCommand, IPackageMetaPrefetchingCommand private readonly IFeatures _features; private readonly IPackagingService _packagingService; private readonly IConfigurationService _configurationService; + private readonly AgentInitCommand _agentInitCommand; + private readonly ICliHostEnvironment _hostEnvironment; private static readonly Option s_nameOption = new("--name", "-n") { @@ -72,7 +74,9 @@ public NewCommand( ICliUpdateNotifier updateNotifier, CliExecutionContext executionContext, IPackagingService packagingService, - IConfigurationService configurationService) + IConfigurationService configurationService, + AgentInitCommand agentInitCommand, + ICliHostEnvironment hostEnvironment) : base("new", NewCommandStrings.Description, features, updateNotifier, executionContext, interactionService, telemetry) { _prompter = prompter; @@ -80,6 +84,8 @@ public NewCommand( _features = features; _packagingService = packagingService; _configurationService = configurationService; + _agentInitCommand = agentInitCommand; + _hostEnvironment = hostEnvironment; Options.Add(s_nameOption); Options.Add(s_outputOption); @@ -366,7 +372,8 @@ protected override async Task ExecuteAsync(ParseResult parseResult, Cancell extensionInteractionService.OpenEditor(templateResult.OutputPath); } - return templateResult.ExitCode; + var workspaceRoot = new DirectoryInfo(templateResult.OutputPath ?? ExecutionContext.WorkingDirectory.FullName); + return await _agentInitCommand.PromptAndChainAsync(_hostEnvironment, InteractionService, templateResult.ExitCode, workspaceRoot, cancellationToken); } private static bool ShouldResolveCliTemplateVersion(ITemplate template) diff --git a/src/Aspire.Cli/Resources/SharedCommandStrings.Designer.cs b/src/Aspire.Cli/Resources/SharedCommandStrings.Designer.cs index 6194fd04993..ab35e84944e 100644 --- a/src/Aspire.Cli/Resources/SharedCommandStrings.Designer.cs +++ b/src/Aspire.Cli/Resources/SharedCommandStrings.Designer.cs @@ -98,5 +98,11 @@ internal static string MultipleInScopeAppHosts { return ResourceManager.GetString("MultipleInScopeAppHosts", resourceCulture); } } + + internal static string PromptRunAgentInit { + get { + return ResourceManager.GetString("PromptRunAgentInit", resourceCulture); + } + } } } diff --git a/src/Aspire.Cli/Resources/SharedCommandStrings.resx b/src/Aspire.Cli/Resources/SharedCommandStrings.resx index b7f1153d03a..f8989e30e0e 100644 --- a/src/Aspire.Cli/Resources/SharedCommandStrings.resx +++ b/src/Aspire.Cli/Resources/SharedCommandStrings.resx @@ -144,4 +144,7 @@ Multiple running AppHosts found in the current directory. Select from running AppHosts. + + Would you like to configure AI agent environments for this project? + diff --git a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.cs.xlf b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.cs.xlf index 3c9a79b9eb2..107cc5a01b7 100644 --- a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.cs.xlf +++ b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.cs.xlf @@ -47,6 +47,11 @@ Using AppHost: {0} + + Would you like to configure AI agent environments for this project? + Would you like to configure AI agent environments for this project? + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.de.xlf b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.de.xlf index c8786dcc27e..bb25f939810 100644 --- a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.de.xlf +++ b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.de.xlf @@ -47,6 +47,11 @@ Using AppHost: {0} + + Would you like to configure AI agent environments for this project? + Would you like to configure AI agent environments for this project? + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.es.xlf b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.es.xlf index 8d3799b0a65..b4715deaceb 100644 --- a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.es.xlf +++ b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.es.xlf @@ -47,6 +47,11 @@ Using AppHost: {0} + + Would you like to configure AI agent environments for this project? + Would you like to configure AI agent environments for this project? + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.fr.xlf b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.fr.xlf index e9d326fd951..a511c9fb5e3 100644 --- a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.fr.xlf +++ b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.fr.xlf @@ -47,6 +47,11 @@ Using AppHost: {0} + + Would you like to configure AI agent environments for this project? + Would you like to configure AI agent environments for this project? + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.it.xlf b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.it.xlf index bb4ff0a6c9d..c83b0cee322 100644 --- a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.it.xlf +++ b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.it.xlf @@ -47,6 +47,11 @@ Using AppHost: {0} + + Would you like to configure AI agent environments for this project? + Would you like to configure AI agent environments for this project? + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.ja.xlf b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.ja.xlf index 7de68457d21..69e2c44925e 100644 --- a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.ja.xlf +++ b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.ja.xlf @@ -47,6 +47,11 @@ Using AppHost: {0} + + Would you like to configure AI agent environments for this project? + Would you like to configure AI agent environments for this project? + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.ko.xlf b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.ko.xlf index 63971b68257..7fe446a7109 100644 --- a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.ko.xlf +++ b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.ko.xlf @@ -47,6 +47,11 @@ Using AppHost: {0} + + Would you like to configure AI agent environments for this project? + Would you like to configure AI agent environments for this project? + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.pl.xlf b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.pl.xlf index 096aff73c39..9102014fb69 100644 --- a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.pl.xlf +++ b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.pl.xlf @@ -47,6 +47,11 @@ Using AppHost: {0} + + Would you like to configure AI agent environments for this project? + Would you like to configure AI agent environments for this project? + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.pt-BR.xlf b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.pt-BR.xlf index a9fb787a8f1..bf713402e3c 100644 --- a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.pt-BR.xlf +++ b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.pt-BR.xlf @@ -47,6 +47,11 @@ Using AppHost: {0} + + Would you like to configure AI agent environments for this project? + Would you like to configure AI agent environments for this project? + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.ru.xlf b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.ru.xlf index e9547303b0e..aa72a68efea 100644 --- a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.ru.xlf +++ b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.ru.xlf @@ -47,6 +47,11 @@ Using AppHost: {0} + + Would you like to configure AI agent environments for this project? + Would you like to configure AI agent environments for this project? + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.tr.xlf b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.tr.xlf index 5be4ba2cbbd..151c4bacfc1 100644 --- a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.tr.xlf +++ b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.tr.xlf @@ -47,6 +47,11 @@ Using AppHost: {0} + + Would you like to configure AI agent environments for this project? + Would you like to configure AI agent environments for this project? + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.zh-Hans.xlf b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.zh-Hans.xlf index 1a77f3fde09..c259a8971d2 100644 --- a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.zh-Hans.xlf +++ b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.zh-Hans.xlf @@ -47,6 +47,11 @@ Using AppHost: {0} + + Would you like to configure AI agent environments for this project? + Would you like to configure AI agent environments for this project? + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.zh-Hant.xlf b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.zh-Hant.xlf index f3ab18f0b52..fba81bb49d9 100644 --- a/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.zh-Hant.xlf +++ b/src/Aspire.Cli/Resources/xlf/SharedCommandStrings.zh-Hant.xlf @@ -47,6 +47,11 @@ Using AppHost: {0} + + Would you like to configure AI agent environments for this project? + Would you like to configure AI agent environments for this project? + + \ No newline at end of file diff --git a/tests/Aspire.Cli.EndToEnd.Tests/BundleSmokeTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/BundleSmokeTests.cs index b628c6defd0..c6e3fb5bffe 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/BundleSmokeTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/BundleSmokeTests.cs @@ -81,6 +81,7 @@ public async Task CreateAndRunAspireStarterProjectWithBundle() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter) // Start AppHost in detached mode and capture JSON output .Type("aspire run --detach --format json | tee /tmp/aspire-detach.json") diff --git a/tests/Aspire.Cli.EndToEnd.Tests/DescribeCommandTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/DescribeCommandTests.cs index 0c9111e6504..9621c9fd50a 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/DescribeCommandTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/DescribeCommandTests.cs @@ -95,6 +95,7 @@ public async Task DescribeCommandShowsRunningResources() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Navigate to the AppHost directory @@ -223,6 +224,7 @@ public async Task DescribeCommandResolvesReplicaNames() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Navigate to the AppHost directory diff --git a/tests/Aspire.Cli.EndToEnd.Tests/DockerDeploymentTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/DockerDeploymentTests.cs index ea6cf828cab..78b8481acc7 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/DockerDeploymentTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/DockerDeploymentTests.cs @@ -84,6 +84,7 @@ public async Task CreateAndDeployToDockerCompose() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) // For test project prompt, default is "No" so just press Enter to accept it .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Step 2: Navigate into the project directory @@ -253,6 +254,7 @@ public async Task CreateAndDeployToDockerComposeInteractive() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) // For test project prompt, default is "No" so just press Enter to accept it .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Step 2: Navigate into the project directory diff --git a/tests/Aspire.Cli.EndToEnd.Tests/EmptyAppHostTemplateTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/EmptyAppHostTemplateTests.cs index 40ff69ac5fe..e7cc602dd2d 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/EmptyAppHostTemplateTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/EmptyAppHostTemplateTests.cs @@ -79,6 +79,7 @@ public async Task CreateEmptyAppHostProject() .WaitUntil(s => waitingForUrlsPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() // select "No" for localhost URLs (default) // Empty AppHost template doesn't have Redis or test project prompts + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter) // Note: We don't run 'aspire run' for Empty AppHost since there's nothing to run .Type("exit") diff --git a/tests/Aspire.Cli.EndToEnd.Tests/JsReactTemplateTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/JsReactTemplateTests.cs index f0c5eef3a52..ab8c5741a87 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/JsReactTemplateTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/JsReactTemplateTests.cs @@ -91,6 +91,7 @@ public async Task CreateAndRunJsReactProject() // For Redis prompt, default is "Yes" so we need to select "No" by pressing Down .Key(Hex1b.Input.Hex1bKey.DownArrow) .Enter() // select "No" for Redis Cache + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter) .Type("aspire run") .Enter() diff --git a/tests/Aspire.Cli.EndToEnd.Tests/KubernetesPublishTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/KubernetesPublishTests.cs index e39899f2b5d..8e8bf5e525a 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/KubernetesPublishTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/KubernetesPublishTests.cs @@ -160,6 +160,7 @@ public async Task CreateAndPublishToKubernetes() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) // For test project prompt, default is "No" so just press Enter to accept it .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Step 2: Navigate into the project directory diff --git a/tests/Aspire.Cli.EndToEnd.Tests/LogsCommandTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/LogsCommandTests.cs index 680fe95fd2b..72bff108ae7 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/LogsCommandTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/LogsCommandTests.cs @@ -92,6 +92,7 @@ public async Task LogsCommandShowsResourceLogs() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Navigate to the AppHost directory diff --git a/tests/Aspire.Cli.EndToEnd.Tests/MultipleAppHostTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/MultipleAppHostTests.cs index 89b7f87a936..e1b06da3e98 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/MultipleAppHostTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/MultipleAppHostTests.cs @@ -73,6 +73,7 @@ public async Task DetachFormatJsonProducesValidJson() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); sequenceBuilder.ClearScreen(counter); diff --git a/tests/Aspire.Cli.EndToEnd.Tests/PsCommandTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/PsCommandTests.cs index 575826dc0cb..ea428cb0ffa 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/PsCommandTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/PsCommandTests.cs @@ -95,6 +95,7 @@ public async Task PsCommandListsRunningAppHost() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Navigate to the AppHost directory diff --git a/tests/Aspire.Cli.EndToEnd.Tests/PythonReactTemplateTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/PythonReactTemplateTests.cs index 683afa46241..1498d896d88 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/PythonReactTemplateTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/PythonReactTemplateTests.cs @@ -86,6 +86,7 @@ public async Task CreateAndRunPythonReactProject() // For Redis prompt, default is "Yes" so we need to select "No" by pressing Down .Key(Hex1b.Input.Hex1bKey.DownArrow) .Enter() // select "No" for Redis Cache + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter) .Type("aspire run") .Enter() diff --git a/tests/Aspire.Cli.EndToEnd.Tests/SecretDotNetAppHostTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/SecretDotNetAppHostTests.cs index 59f80a150b0..301e33938e0 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/SecretDotNetAppHostTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/SecretDotNetAppHostTests.cs @@ -70,6 +70,7 @@ public async Task SecretCrudOnDotNetAppHost() .Enter() .WaitUntil(s => waitingForUrlsPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // cd into the project diff --git a/tests/Aspire.Cli.EndToEnd.Tests/SecretTypeScriptAppHostTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/SecretTypeScriptAppHostTests.cs index 91f8e70fabe..7172123b457 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/SecretTypeScriptAppHostTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/SecretTypeScriptAppHostTests.cs @@ -58,6 +58,7 @@ public async Task SecretCrudOnTypeScriptAppHost() .WaitUntil(s => waitingForTypeScriptSelected.Search(s).Count > 0, TimeSpan.FromSeconds(5)) .Enter() .WaitUntil(s => waitingForAppHostCreated.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Set secrets using --apphost diff --git a/tests/Aspire.Cli.EndToEnd.Tests/SmokeTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/SmokeTests.cs index 7903092841d..969a2f0f792 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/SmokeTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/SmokeTests.cs @@ -94,6 +94,7 @@ public async Task CreateAndRunAspireStarterProject() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter) .Type("aspire run") .Enter() diff --git a/tests/Aspire.Cli.EndToEnd.Tests/StartStopTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/StartStopTests.cs index b9326bae40f..a31022c7353 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/StartStopTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/StartStopTests.cs @@ -83,6 +83,7 @@ public async Task CreateStartAndStopAspireProject() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Navigate to the AppHost directory @@ -224,6 +225,7 @@ public async Task AddPackageWhileAppHostRunningDetached() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Navigate to the AppHost directory @@ -341,6 +343,7 @@ public async Task AddPackageInteractiveWhileAppHostRunningDetached() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Navigate to the AppHost directory diff --git a/tests/Aspire.Cli.EndToEnd.Tests/StopNonInteractiveTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/StopNonInteractiveTests.cs index e4a5a2c9023..1ebf6f59588 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/StopNonInteractiveTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/StopNonInteractiveTests.cs @@ -86,6 +86,7 @@ public async Task StopNonInteractiveSingleAppHost() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Navigate to the AppHost directory @@ -200,6 +201,7 @@ public async Task StopAllAppHostsFromAppHostDirectory() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Clear screen before second project creation @@ -221,6 +223,7 @@ public async Task StopAllAppHostsFromAppHostDirectory() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Start first AppHost in background @@ -339,6 +342,7 @@ public async Task StopAllAppHostsFromUnrelatedDirectory() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Clear screen before second project creation @@ -360,6 +364,7 @@ public async Task StopAllAppHostsFromUnrelatedDirectory() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Start first AppHost in background @@ -488,6 +493,7 @@ public async Task StopNonInteractiveMultipleAppHostsShowsError() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Clear screen before second project creation @@ -509,6 +515,7 @@ public async Task StopNonInteractiveMultipleAppHostsShowsError() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Start first AppHost in background diff --git a/tests/Aspire.Cli.EndToEnd.Tests/TypeScriptPolyglotTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/TypeScriptPolyglotTests.cs index 46a6576354e..24e534b004d 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/TypeScriptPolyglotTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/TypeScriptPolyglotTests.cs @@ -73,6 +73,7 @@ public async Task CreateTypeScriptAppHostWithViteApp() .WaitUntil(s => waitingForTypeScriptSelected.Search(s).Count > 0, TimeSpan.FromSeconds(5)) .Enter() // select TypeScript .WaitUntil(s => waitingForAppHostCreated.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Step 2: Create a Vite app using npm create vite diff --git a/tests/Aspire.Cli.EndToEnd.Tests/TypeScriptStarterTemplateTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/TypeScriptStarterTemplateTests.cs index 618030e219f..c4a476af6cc 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/TypeScriptStarterTemplateTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/TypeScriptStarterTemplateTests.cs @@ -78,6 +78,7 @@ public async Task CreateAndRunTypeScriptStarterProject() .Enter() // accept default output path .WaitUntil(s => waitingForUrlsPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() // select "No" for localhost URLs (default) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Step 2: Navigate into the project and start it in background with JSON output diff --git a/tests/Aspire.Cli.EndToEnd.Tests/WaitCommandTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/WaitCommandTests.cs index 1c6e3bbd301..2e5b21fcbc5 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/WaitCommandTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/WaitCommandTests.cs @@ -86,6 +86,7 @@ public async Task CreateStartWaitAndStopAspireProject() .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter); // Navigate to the AppHost directory diff --git a/tests/Aspire.Cli.Tests/Commands/AddCommandTests.cs b/tests/Aspire.Cli.Tests/Commands/AddCommandTests.cs index 4b8605c56ed..7784b475921 100644 --- a/tests/Aspire.Cli.Tests/Commands/AddCommandTests.cs +++ b/tests/Aspire.Cli.Tests/Commands/AddCommandTests.cs @@ -264,6 +264,7 @@ public async Task AddCommandPromptsForDisambiguation() using var workspace = TemporaryWorkspace.Create(outputHelper); var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, options => { + options.CliHostEnvironmentFactory = _ => TestHelpers.CreateInteractiveHostEnvironment(); options.AddCommandPrompterFactory = (sp) => { @@ -452,6 +453,8 @@ public async Task AddCommand_NoMatchingPackages_DisplaysNoMatchesMessage() using var workspace = TemporaryWorkspace.Create(outputHelper); var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, options => { + options.CliHostEnvironmentFactory = _ => TestHelpers.CreateInteractiveHostEnvironment(); + options.InteractionServiceFactory = (sp) => { var testInteractionService = new TestInteractionService(); @@ -856,6 +859,8 @@ public async Task AddCommand_WithPartialMatch_FiltersUsingFuzzySearch() using var workspace = TemporaryWorkspace.Create(outputHelper); var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, options => { + options.CliHostEnvironmentFactory = _ => TestHelpers.CreateInteractiveHostEnvironment(); + options.AddCommandPrompterFactory = (sp) => { var interactionService = sp.GetRequiredService(); diff --git a/tests/Aspire.Cli.Tests/Commands/NewCommandTests.cs b/tests/Aspire.Cli.Tests/Commands/NewCommandTests.cs index 59f04e7c528..6e49b87a023 100644 --- a/tests/Aspire.Cli.Tests/Commands/NewCommandTests.cs +++ b/tests/Aspire.Cli.Tests/Commands/NewCommandTests.cs @@ -1014,6 +1014,8 @@ public async Task NewCommandWithEmptyTemplateAndCSharpPromptsForLocalhostTldAndU var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, options => { + options.CliHostEnvironmentFactory = _ => TestHelpers.CreateInteractiveHostEnvironment(); + options.InteractionServiceFactory = _ => new TestInteractionService { PromptForSelectionCallback = (promptText, choices, choiceFormatter, cancellationToken) => @@ -1189,6 +1191,8 @@ public async Task NewCommandWithEmptyTemplateAndTypeScriptPromptsForLocalhostTld var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, options => { + options.CliHostEnvironmentFactory = _ => TestHelpers.CreateInteractiveHostEnvironment(); + options.InteractionServiceFactory = _ => new TestInteractionService { PromptForSelectionCallback = (promptText, choices, choiceFormatter, cancellationToken) => diff --git a/tests/Aspire.Cli.Tests/Commands/RootCommandTests.cs b/tests/Aspire.Cli.Tests/Commands/RootCommandTests.cs index 98da8ad075a..1d421c82bc2 100644 --- a/tests/Aspire.Cli.Tests/Commands/RootCommandTests.cs +++ b/tests/Aspire.Cli.Tests/Commands/RootCommandTests.cs @@ -86,6 +86,7 @@ public async Task FirstTimeUseNotice_BannerDisplayedWhenSentinelDoesNotExist() options.ErrorTextWriter = errorWriter; options.FirstTimeUseNoticeSentinelFactory = _ => sentinel; options.BannerServiceFactory = _ => bannerService; + options.CliHostEnvironmentFactory = _ => TestHelpers.CreateInteractiveHostEnvironment(); }); var provider = services.BuildServiceProvider(); @@ -261,6 +262,7 @@ public async Task Banner_TelemetryNoticeShownOnFirstRun() options.ErrorTextWriter = errorWriter; options.FirstTimeUseNoticeSentinelFactory = _ => sentinel; options.BannerServiceFactory = _ => bannerService; + options.CliHostEnvironmentFactory = _ => TestHelpers.CreateInteractiveHostEnvironment(); }); var provider = services.BuildServiceProvider(); @@ -331,6 +333,7 @@ public async Task InformationalFlag_DoesNotCreateSentinel_OnSubsequentFirstRun() { options.FirstTimeUseNoticeSentinelFactory = _ => sentinel; options.BannerServiceFactory = _ => bannerService; + options.CliHostEnvironmentFactory = _ => TestHelpers.CreateInteractiveHostEnvironment(); }); var provider = services.BuildServiceProvider(); diff --git a/tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs b/tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs index 2546f6bd1ba..fbe3b82c187 100644 --- a/tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs +++ b/tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs @@ -369,7 +369,7 @@ public ISolutionLocator CreateDefaultSolutionLocatorFactory(IServiceProvider ser public Func CliHostEnvironmentFactory { get; set; } = (IServiceProvider serviceProvider) => { var configuration = serviceProvider.GetRequiredService(); - return new CliHostEnvironment(configuration, nonInteractive: false); + return new CliHostEnvironment(configuration, nonInteractive: true); }; public Func InteractionServiceFactory { get; set; } = (IServiceProvider serviceProvider) => diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AcaCompactNamingDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AcaCompactNamingDeploymentTests.cs index 91b0f4d84f8..8eb942dee73 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AcaCompactNamingDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AcaCompactNamingDeploymentTests.cs @@ -96,6 +96,7 @@ private async Task DeployWithCompactNamingFixesStorageCollisionCore(Cancellation .Wait(TimeSpan.FromSeconds(5)) .Enter() .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); // Step 4: Add required packages diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AcaCompactNamingUpgradeDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AcaCompactNamingUpgradeDeploymentTests.cs index 0cfc7290cca..3680b1d2fce 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AcaCompactNamingUpgradeDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AcaCompactNamingUpgradeDeploymentTests.cs @@ -121,6 +121,7 @@ private async Task UpgradeFromGaToDevDoesNotDuplicateStorageAccountsCore(Cancell .Wait(TimeSpan.FromSeconds(5)) .Enter() .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); // Step 6: Add ACA package using GA CLI (uses GA NuGet packages) diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AcaCustomRegistryDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AcaCustomRegistryDeploymentTests.cs index 0e74570250f..12d221f3fc1 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AcaCustomRegistryDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AcaCustomRegistryDeploymentTests.cs @@ -130,6 +130,7 @@ private async Task DeployStarterTemplateWithCustomRegistryCore(CancellationToken .Enter() // Select "No" for Redis Cache .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() // Select "No" for test project (default) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(5)); // Step 4: Navigate to project directory diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AcaDeploymentErrorOutputTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AcaDeploymentErrorOutputTests.cs index 96ac0e7850a..48a3a908dd8 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AcaDeploymentErrorOutputTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AcaDeploymentErrorOutputTests.cs @@ -99,6 +99,7 @@ private async Task DeployWithInvalidLocation_ErrorOutputIsCleanCore(Cancellation .Wait(TimeSpan.FromSeconds(5)) .Enter() .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); // Step 4: Add Azure Container Apps package diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AcaExistingRegistryDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AcaExistingRegistryDeploymentTests.cs index f16553ca300..a34ac26ff70 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AcaExistingRegistryDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AcaExistingRegistryDeploymentTests.cs @@ -154,6 +154,7 @@ private async Task DeployStarterTemplateWithExistingRegistryCore(CancellationTok .Enter() // Select "No" for Redis Cache .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() // Select "No" for test project (default) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(5)); // Step 5: Navigate to project directory diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AcaStarterDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AcaStarterDeploymentTests.cs index 5bf5a2c7af1..360e6d7681e 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AcaStarterDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AcaStarterDeploymentTests.cs @@ -131,6 +131,7 @@ private async Task DeployStarterTemplateToAzureContainerAppsCore(CancellationTok .Enter() // Select "No" for Redis Cache .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() // Select "No" for test project (default) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(5)); // Step 4: Navigate to project directory diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AcrPurgeTaskDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AcrPurgeTaskDeploymentTests.cs index bae335ce5f3..58a1a4cab02 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AcrPurgeTaskDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AcrPurgeTaskDeploymentTests.cs @@ -131,6 +131,7 @@ private async Task DeployPythonStarterWithPurgeTaskCore(CancellationToken cancel // For Redis prompt, default is "Yes" so we need to select "No" by pressing Down .Key(Hex1b.Input.Hex1bKey.DownArrow) .Enter() // Select "No" for Redis Cache + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(5)); // Step 4: Navigate to project directory diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AksStarterDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AksStarterDeploymentTests.cs index 6e25dfaf4c3..69e86dd02bf 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AksStarterDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AksStarterDeploymentTests.cs @@ -212,6 +212,7 @@ private async Task DeployStarterTemplateToAksCore(CancellationToken cancellation .Enter() // Select "No" for Redis Cache .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() // Select "No" for test project (default) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(5)); // Step 12: Navigate to project directory diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AksStarterWithRedisDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AksStarterWithRedisDeploymentTests.cs index 25cdc3aba6e..5165fcbc7dc 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AksStarterWithRedisDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AksStarterWithRedisDeploymentTests.cs @@ -211,6 +211,7 @@ private async Task DeployStarterTemplateWithRedisToAksCore(CancellationToken can .Enter() // Select "Yes" for Redis Cache (first/default option) .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() // Select "No" for test project (default) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(5)); // Step 12: Navigate to project directory diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AppServicePythonDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AppServicePythonDeploymentTests.cs index c15d910933f..cf126aafb6f 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AppServicePythonDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AppServicePythonDeploymentTests.cs @@ -133,6 +133,7 @@ private async Task DeployPythonFastApiTemplateToAzureAppServiceCore(Cancellation // For Redis prompt, default is "Yes" so we need to select "No" by pressing Down .Key(Hex1b.Input.Hex1bKey.DownArrow) .Enter() // Select "No" for Redis Cache + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(5)); // Step 4: Navigate to project directory diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AppServiceReactDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AppServiceReactDeploymentTests.cs index f006cd1475b..60d917aea5b 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AppServiceReactDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AppServiceReactDeploymentTests.cs @@ -139,6 +139,7 @@ private async Task DeployReactTemplateToAzureAppServiceCore(CancellationToken ca .Key(Hex1b.Input.Hex1bKey.DownArrow) .Enter() // Select "No" for Redis Cache // Note: React template does NOT have a test project prompt (unlike Blazor starter) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(5)); // Step 4: Navigate to project directory diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AzureAppConfigDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AzureAppConfigDeploymentTests.cs index f37a09ee591..ba542dbb355 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AzureAppConfigDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AzureAppConfigDeploymentTests.cs @@ -103,6 +103,7 @@ private async Task DeployAzureAppConfigResourceCore(CancellationToken cancellati .Wait(TimeSpan.FromSeconds(5)) .Enter() // Dismiss NuGet.config prompt if present (no-op if already auto-accepted) .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); // Step 4a: Add Aspire.Hosting.Azure.ContainerApps package (for managed identity support) diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AzureContainerRegistryDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AzureContainerRegistryDeploymentTests.cs index 74fab85cadd..ec4805b85aa 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AzureContainerRegistryDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AzureContainerRegistryDeploymentTests.cs @@ -98,6 +98,7 @@ private async Task DeployAzureContainerRegistryResourceCore(CancellationToken ca .Wait(TimeSpan.FromSeconds(5)) .Enter() // Dismiss NuGet.config prompt if present (no-op if already auto-accepted) .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); // Step 4: Add Aspire.Hosting.Azure.ContainerRegistry package diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AzureEventHubsDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AzureEventHubsDeploymentTests.cs index 691cf2b1102..384332ec323 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AzureEventHubsDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AzureEventHubsDeploymentTests.cs @@ -103,6 +103,7 @@ private async Task DeployAzureEventHubsResourceCore(CancellationToken cancellati .Wait(TimeSpan.FromSeconds(5)) .Enter() // Dismiss NuGet.config prompt if present (no-op if already auto-accepted) .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); // Step 4a: Add Aspire.Hosting.Azure.ContainerApps package (for managed identity support) diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AzureKeyVaultDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AzureKeyVaultDeploymentTests.cs index 17878541155..e194eff4a91 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AzureKeyVaultDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AzureKeyVaultDeploymentTests.cs @@ -103,6 +103,7 @@ private async Task DeployAzureKeyVaultResourceCore(CancellationToken cancellatio .Wait(TimeSpan.FromSeconds(5)) .Enter() // Dismiss NuGet.config prompt if present (no-op if already auto-accepted) .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); // Step 4a: Add Aspire.Hosting.Azure.ContainerApps package (for managed identity support) diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AzureLogAnalyticsDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AzureLogAnalyticsDeploymentTests.cs index 60c1d4c4129..0bb01c02aa0 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AzureLogAnalyticsDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AzureLogAnalyticsDeploymentTests.cs @@ -98,6 +98,7 @@ private async Task DeployAzureLogAnalyticsResourceCore(CancellationToken cancell .Wait(TimeSpan.FromSeconds(5)) .Enter() // Dismiss NuGet.config prompt if present (no-op if already auto-accepted) .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); // Step 4: Add Aspire.Hosting.Azure.OperationalInsights package diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AzureServiceBusDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AzureServiceBusDeploymentTests.cs index a901cb64bef..81aa0439027 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AzureServiceBusDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AzureServiceBusDeploymentTests.cs @@ -103,6 +103,7 @@ private async Task DeployAzureServiceBusResourceCore(CancellationToken cancellat .Wait(TimeSpan.FromSeconds(5)) .Enter() // Dismiss NuGet.config prompt if present (no-op if already auto-accepted) .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); // Step 4a: Add Aspire.Hosting.Azure.ContainerApps package (for managed identity support) diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AzureStorageDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AzureStorageDeploymentTests.cs index 66afe215823..0534a78822f 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AzureStorageDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AzureStorageDeploymentTests.cs @@ -103,6 +103,7 @@ private async Task DeployAzureStorageResourceCore(CancellationToken cancellation .Wait(TimeSpan.FromSeconds(5)) .Enter() // Dismiss NuGet.config prompt if present (no-op if already auto-accepted) .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); // Step 4a: Add Aspire.Hosting.Azure.ContainerApps package (for managed identity support) diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/Helpers/DeploymentE2ETestHelpers.cs b/tests/Aspire.Deployment.EndToEnd.Tests/Helpers/DeploymentE2ETestHelpers.cs index 8333e96b5bc..ad0eb8a7f7a 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/Helpers/DeploymentE2ETestHelpers.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/Helpers/DeploymentE2ETestHelpers.cs @@ -174,4 +174,27 @@ internal static Hex1bTerminalInputSequenceBuilder SourceAspireCliEnvironment( .WaitForSuccessPrompt(counter); } + /// + /// Runs aspire init and handles the NuGet.config and agent init prompts. + /// The agent init prompt is declined so the command exits cleanly. + /// + internal static Hex1bTerminalInputSequenceBuilder RunAspireInit( + this Hex1bTerminalInputSequenceBuilder builder, + SequenceCounter counter) + { + var waitingForInitComplete = new CellPatternSearcher() + .Find("Aspire initialization complete"); + + return builder + .Type("aspire init") + .Enter() + // NuGet.config prompt may or may not appear depending on environment. + // Wait a moment then press Enter to dismiss if present. + .Wait(TimeSpan.FromSeconds(5)) + .Enter() + .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() + .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); + } + } diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/PythonFastApiDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/PythonFastApiDeploymentTests.cs index 3a7255a684c..8d9bd5596e4 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/PythonFastApiDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/PythonFastApiDeploymentTests.cs @@ -133,6 +133,7 @@ private async Task DeployPythonFastApiTemplateToAzureContainerAppsCore(Cancellat // For Redis prompt, default is "Yes" so we need to select "No" by pressing Down .Key(Hex1b.Input.Hex1bKey.DownArrow) .Enter() // Select "No" for Redis Cache + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(5)); // Step 4: Navigate to project directory diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/VnetKeyVaultConnectivityDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/VnetKeyVaultConnectivityDeploymentTests.cs index 77e21948e90..db2df703219 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/VnetKeyVaultConnectivityDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/VnetKeyVaultConnectivityDeploymentTests.cs @@ -119,6 +119,7 @@ private async Task DeployStarterTemplateWithKeyVaultPrivateEndpointCore(Cancella .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(5)); // Step 4: Navigate to project directory diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/VnetKeyVaultInfraDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/VnetKeyVaultInfraDeploymentTests.cs index af4cd443987..4d8d8931326 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/VnetKeyVaultInfraDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/VnetKeyVaultInfraDeploymentTests.cs @@ -90,6 +90,7 @@ private async Task DeployVnetKeyVaultInfrastructureCore(CancellationToken cancel .Wait(TimeSpan.FromSeconds(5)) .Enter() .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); // Step 4a: Add Aspire.Hosting.Azure.AppContainers diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/VnetSqlServerConnectivityDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/VnetSqlServerConnectivityDeploymentTests.cs index b1fd51fbddf..7f508f1c296 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/VnetSqlServerConnectivityDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/VnetSqlServerConnectivityDeploymentTests.cs @@ -119,6 +119,7 @@ private async Task DeployStarterTemplateWithSqlServerPrivateEndpointCore(Cancell .Enter() .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(5)); // Step 4: Navigate to project directory diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/VnetSqlServerInfraDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/VnetSqlServerInfraDeploymentTests.cs index aa91bc6d58c..3e65252a628 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/VnetSqlServerInfraDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/VnetSqlServerInfraDeploymentTests.cs @@ -90,6 +90,7 @@ private async Task DeployVnetSqlServerInfrastructureCore(CancellationToken cance .Wait(TimeSpan.FromSeconds(5)) .Enter() .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); // Step 4a: Add Aspire.Hosting.Azure.AppContainers diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/VnetStorageBlobConnectivityDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/VnetStorageBlobConnectivityDeploymentTests.cs index 294de71c57c..065edae967a 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/VnetStorageBlobConnectivityDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/VnetStorageBlobConnectivityDeploymentTests.cs @@ -121,6 +121,7 @@ private async Task DeployStarterTemplateWithStorageBlobPrivateEndpointCore(Cance .Enter() // No for Redis .WaitUntil(s => waitingForTestPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(10)) .Enter() // No for test project + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(5)); // Step 4: Navigate to project directory diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/VnetStorageBlobInfraDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/VnetStorageBlobInfraDeploymentTests.cs index ab085048822..01e1138e91b 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/VnetStorageBlobInfraDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/VnetStorageBlobInfraDeploymentTests.cs @@ -91,6 +91,7 @@ private async Task DeployVnetStorageBlobInfrastructureCore(CancellationToken can .Wait(TimeSpan.FromSeconds(5)) .Enter() .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); // Step 4a: Add Aspire.Hosting.Azure.AppContainers diff --git a/tests/Shared/Hex1bTestHelpers.cs b/tests/Shared/Hex1bTestHelpers.cs index 0479a226c40..ac287ac262b 100644 --- a/tests/Shared/Hex1bTestHelpers.cs +++ b/tests/Shared/Hex1bTestHelpers.cs @@ -236,4 +236,21 @@ internal static Hex1bTerminalInputSequenceBuilder ExecuteCallback( return true; }, TimeSpan.FromSeconds(1)); } + + /// + /// Handles the agent init confirmation prompt that appears after aspire init or aspire new. + /// Declines the prompt so the command exits cleanly. + /// + internal static Hex1bTerminalInputSequenceBuilder DeclineAgentInitPrompt( + this Hex1bTerminalInputSequenceBuilder builder) + { + var agentInitPrompt = new CellPatternSearcher() + .Find("configure AI agent environments"); + + return builder + .WaitUntil(s => agentInitPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(30)) + .Wait(500) + .Type("n") + .Enter(); + } } \ No newline at end of file