Skip to content

Comments

Stop running AppHost before adding packages#14573

Open
mitchdenny wants to merge 7 commits intorelease/13.2from
fix/add-command-stop-running-apphost
Open

Stop running AppHost before adding packages#14573
mitchdenny wants to merge 7 commits intorelease/13.2from
fix/add-command-stop-running-apphost

Conversation

@mitchdenny
Copy link
Member

Summary

When running aspire add while an AppHost is running in detached mode, the project file is locked by the build server, causing dotnet add package to fail. The add command now stops any running AppHost instance before attempting to add the package.

Changes

  • Added a call to project.CheckAndHandleRunningInstanceAsync() in AddCommand before invoking AddPackageAsync()
  • Uses the same running instance detection pattern already used by the RunCommand
  • The CheckAndHandleRunningInstanceAsync method displays user-visible messages about stopping the instance (via RunningInstanceManager)

Addresses part of #14238

When running 'aspire add' while an AppHost is running in detached mode,
the project file is locked by the build server, causing 'dotnet add
package' to fail. The add command now stops any running AppHost instance
before attempting to add the package, using the same running instance
detection pattern used by the run command.

Fixes part of #14238

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 19, 2026 07:24
@github-actions
Copy link
Contributor

github-actions bot commented Feb 19, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 14573

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 14573"

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the aspire add workflow to avoid dotnet add package failing when the AppHost project is locked by a detached running AppHost instance, by proactively stopping any detected running instance before modifying the project.

Changes:

  • Calls project.CheckAndHandleRunningInstanceAsync(...) in AddCommand before invoking AddPackageAsync().
  • Adds inline comments explaining why a running AppHost can block package installation.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 19, 2026

🎬 CLI E2E Test Recordings

The following terminal recordings are available for commit bff6ea5:

Test Recording
AddPackageInteractiveWhileAppHostRunningDetached ▶️ View Recording
AddPackageWhileAppHostRunningDetached ▶️ View Recording
AgentCommands_AllHelpOutputs_AreCorrect ▶️ View Recording
AgentInitCommand_MigratesDeprecatedConfig ▶️ View Recording
Banner_DisplayedOnFirstRun ▶️ View Recording
Banner_DisplayedWithExplicitFlag ▶️ View Recording
CreateAndDeployToDockerCompose ▶️ View Recording
CreateAndDeployToDockerComposeInteractive ▶️ View Recording
CreateAndPublishToKubernetes ▶️ View Recording
CreateAndRunAspireStarterProject ▶️ View Recording
CreateAndRunAspireStarterProjectWithBundle ▶️ View Recording
CreateAndRunJsReactProject ▶️ View Recording
CreateAndRunPythonReactProject ▶️ View Recording
CreateEmptyAppHostProject ▶️ View Recording
CreateStartAndStopAspireProject ▶️ View Recording
CreateStartWaitAndStopAspireProject ▶️ View Recording
CreateTypeScriptAppHostWithViteApp ▶️ View Recording
DoctorCommand_DetectsDeprecatedAgentConfig ▶️ View Recording
DoctorCommand_WithSslCertDir_ShowsTrusted ▶️ View Recording
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted ▶️ View Recording
LogsCommandShowsResourceLogs ▶️ View Recording
PsCommandListsRunningAppHost ▶️ View Recording
ResourcesCommandShowsRunningResources ▶️ View Recording
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels ▶️ View Recording

📹 Recordings uploaded automatically from CI run #22209757033

@mitchdenny mitchdenny linked an issue Feb 19, 2026 that may be closed by this pull request
Mitch Denny and others added 2 commits February 19, 2026 19:28
Validates that 'aspire add' succeeds when an AppHost is running in
detached mode. The add command should automatically stop the running
AppHost to release file locks before modifying the project.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The aspire add --non-interactive flag doesn't suppress the version
selection prompt. Updated the test to wait for and accept the default
version before continuing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Gate CheckAndHandleRunningInstanceAsync behind
  KnownFeatures.RunningInstanceDetectionEnabled feature flag,
  matching RunCommand behavior
