Skip to content

Add stop --force persistent resource cleanup#18718

Open
danegsta wants to merge 29 commits into
mainfrom
danegsta-persistent-resource-cleanup-mode
Open

Add stop --force persistent resource cleanup#18718
danegsta wants to merge 29 commits into
mainfrom
danegsta-persistent-resource-cleanup-mode

Conversation

@danegsta

@danegsta danegsta commented Jul 9, 2026

Copy link
Copy Markdown
Member

Description

This adds aspire stop --force support for cleaning up persistent DCP resources for an AppHost without relaunching the AppHost.

User-facing usage

Users can stop the selected AppHost and clean up its persistent resources with:

aspire stop --force

The command first performs the normal AppHost stop flow. It then computes the stable workload ID for the AppHost and invokes DCP cleanup for that workload.

Implementation notes

The CLI now stamps DCP_WORKLOAD_ID when launching .NET and guest AppHosts. The workload ID is derived from the AppHost path after symlink resolution, with Windows-only path lowercasing to preserve Windows path casing behavior without collapsing distinct case-sensitive paths on macOS or Linux.

aspire stop --force computes the same workload ID and runs dcp cleanup <workloadId> using the CLI bundle when available, or the discovered Aspire layout DCP otherwise. The command does not relaunch the AppHost to discover resources.

For .NET AppHosts, cleanup compatibility is checked from AppHost metadata. AppHosts using the Aspire CLI bundle are treated as compatible. Non-bundle AppHosts on Aspire.Hosting 13.5 or later are also treated as compatible. If the AppHost version is older, missing, or cannot be inspected, the CLI emits a warning and still attempts DCP cleanup for the workload ID.

Validation

dotnet test --project tests/Aspire.Cli.Tests/Aspire.Cli.Tests.csproj --no-launch-profile -- --filter-class "*.DotNetAppHostProjectTests" --filter-class "*.StopCommandTests" --filter-class "*.GuestAppHostProjectTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"
ASPIRE_E2E_ARCHIVE=/tmp/aspire-stopforce-smoke.tar.gz dotnet test --project tests/Aspire.Cli.EndToEnd.Tests/Aspire.Cli.EndToEnd.Tests.csproj --no-launch-profile -- --filter-method "*.StopForceCleansUpPersistentContainer" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"
git diff --check

Fixes #17324
Fixes #9363

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 9, 2026 21:51
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🚀 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/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 18718

Or

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

Copilot AI 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.

Pull request overview

Adds aspire stop --force to stop an AppHost and relaunch it in DCP cleanup mode for persistent resources.

Changes:

  • Adds CLI cleanup launch, version gating, warnings, and guest propagation.
  • Adds DCP persistent/cleanup lifecycle modes.
  • Adds unit and end-to-end coverage.

Reviewed changes

Copilot reviewed 34 out of 35 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/Aspire.Hosting.Tests/Dcp/ResourceSnapshotBuilderTests.cs Updates lifecycle snapshot coverage.
tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs Tests persistent and cleanup modes.
tests/Aspire.Hosting.Tests/Dcp/ConfigureDefaultDcpOptionsTests.cs Tests cleanup configuration binding.
tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs Registers the cleanup launcher.
tests/Aspire.Cli.Tests/Commands/StopCommandTests.cs Tests stop --force behavior.
tests/Aspire.Cli.EndToEnd.Tests/StopForceTests.cs Verifies persistent container removal.
src/Shared/KnownConfigNames.cs Defines the cleanup configuration key.
src/Aspire.Hosting/Dcp/ResourceSnapshotBuilder.cs Reads the new lifecycle mode.
src/Aspire.Hosting/Dcp/Model/ModelCommon.cs Defines lifecycle mode values.
src/Aspire.Hosting/Dcp/Model/Executable.cs Adds executable lifecycle mode.
src/Aspire.Hosting/Dcp/Model/ContainerNetwork.cs Adds network lifecycle mode.
src/Aspire.Hosting/Dcp/Model/Container.cs Adds container lifecycle mode.
src/Aspire.Hosting/Dcp/ExecutableCreator.cs Emits cleanup executable specifications.
src/Aspire.Hosting/Dcp/DcpVersion.cs Raises the minimum DCP version.
src/Aspire.Hosting/Dcp/DcpOptions.cs Configures and validates cleanup mode.
src/Aspire.Hosting/Dcp/ContainerCreator.cs Emits cleanup container specifications.
src/Aspire.Cli/Resources/xlf/StopCommandStrings.zh-Hant.xlf Updates Traditional Chinese localization data.
src/Aspire.Cli/Resources/xlf/StopCommandStrings.zh-Hans.xlf Updates Simplified Chinese localization data.
src/Aspire.Cli/Resources/xlf/StopCommandStrings.tr.xlf Updates Turkish localization data.
src/Aspire.Cli/Resources/xlf/StopCommandStrings.ru.xlf Updates Russian localization data.
src/Aspire.Cli/Resources/xlf/StopCommandStrings.pt-BR.xlf Updates Portuguese localization data.
src/Aspire.Cli/Resources/xlf/StopCommandStrings.pl.xlf Updates Polish localization data.
src/Aspire.Cli/Resources/xlf/StopCommandStrings.ko.xlf Updates Korean localization data.
src/Aspire.Cli/Resources/xlf/StopCommandStrings.ja.xlf Updates Japanese localization data.
src/Aspire.Cli/Resources/xlf/StopCommandStrings.it.xlf Updates Italian localization data.
src/Aspire.Cli/Resources/xlf/StopCommandStrings.fr.xlf Updates French localization data.
src/Aspire.Cli/Resources/xlf/StopCommandStrings.es.xlf Updates Spanish localization data.
src/Aspire.Cli/Resources/xlf/StopCommandStrings.de.xlf Updates German localization data.
src/Aspire.Cli/Resources/xlf/StopCommandStrings.cs.xlf Updates Czech localization data.
src/Aspire.Cli/Resources/StopCommandStrings.resx Adds force-cleanup messages.
src/Aspire.Cli/Resources/StopCommandStrings.Designer.cs Exposes the new resources.
src/Aspire.Cli/Projects/GuestAppHostProject.cs Propagates cleanup mode to guests.
src/Aspire.Cli/Program.cs Registers the cleanup launcher.
src/Aspire.Cli/Commands/StopCommand.cs Implements stop --force.
src/Aspire.Cli/Commands/AppHostCleanupLauncher.cs Launches and coordinates cleanup mode.
Files not reviewed (1)
  • src/Aspire.Cli/Resources/StopCommandStrings.Designer.cs: Generated file

Comment thread src/Aspire.Cli/Commands/AppHostCleanupLauncher.cs Outdated
Comment thread src/Aspire.Cli/Commands/AppHostCleanupLauncher.cs Outdated
Comment thread src/Aspire.Cli/Commands/StopCommand.cs Outdated
Comment thread src/Aspire.Cli/Projects/GuestAppHostProject.cs Outdated
Comment thread src/Aspire.Cli/Commands/AppHostCleanupLauncher.cs Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 9, 2026 22:11

Copilot AI 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.

Pull request overview

Copilot reviewed 36 out of 37 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • src/Aspire.Cli/Resources/StopCommandStrings.Designer.cs: Generated file

Comment thread src/Aspire.Hosting/Dcp/ResourceSnapshotBuilder.cs Outdated
Comment thread src/Aspire.Cli/Commands/StopCommand.cs Outdated
Comment thread tests/Aspire.Cli.Tests/Commands/StopCommandTests.cs Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 9, 2026 22:31
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI 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.

Pull request overview

Copilot reviewed 37 out of 38 changed files in this pull request and generated 6 comments.

Files not reviewed (1)
  • src/Aspire.Cli/Resources/StopCommandStrings.Designer.cs: Generated file

Comment thread src/Aspire.Cli/Commands/StopCommand.cs Outdated
Comment thread src/Aspire.Cli/Commands/StopCommand.cs Outdated
Comment thread Aspire.slnx
Comment thread src/Aspire.Hosting/Dcp/ContainerCreator.cs Outdated
Comment thread src/Aspire.Hosting/Dcp/ContainerCreator.cs Outdated
Comment thread src/Aspire.Hosting/Dcp/ExecutableCreator.cs Outdated
Copilot AI review requested due to automatic review settings July 9, 2026 22:39

Copilot AI 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.

Pull request overview

Copilot reviewed 37 out of 38 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • src/Aspire.Cli/Resources/StopCommandStrings.Designer.cs: Generated file

Comment thread src/Aspire.Cli/Commands/AppHostCleanupLauncher.cs Outdated
Comment thread Aspire.slnx
Treat failures while inspecting the AppHost version as an unknown version so a successful stop --force does not become a failed command before cleanup.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 9, 2026 22:51
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI 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.

Pull request overview

Copilot reviewed 37 out of 38 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • src/Aspire.Cli/Resources/StopCommandStrings.Designer.cs: Generated file

Comment thread Aspire.slnx
Comment thread src/Aspire.Hosting/Dcp/ContainerCreator.cs Outdated
Copilot AI review requested due to automatic review settings July 9, 2026 22:56

Copilot AI 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.

Pull request overview

Copilot reviewed 37 out of 38 changed files in this pull request and generated 5 comments.

Files not reviewed (1)
  • src/Aspire.Cli/Resources/StopCommandStrings.Designer.cs: Generated file

Comment thread src/Aspire.Cli/Commands/AppHostCleanupLauncher.cs Outdated
Comment thread src/Aspire.Cli/Commands/AppHostCleanupLauncher.cs Outdated
Comment thread Aspire.slnx
Comment thread src/Aspire.Cli/Commands/StopCommand.cs
Comment thread src/Aspire.Cli/Commands/StopCommand.cs Outdated
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 9, 2026 23:15
@danegsta

Copy link
Copy Markdown
Member Author

Converting back to draft while I fix a timing issue with running the cleanup command while DCP is doing graceful shutdown.

Copilot AI review requested due to automatic review settings July 20, 2026 22:37
@github-actions

This comment has been minimized.

Copilot AI 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.

Pull request overview

Copilot reviewed 29 out of 30 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • src/Aspire.Cli/Resources/StopCommandStrings.Designer.cs: Generated file
Comments suppressed due to low confidence (2)

src/Aspire.Cli/Projects/DotNetAppHostProject.cs:548

  • This value is not authoritative on the dotnet run fallback paths (watch, single-file, extension-host, multi-targeted, or direct-launch-disabled AppHosts). dotnet run reapplies launch-profile environmentVariables to the child process, overriding inherited values, so a profile containing DCP_WORKLOAD_ID records resources under that value while stop --force computes the stable ID and reports successful cleanup of zero matches. Preserve the profile inputs but reapply this reserved value after profile merging for every launch path.
        env[KnownConfigNames.DcpWorkloadId] = AppHostWorkloadId.Create(effectiveAppHostFile);

src/Aspire.Cli/Commands/DcpWorkloadCleanupService.cs:65

  • Bundle acquisition calls FileLock.AcquireAsync, which throws TimeoutException after its five-minute contention timeout. That expected failure is not included in this filter, so it escapes the cleanup-specific result handling and is reported by BaseCommand as an unexpected command failure instead of DcpCleanupFailed. Include TimeoutException in the cleanup failure filter.
        catch (Exception ex) when (ex is InvalidOperationException or Win32Exception or IOException or UnauthorizedAccessException)

@danegsta

Copy link
Copy Markdown
Member Author

PR Testing Report

PR Information