- Check RunningInstanceResult.StopFailed return value and fail
  early with a clear error message instead of proceeding
- Add E2E test for interactive aspire add flow (no integration
  argument) while AppHost is running in detached mode

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
// which prevents 'dotnet add package' from modifying the project.
if (_features.IsFeatureEnabled(KnownFeatures.RunningInstanceDetectionEnabled, defaultValue: true))
{
var runningInstanceResult = await project.CheckAndHandleRunningInstanceAsync(
Copy link
Member

Choose a reason for hiding this comment

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

Isn't FindAndStopRunningInstanceAsync a better name? Check and handle are pretty generic descriptors.

.Find($"Enter the project name ({workspace.WorkspaceRoot.Name}): ");

var waitingForOutputPathPrompt = new CellPatternSearcher()
.Find("Enter the output path:");
Copy link
Member

Choose a reason for hiding this comment

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

The hardcoded text in these E2E tests worries me. When we change text (which will be often) tests will fail, and the E2E tests don't give friendly error messages.

They don't say something actionable like "Enter the output path: was not found", but have a message like "Timeout after 30 seconds".

Comment on lines +221 to +225
if (runningInstanceResult == RunningInstanceResult.StopFailed)
{
InteractionService.DisplayError(AddCommandStrings.UnableToStopRunningInstances);
return ExitCodeConstants.FailedToAddPackage;
}
Copy link
Member

Choose a reason for hiding this comment

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

How come this is only written when there is a failure to stop but not success to stop? Shouldn't the previous method either log about both or about none?

Mitch Denny and others added 3 commits February 20, 2026 12:27
The aspire add command now auto-stops the running AppHost, so the
subsequent aspire stop cleanup command returns exit code 7 (no running
instances found). Use a generic prompt pattern that accepts both OK
and ERR exit codes for the cleanup step.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The RightText() method checks for immediately-adjacent text, but
the ERR prompt has intermediate text between the counter and '] $'.
Instead, wait for the known aspire stop output messages which
correctly handles both 'no running instances' and 'stopped
successfully' outcomes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ceAsync

Address PR feedback from JamesNK: the method name is more descriptive
about what the method actually does — finds running instances and stops
them.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
// which prevents 'dotnet add package' from modifying the project.
if (_features.IsFeatureEnabled(KnownFeatures.RunningInstanceDetectionEnabled, defaultValue: true))
{
var runningInstanceResult = await project.FindAndStopRunningInstanceAsync(
Copy link
Member

Choose a reason for hiding this comment

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

Should this prompt to the user with something like: "A running AppHost was detected. Would you like to stop it to be able to add the integration?" Or something along those lines? I understand this is behind a feature flag, but I just feel like it might be worth it to prevent folks from shooting themselves in the foot (especially given things like logs and telemetry are likely lost after stopping.)

Copy link
Member

@joperezr joperezr Feb 20, 2026

Choose a reason for hiding this comment

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

I realize this is the same thing that happens if a user calls aspire run again on a detached project, so perhaps that's something we can consider as a follow up for potential UX issues. Also, with a subsequent aspire run I guess the current behavior might even be expected to some degree, while perhaps aspire add is not as intuitive since folks would like not assume we are keeping a handle on the project.

ExecutionContext.HomeDirectory,
cancellationToken);

if (runningInstanceResult == RunningInstanceResult.StopFailed)
Copy link
Member

Choose a reason for hiding this comment

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

I noticed that in the RunCommand we actually still go ahead with the command even if stopping fails, unlike here. Assuming that is intentional as we know this will break otherwise.

Copy link
Member

@joperezr joperezr left a comment

Choose a reason for hiding this comment

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

Some minor feedback from me, but nothing really blocking.

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.

CLI commands suggestions

3 participants