Artifact Version Verification

  • Expected Commit: b8ceb48
  • Installed Version: 13.5.0-pr.18718.gb8ceb485
  • Status: Verified - installed dogfood CLI contains the PR head short SHA b8ceb485.
  • Bundled DCP: 0.25.8 (63bdff89403cb26d2e3b793613fcd967921f6db6, build 2026-07-20T20:42:26Z)

Changes Analyzed

Files Changed

  • src/Aspire.Cli/Commands/DcpWorkloadCleanupService.cs - Added DCP cleanup invocation service.
  • src/Aspire.Cli/Commands/StopCommand.cs - Added stop --force flow and validation.
  • src/Aspire.Cli/Projects/AppHostWorkloadId.cs - Added stable AppHost workload ID calculation.
  • src/Aspire.Cli/Projects/DotNetAppHostProject.cs - Stamps workload ID / bundled DCP config for .NET AppHosts.
  • src/Aspire.Cli/Projects/GuestAppHostProject.cs - Stamps workload ID for guest AppHosts.
  • src/Aspire.Cli/Resources/StopCommandStrings.* - Added localized stop/cleanup messages.
  • src/Shared/KnownConfigNames.cs - Added DCP/workload config names.
  • tests/Aspire.Cli.EndToEnd.Tests/StopForceTests.cs - Added E2E cleanup coverage.
  • tests/Aspire.Cli.Tests/** - Added/updated unit coverage for stop force, workload IDs, and project launch config.
  • tests/Aspire.Hosting.Tests/Dcp/ConfigureDefaultDcpOptionsTests.cs - Adjusted DCP option expectations.

Change Categories

  • CLI changes detected
  • Hosting integration changes
  • Dashboard changes
  • Client/component changes
  • Template changes
  • VS Code extension changes
  • Test changes detected
  • CI infrastructure changes

Test Scenarios Executed

Scenario 1: Foreground run cleanup race

Objective: Verify official DCP 0.25.8 handles the previously observed lease-release race when aspire stop --force --apphost is invoked immediately against a foreground aspire run AppHost.
Coverage Type: Happy path / race regression
Status: Passed

Steps:

  1. Created an aspire-empty file-based C# AppHost from the PR hive and version.
  2. Added a persistent Redis container named cleanupfinalfg123.
  3. Started the AppHost with aspire run --apphost <apphost.cs> --non-interactive in the background.
  4. Waited only until Docker reported the persistent Redis container running.
  5. Immediately ran aspire stop --force --apphost <apphost.cs> from another command context.
  6. Confirmed the command exited successfully, the foreground run process was gone, and the persistent Docker container was removed.

Evidence:

  • Scenario log: logs/scenario-1-foreground-race.log
  • AppHost output: logs/scenario-1-run-output.txt
  • Stop output: logs/scenario-1-stop-output.txt
  • CLI cleanup log: cli-logs/cli_20260720T234310_d3f08979.log

Observations:

  • DCP cleanup stdout reported {"stopped":{"containers":1,"executables":0,"networks":1}}.
  • No resource lease is held, active endpoints, or DCP cleanup failure markers were present.

Scenario 2: Detached start cleanup happy path

Objective: Verify aspire stop --force --apphost <path> stops a detached AppHost and removes a persistent Redis container created by DCP.
Coverage Type: Happy path
Status: Passed

Steps:

  1. Created a fresh file-based AppHost with persistent Redis container cleanupfinaldet123.
  2. Started it with aspire start --apphost <apphost.cs> --format json under a pseudo-terminal.
  3. Confirmed the container was running.
  4. Ran aspire stop --force --apphost <apphost.cs>.
  5. Confirmed the persistent container was removed.

Evidence:

  • Scenario log: logs/scenario-2-detached-start.log
  • CLI cleanup log: cli-logs/cli_20260720T234322_d3bd01b2.log

Observations:

  • DCP cleanup stdout reported one container and one network stopped.

Scenario 3: Cleanup after AppHost is already stopped

Objective: Verify stop --force --apphost <path> cleans persistent resources even when the known AppHost is no longer running.
Coverage Type: Recovery / already-stopped state
Status: Passed

Steps:

  1. Created a fresh AppHost with persistent Redis container cleanupfinalstopped123.
  2. Started it with detached aspire start.
  3. Confirmed the container was running.
  4. Ran normal aspire stop --apphost <apphost.cs> without --force; the persistent container remained.
  5. Ran aspire stop --force --apphost <apphost.cs> after the AppHost was stopped.
  6. Confirmed the persistent container was removed.

Evidence:

  • Scenario log: logs/scenario-3-already-stopped.log
  • CLI cleanup log: cli-logs/cli_20260720T234334_ee100444.log

Observations:

  • The command printed the expected informational “No AppHost is currently running” message and still proceeded to cleanup.

Scenario 4: Symlinked parent-directory AppHost path

Objective: Verify workload identity is stable when the AppHost is started through a symlinked parent directory and force-stopped using the real parent directory path.
Coverage Type: Boundary
Status: Passed

Steps:

  1. Created a fresh AppHost with persistent Redis container cleanupfinalsym123.
  2. Created a symlink to the AppHost project directory.
  3. Started the AppHost using <symlinked-dir>/apphost.cs.
  4. Confirmed the container was running.
  5. Ran aspire stop --force --apphost <real-dir>/apphost.cs.
  6. Confirmed the persistent container was removed.

Evidence:

  • Scenario log: logs/scenario-4-symlink-dir.log
  • CLI cleanup log: cli-logs/cli_20260720T234347_12d9050c.log

Observations:

  • The CLI discovered the running AppHost under the symlinked path but cleanup using the real path still targeted the same workload and removed the persistent resource.

Scenario 5: Invalid --force --all option combination

Objective: Verify invalid force/all usage fails safely with a clear validation error.
Coverage Type: Unhappy path
Status: Passed

Steps:

  1. Ran aspire stop --force --all.
  2. Confirmed the command exited non-zero.
  3. Confirmed the error explained that --all and --force cannot be used together.

Expected Unhappy-Path Outcome: A non-zero exit code and validation error.

Evidence:

  • Scenario log: logs/scenario-5-invalid-options.log
  • CLI validation log: cli-logs/cli_20260720T234348_a1f428bc.log

Observations:

  • The command exited with code 1 and printed: The --all and --force options cannot be used together.

Summary

Scenario Status Notes
Foreground run cleanup race Passed Official DCP 0.25.8 cleaned one persistent container and one network immediately after foreground run stop.
Detached start cleanup happy path Passed Persistent container removed after detached start.
Already-stopped AppHost cleanup Passed Cleanup proceeded after “No AppHost is currently running.”
Symlinked parent-directory AppHost path Passed Start via symlink path and cleanup via real path succeeded.
Invalid --force --all option combination Passed Non-zero exit with clear validation error.

Overall Result

PR VERIFIED

All approved local smoke scenarios passed against PR dogfood CLI 13.5.0-pr.18718.gb8ceb485 and official bundled DCP 0.25.8. The previous foreground-run cleanup race did not reproduce; DCP cleanup reported successful removal of the persistent container and network.

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

Copilot-Session: fa0e5f04-5e48-4592-8d8c-d20e961cbadb
Copilot AI review requested due to automatic review settings July 21, 2026 01:15
@github-actions

This comment has been minimized.

Copilot AI 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.

Pull request overview

Copilot reviewed 29 out of 30 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • src/Aspire.Cli/Resources/StopCommandStrings.Designer.cs: Generated file
Comments suppressed due to low confidence (1)

src/Aspire.Cli/Projects/DotNetAppHostProject.cs:547

  • This value is not authoritative on fallback dotnet run paths (watch mode, extension hosts, disabled direct launch, or unsupported launch profiles). dotnet run applies launchSettings.json environment variables after inherited process variables, so a profile containing DCP_WORKLOAD_ID overrides this stable ID. DCP then records resources under the profile value while stop --force computes a different ID and reports successful cleanup of zero resources. Preserve the other launch-profile inputs while ensuring this internal key cannot be overridden; the added conflicting-profile test currently exercises only direct launch.
        env[KnownConfigNames.DcpWorkloadId] = AppHostWorkloadId.Create(effectiveAppHostFile);

Comment thread src/Shared/KnownConfigNames.cs
@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

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

Copilot-Session: fa0e5f04-5e48-4592-8d8c-d20e961cbadb
Copilot AI review requested due to automatic review settings July 21, 2026 01:49
@github-actions

This comment has been minimized.

Copilot AI 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.

Pull request overview

Copilot reviewed 29 out of 30 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • src/Aspire.Cli/Resources/StopCommandStrings.Designer.cs: Generated file
Comments suppressed due to low confidence (2)

src/Aspire.Cli/Commands/StopCommand.cs:123

  • This resolves and validates an explicit AppHost before performing the normal stop. Unlike the existing socket fast path, ProjectLocator runs ValidateAppHostAsync; if a running .NET AppHost becomes unbuildable after launch, resolution returns no project and --force never stops it. Preserve the normal file/socket-first stop behavior, then use the stopped connection path for cleanup (falling back to project discovery only when nothing is running).
        var appHostFile = passedAppHostProjectFile is not null
            ? await TryResolveAppHostFileAsync(passedAppHostProjectFile, cancellationToken).ConfigureAwait(false)
            : null;

src/Aspire.Cli/Projects/DotNetAppHostProject.cs:547

  • The workload ID is only added to the environment of the dotnet run process. On fallback paths, the .NET SDK subsequently applies launch-profile environment variables to the AppHost command, so a profile containing DCP_WORKLOAD_ID overrides this computed value. DCP then records resources under the profile value and stop --force cleans the computed value, leaving resources behind. Pass this internal value through the SDK's authoritative runtime-environment mechanism while preserving the other launch-profile inputs.
        env[KnownConfigNames.DcpWorkloadId] = AppHostWorkloadId.Create(effectiveAppHostFile);

Comment thread src/Aspire.Cli/Commands/StopCommand.cs
Comment thread src/Aspire.Cli/Commands/DcpWorkloadCleanupService.cs
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: fa0e5f04-5e48-4592-8d8c-d20e961cbadb

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 21, 2026 02:01

Copilot AI 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.

Pull request overview

Copilot reviewed 29 out of 30 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • src/Aspire.Cli/Resources/StopCommandStrings.Designer.cs: Generated file
Comments suppressed due to low confidence (1)

src/Aspire.Cli/Projects/DotNetAppHostProject.cs:547

  • This value is authoritative only on the direct-launch path, where TryCreateDirectRunSpecAsync overlays env after launch-profile variables. On any fallback to _runner.RunAsync (including watch and executable profiles), NoLaunchProfile is false and dotnet run reapplies launchSettings.json variables to the AppHost process. A profile containing DCP_WORKLOAD_ID therefore overrides this computed ID, so DCP records resources under a different workload and stop --force can report success without cleaning them. Ensure the fallback launch gives the computed workload ID precedence over profile values, and cover a fallback profile containing a conflicting value.
        env[KnownConfigNames.DcpWorkloadId] = AppHostWorkloadId.Create(effectiveAppHostFile);

Comment thread src/Aspire.Cli/Commands/StopCommand.cs Outdated
@github-actions

This comment has been minimized.

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

Copilot-Session: fa0e5f04-5e48-4592-8d8c-d20e961cbadb
Copilot AI review requested due to automatic review settings July 21, 2026 02:35
@github-actions

Copy link
Copy Markdown
Contributor

Tests selector (audit mode)

The full test matrix and all jobs still run in audit mode. The tests and jobs below are what selective CI would run under enforcement.

54 / 100 test projects · 5 jobs, from 30 changed files.

Selected test projects (54 / 100)

Aspire.Cli.EndToEnd.Tests, Aspire.Cli.Tests, Aspire.Dashboard.Components.Tests, Aspire.Dashboard.Tests, Aspire.EndToEnd.Tests, Aspire.Hosting.Analyzers.Tests, Aspire.Hosting.Azure.Kubernetes.Tests, Aspire.Hosting.Azure.Kusto.Tests, Aspire.Hosting.Azure.Tests, Aspire.Hosting.Blazor.Tests, Aspire.Hosting.Browsers.Tests, Aspire.Hosting.CodeGeneration.Go.Tests, Aspire.Hosting.CodeGeneration.Java.Tests, Aspire.Hosting.CodeGeneration.Python.Tests, Aspire.Hosting.CodeGeneration.Rust.Tests, Aspire.Hosting.CodeGeneration.TypeScript.Tests, Aspire.Hosting.Containers.Tests, Aspire.Hosting.DevTunnels.Tests, Aspire.Hosting.Docker.Tests, Aspire.Hosting.Dotnet.Tests, Aspire.Hosting.DotnetTool.Tests, Aspire.Hosting.EntityFrameworkCore.Tests, Aspire.Hosting.Foundry.Tests, Aspire.Hosting.Garnet.Tests, Aspire.Hosting.GitHub.Models.Tests, Aspire.Hosting.Go.Tests, Aspire.Hosting.JavaScript.Tests, Aspire.Hosting.Kafka.Tests, Aspire.Hosting.Keycloak.Tests, Aspire.Hosting.Kubernetes.Tests, Aspire.Hosting.Maui.Tests, Aspire.Hosting.Milvus.Tests, Aspire.Hosting.MongoDB.Tests, Aspire.Hosting.MySql.Tests, Aspire.Hosting.Nats.Tests, Aspire.Hosting.OpenAI.Tests, Aspire.Hosting.Oracle.Tests, Aspire.Hosting.Orleans.Tests, Aspire.Hosting.PostgreSQL.Tests, Aspire.Hosting.Python.Tests, Aspire.Hosting.Qdrant.Tests, Aspire.Hosting.RabbitMQ.Tests, Aspire.Hosting.Radius.Tests, Aspire.Hosting.Redis.Tests, Aspire.Hosting.RemoteHost.Tests, Aspire.Hosting.Seq.Tests, Aspire.Hosting.SqlServer.Tests, Aspire.Hosting.Testing.Tests, Aspire.Hosting.Tests, Aspire.Hosting.Valkey.Tests, Aspire.Hosting.Yarp.Tests, Aspire.Managed.Tests, Aspire.Playground.Tests, Aspire.Templates.Tests

Selected jobs (5)

cli-starter, deployment-e2e, extension-e2e, polyglot, typescript-api-compat


How these were chosen — grouped by what changed

⚠️ 47 of the 54 selected test projects come from a single change — src/Shared/KnownConfigNames.cs.

🔧 src/Shared/KnownConfigNames.cs (changed source)
47 via the project graph

show 47

Aspire.Dashboard.Components.Tests, Aspire.Dashboard.Tests, Aspire.Hosting.Analyzers.Tests (2 hops), Aspire.Hosting.Azure.Kubernetes.Tests (2 hops), Aspire.Hosting.Azure.Kusto.Tests (2 hops), Aspire.Hosting.Azure.Tests, Aspire.Hosting.Browsers.Tests, Aspire.Hosting.CodeGeneration.Go.Tests, Aspire.Hosting.CodeGeneration.Java.Tests, Aspire.Hosting.CodeGeneration.Python.Tests, Aspire.Hosting.CodeGeneration.Rust.Tests, Aspire.Hosting.CodeGeneration.TypeScript.Tests, Aspire.Hosting.Containers.Tests, Aspire.Hosting.DevTunnels.Tests (2 hops), Aspire.Hosting.Docker.Tests (2 hops), Aspire.Hosting.DotnetTool.Tests (2 hops), Aspire.Hosting.EntityFrameworkCore.Tests (2 hops), Aspire.Hosting.Foundry.Tests (2 hops), Aspire.Hosting.Garnet.Tests (2 hops), Aspire.Hosting.GitHub.Models.Tests, Aspire.Hosting.Go.Tests (2 hops), Aspire.Hosting.JavaScript.Tests (2 hops), Aspire.Hosting.Kafka.Tests (2 hops), Aspire.Hosting.Keycloak.Tests (2 hops), Aspire.Hosting.Kubernetes.Tests (2 hops), Aspire.Hosting.Maui.Tests, Aspire.Hosting.Milvus.Tests (2 hops), Aspire.Hosting.MongoDB.Tests (2 hops), Aspire.Hosting.MySql.Tests (2 hops), Aspire.Hosting.Nats.Tests (2 hops), Aspire.Hosting.OpenAI.Tests, Aspire.Hosting.Oracle.Tests (2 hops), Aspire.Hosting.Orleans.Tests (2 hops), Aspire.Hosting.PostgreSQL.Tests (2 hops), Aspire.Hosting.Python.Tests (2 hops), Aspire.Hosting.Qdrant.Tests (2 hops), Aspire.Hosting.RabbitMQ.Tests (2 hops), Aspire.Hosting.Redis.Tests (2 hops), Aspire.Hosting.RemoteHost.Tests, Aspire.Hosting.Seq.Tests (2 hops), Aspire.Hosting.SqlServer.Tests (2 hops), Aspire.Hosting.Testing.Tests, Aspire.Hosting.Valkey.Tests (2 hops), Aspire.Hosting.Yarp.Tests (2 hops), Aspire.Managed.Tests, Aspire.Playground.Tests, Aspire.Templates.Tests

🧪 tests/Aspire.Hosting.Tests/Dcp/ConfigureDefaultDcpOptionsTests.cs (changed test)
1 directly: Aspire.Hosting.Tests
3 via the project graph: Aspire.Hosting.Blazor.Tests, Aspire.Hosting.Dotnet.Tests, Aspire.Hosting.Radius.Tests

📦 affected project Aspire.Cli
1 test: Aspire.Cli.EndToEnd.Tests

📦 affected project Aspire.Hosting
1 test: Aspire.EndToEnd.Tests

🔧 src/Aspire.Cli/Resources/StopCommandStrings.Designer.cs (changed source)
1 via the project graph: Aspire.Cli.EndToEnd.Tests

🧪 tests/Aspire.Cli.EndToEnd.Tests/StopForceTests.cs (changed test)
1 directly: Aspire.Cli.EndToEnd.Tests

🧪 tests/Aspire.Cli.Tests/Commands/StopCommandTests.cs (changed test)
1 directly: Aspire.Cli.Tests

🧪 tests/Aspire.Cli.Tests/Projects/AppHostWorkloadIdTests.cs (changed test)
1 directly: Aspire.Cli.Tests

🧪 tests/Aspire.Cli.Tests/Projects/DotNetAppHostProjectTests.cs (changed test)
1 directly: Aspire.Cli.Tests

🧪 tests/Aspire.Cli.Tests/Projects/GuestAppHostProjectTests.cs (changed test)
1 directly: Aspire.Cli.Tests

🧪 tests/Aspire.Cli.Tests/TestServices/FakeAppHostServerSession.cs (changed test)
1 directly: Aspire.Cli.Tests

🧪 tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs (changed test)
1 directly: Aspire.Cli.Tests

Job reasons

Job Triggered by
cli-starter • affected project Aspire.Cli
• selected test Aspire.Cli.Tests
deployment-e2e affected project Aspire.Cli
extension-e2e src/Aspire.Cli/Commands/DcpWorkloadCleanupService.cs, src/Aspire.Cli/Commands/StopCommand.cs, src/Aspire.Cli/Program.cs, src/Aspire.Cli/Projects/AppHostWorkloadId.cs, src/Aspire.Cli/Projects/DotNetAppHostProject.cs, src/Aspire.Cli/Projects/GuestAppHostProject.cs, src/Aspire.Cli/Resources/StopCommandStrings.Designer.cs, src/Aspire.Cli/Resources/StopCommandStrings.resx, src/Aspire.Cli/Resources/xlf/StopCommandStrings.cs.xlf, src/Aspire.Cli/Resources/xlf/StopCommandStrings.de.xlf, src/Aspire.Cli/Resources/xlf/StopCommandStrings.es.xlf, src/Aspire.Cli/Resources/xlf/StopCommandStrings.fr.xlf, src/Aspire.Cli/Resources/xlf/StopCommandStrings.it.xlf, src/Aspire.Cli/Resources/xlf/StopCommandStrings.ja.xlf, src/Aspire.Cli/Resources/xlf/StopCommandStrings.ko.xlf, src/Aspire.Cli/Resources/xlf/StopCommandStrings.pl.xlf, src/Aspire.Cli/Resources/xlf/StopCommandStrings.pt-BR.xlf, src/Aspire.Cli/Resources/xlf/StopCommandStrings.ru.xlf, src/Aspire.Cli/Resources/xlf/StopCommandStrings.tr.xlf, src/Aspire.Cli/Resources/xlf/StopCommandStrings.zh-Hans.xlf, src/Aspire.Cli/Resources/xlf/StopCommandStrings.zh-Hant.xlf, tests/Aspire.Cli.EndToEnd.Tests/StopForceTests.cs, tests/Aspire.Cli.Tests/Commands/StopCommandTests.cs, tests/Aspire.Cli.Tests/Projects/AppHostWorkloadIdTests.cs, tests/Aspire.Cli.Tests/Projects/DotNetAppHostProjectTests.cs, tests/Aspire.Cli.Tests/Projects/GuestAppHostProjectTests.cs, tests/Aspire.Cli.Tests/TestServices/FakeAppHostServerSession.cs, tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs
• affected project Aspire.Cli
polyglot affected project Aspire.Cli
typescript-api-compat affected project Aspire.Cli

Selection computed for commit b28f0d1.

Copilot AI 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.

Pull request overview

Copilot reviewed 29 out of 30 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • src/Aspire.Cli/Resources/StopCommandStrings.Designer.cs: Generated file
Comments suppressed due to low confidence (3)

src/Aspire.Cli/Commands/StopCommand.cs:299

  • The AppHost path is already known from the selected connection, but this branch discards it when the socket disappears between resolution and this second lookup. In the --force flow that triggers fresh project discovery, which can clean a different local AppHost workload (or fail) instead of the one the user selected. Preserve appHostFile even when there is nothing left to stop.
            return new StopAppHostResult(CliExitCodes.Success, null);

src/Aspire.Cli/Commands/StopCommand.cs:320

  • A successfully resolved AppHost can disappear or fail the redundant monitor scan before this point. Returning null loses that selected path, so stop --force falls back to project discovery and may clean the wrong workload. Return the known appHostFile here just as on a successful stop.
            return new StopAppHostResult(CliExitCodes.Success, null);

src/Aspire.Cli/Projects/DotNetAppHostProject.cs:547

  • This environment assignment is not authoritative on the dotnet run fallback path. dotnet run applies launch-profile environment variables to the AppHost child after inheriting this environment, so a profile containing DCP_WORKLOAD_ID overrides the stable ID; direct launch explicitly avoids that by merging env after the profile. In fallback scenarios such as watch mode or disabled/unsupported direct launch, stop --force then cleans the computed ID, finds no resources, and reports success. Ensure the internal workload ID is reapplied after launch-profile processing for every launch path.
        env[KnownConfigNames.DcpWorkloadId] = AppHostWorkloadId.Create(effectiveAppHostFile);

Comment thread src/Aspire.Cli/Commands/StopCommand.cs
@danegsta

Copy link
Copy Markdown
Member Author

PR Testing Report

PR Information

Artifact Version Verification

  • Expected Commit: b28f0d1
  • Installed Version: 13.5.0-pr.18718.gb28f0d16
  • Status: Verified. The installed dogfood CLI version contains the PR head short SHA b28f0d16.

Changes Analyzed

Files Changed

  • src/Aspire.Cli/Commands/DcpWorkloadCleanupService.cs - Added DCP workload cleanup invocation.
  • src/Aspire.Cli/Commands/StopCommand.cs - Added --force, cleanup flow, all-matching selected-AppHost stop behavior, compatibility checks, and option validation.
  • src/Aspire.Cli/Program.cs - Registered cleanup service dependencies.
  • src/Aspire.Cli/Projects/AppHostWorkloadId.cs - Added stable AppHost workload ID generation.
  • src/Aspire.Cli/Projects/DotNetAppHostProject.cs - Stamps DCP workload ID for .NET AppHost launches.
  • src/Aspire.Cli/Projects/GuestAppHostProject.cs - Stamps DCP workload ID for guest AppHost launches.
  • src/Aspire.Cli/Resources/StopCommandStrings.* and src/Aspire.Cli/Resources/xlf/StopCommandStrings.*.xlf - Added localized stop/cleanup messages.
  • src/Shared/KnownConfigNames.cs - Added DCP workload and publisher config names.
  • tests/Aspire.Cli.EndToEnd.Tests/StopForceTests.cs - Added Docker-backed stop-force cleanup E2E coverage.
  • tests/Aspire.Cli.Tests/** and tests/Aspire.Hosting.Tests/Dcp/ConfigureDefaultDcpOptionsTests.cs - Added/updated focused unit coverage.

Change Categories

  • CLI changes detected
  • Hosting integration changes
  • Dashboard changes
  • CI infrastructure changes
  • VS Code extension changes
  • Test changes detected

Test Scenarios Executed

Scenario 1: Focused source validation

Objective: Verify focused unit coverage for the changed CLI stop, workload ID, and AppHost launch environment behavior.
Coverage Type: Unit/source validation
Status: Passed

Steps:

  1. Ran dotnet test --project tests/Aspire.Cli.Tests/Aspire.Cli.Tests.csproj --no-launch-profile -- --filter-class "*.StopCommandTests" --filter-class "*.AppHostWorkloadIdTests" --filter-class "*.DotNetAppHostProjectTests" --filter-class "*.GuestAppHostProjectTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true".
  2. Attempted the focused new E2E method *.StopForceCleansUpPersistentContainer.

Evidence:

  • Unit test output: command output captured in this session.
  • Docker availability: docker info --format '{{.ServerVersion}}' returned 29.6.1.

Observations:

  • 138 focused CLI unit tests passed.
  • The source E2E method skipped because this local checkout did not have a local Aspire CLI bundle and the E2E runner selected the latest GA install-script strategy. The manual dogfood scenarios below exercised the runtime behavior with PR bits.

Scenario 2: Dogfood artifact verification

Objective: Verify the tested CLI came from PR #18718 and matches the latest PR head.
Coverage Type: Artifact verification
Status: Passed

Steps:

  1. Installed the PR CLI with curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 18718 --install-path <temp> --skip-path --skip-extension.
  2. Ran the installed binary from the isolated temp path with --version.

Evidence:

  • Install log: /var/folders/97/44fp_02d4kd90s9p6sy_jwgh0000gn/T/aspire-pr18718-test-XXXXXX.5Y5yERAGt7/logs/install.log
  • Version verification log: /var/folders/97/44fp_02d4kd90s9p6sy_jwgh0000gn/T/aspire-pr18718-test-XXXXXX.5Y5yERAGt7/logs/version-verify.log
  • CLI path: /var/folders/97/44fp_02d4kd90s9p6sy_jwgh0000gn/T/aspire-pr18718-test-XXXXXX.5Y5yERAGt7/dogfood/pr-18718/bin/aspire
  • PR package hive: /var/folders/97/44fp_02d4kd90s9p6sy_jwgh0000gn/T/aspire-pr18718-test-XXXXXX.5Y5yERAGt7/hives/pr-18718/packages

Observations:

  • Installed version was 13.5.0-pr.18718.gb28f0d16, matching PR head short SHA b28f0d16.

Scenario 3: Persistent cleanup happy path

Objective: Verify aspire stop --force --apphost <path> stops a running AppHost and removes its persistent DCP container resource.
Coverage Type: Happy path
Status: Passed

Steps:

  1. Created a fresh aspire-empty C# file-based AppHost from the PR hive.
  2. Replaced apphost.cs with an AppHost containing a Redis container using .WithPersistentLifetime() and a deterministic container name.
  3. Ran aspire start --apphost <apphost.cs> --non-interactive --nologo.
  4. Verified the Docker container existed.
  5. Ran aspire stop --force --apphost <apphost.cs> --non-interactive --nologo.
  6. Verified the Docker container was removed.

Evidence:

  • Scenario log: /var/folders/97/44fp_02d4kd90s9p6sy_jwgh0000gn/T/aspire-pr18718-test-XXXXXX.5Y5yERAGt7/scenario-1-persistent-happy/output.log
  • AppHost path: /var/folders/97/44fp_02d4kd90s9p6sy_jwgh0000gn/T/aspire-pr18718-test-XXXXXX.5Y5yERAGt7/scenario-1-persistent-happy/StopForceHappy/apphost.cs

Observations:

  • stop --force reported the AppHost stopped successfully and then reported persistent resources cleaned up.
  • The persistent Redis container was removed after cleanup.

Scenario 4: Already-stopped cleanup fallback

Objective: Verify aspire stop --force --apphost <path> can clean persistent resources after the AppHost has already been stopped and its running socket is gone.
Coverage Type: Unhappy path / recovery
Status: Passed

Steps:

  1. Created a fresh aspire-empty C# file-based AppHost from the PR hive.
  2. Added a persistent Redis container with a deterministic container name.
  3. Ran aspire start --apphost <apphost.cs> --non-interactive --nologo.
  4. Ran normal aspire stop --apphost <apphost.cs> --non-interactive --nologo.
  5. Verified the persistent container remained after normal stop.
  6. Ran aspire stop --force --apphost <apphost.cs> --non-interactive --nologo with no running AppHost socket.
  7. Verified the persistent container was removed.

Evidence:

  • Scenario log: /var/folders/97/44fp_02d4kd90s9p6sy_jwgh0000gn/T/aspire-pr18718-test-XXXXXX.5Y5yERAGt7/scenario-2-already-stopped/output.log
  • AppHost path: /var/folders/97/44fp_02d4kd90s9p6sy_jwgh0000gn/T/aspire-pr18718-test-XXXXXX.5Y5yERAGt7/scenario-2-already-stopped/StopForceFallback/apphost.cs

Expected Unhappy-Path Outcome: The command should treat the not-running AppHost as nonfatal when --force has a resolvable AppHost path, then run DCP cleanup.

Observations:

  • Normal stop left the persistent container running, as expected.
  • Subsequent stop --force --apphost printed the not-running message, then cleaned persistent resources successfully.

Scenario 5: Same-AppHost multi-instance shutdown

Objective: Verify one aspire stop --apphost <path> stops all running sockets for the selected AppHost path instead of only the first returned connection.
Coverage Type: Boundary / multi-instance behavior
Status: Passed

Steps:

  1. Created a fresh aspire-empty C# file-based AppHost from the PR hive.
  2. Confirmed the normal CLI launch path stops a previous same-AppHost instance before starting another; this means the scenario must create duplicate same-AppHost sockets outside the CLI start pre-stop path.
  3. Launched two concurrent direct AppHost processes with DcpPublisher__RandomizePorts=true dotnet run <apphost.cs> from the generated app directory.
  4. Ran aspire stop --apphost <apphost.cs> --non-interactive --nologo once.
  5. Verified the stop output contained two distinct successful AppHost stops with different PIDs.
  6. Ran aspire stop --apphost <apphost.cs> --non-interactive --nologo again and verified no matching AppHost was still running.

Evidence:

  • First CLI-start attempt log showing pre-stop behavior: /var/folders/97/44fp_02d4kd90s9p6sy_jwgh0000gn/T/aspire-pr18718-test-XXXXXX.5Y5yERAGt7/scenario-3-multi-instance/output.log
  • Direct multi-instance stop log: /var/folders/97/44fp_02d4kd90s9p6sy_jwgh0000gn/T/aspire-pr18718-test-XXXXXX.5Y5yERAGt7/scenario-3-multi-instance/direct-multi-output.log
  • Stop details: /var/folders/97/44fp_02d4kd90s9p6sy_jwgh0000gn/T/aspire-pr18718-test-XXXXXX.5Y5yERAGt7/scenario-3-multi-instance/direct-stop-all-matching.log
  • Post-stop check: /var/folders/97/44fp_02d4kd90s9p6sy_jwgh0000gn/T/aspire-pr18718-test-XXXXXX.5Y5yERAGt7/scenario-3-multi-instance/direct-stop-after.log

Expected Boundary Outcome: The selected AppHost path maps to both matching sockets, both processes are stopped, and a follow-up stop reports no running AppHost for that path.

Observations:

  • A single stop command reported two successful stops:
    • StopMultiInstance/apphost.cs (PID 54913)
    • StopMultiInstance/apphost.cs (PID 54962)
  • A follow-up stop reported no AppHost currently running for the same path.

Scenario 6: Invalid option boundary

Objective: Verify --all and --force are rejected together instead of performing broad cleanup.
Coverage Type: Unhappy path / validation
Status: Passed

Steps:

  1. Ran aspire stop --all --force --non-interactive --nologo with the PR CLI.
  2. Verified the command returned a non-zero exit code.
  3. Verified the error message mentioned both --all and --force.

Evidence:

  • Scenario log: /var/folders/97/44fp_02d4kd90s9p6sy_jwgh0000gn/T/aspire-pr18718-test-XXXXXX.5Y5yERAGt7/scenario-4-invalid-options/output.log
  • Exit code file: /var/folders/97/44fp_02d4kd90s9p6sy_jwgh0000gn/T/aspire-pr18718-test-XXXXXX.5Y5yERAGt7/scenario-4-invalid-options/exit-code.txt

Expected Unhappy-Path Outcome: The command should fail safely and not attempt an all-AppHosts persistent cleanup.

Observations:

  • The command printed The --all and --force options cannot be used together. and exited with code 1.

Summary

Scenario Status Notes
Focused source validation Passed 138 focused CLI unit tests passed; source E2E skipped locally due missing local bundle.
Dogfood artifact verification Passed Installed CLI version matched PR head short SHA.
Persistent cleanup happy path Passed Persistent Redis container removed by stop --force.
Already-stopped cleanup fallback Passed Cleanup succeeded after normal stop removed the AppHost socket.
Same-AppHost multi-instance shutdown Passed One stop command stopped both matching AppHost instances.
Invalid option boundary Passed --all --force rejected with non-zero exit code.

Overall Result

PR VERIFIED

The PR dogfood CLI at head b28f0d16ef100ec0b12319273aafb678aa7f18b7 passed focused unit validation and the approved local dogfood scenarios for persistent cleanup, already-stopped cleanup fallback, same-AppHost multi-instance shutdown, and invalid option validation.

@danegsta
danegsta marked this pull request as ready for review July 21, 2026 03:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

aspire stop --force to stop persistent containers (& executables) Provide a way to stop all Persistent Containers

2 participants