Add stop --force persistent resource cleanup#18718
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 18718Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 18718" |
There was a problem hiding this comment.
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
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
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>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
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>
This comment has been minimized.
This comment has been minimized.
Preserve socket-first apphost selection for stop --force without an explicit apphost path, then only fall back to project discovery when the stopped connection cannot provide one. Ensure internal cleanup env vars cannot be overridden by launch profiles by disabling launch profiles for cleanup launches and reapplying the cleanup flags after launch settings are read. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
Replay forwarded AppHost arguments when launching the internal cleanup AppHost so argument-dependent persistent resources are represented during DCP cleanup. Remove the unbounded dashboard URL lookup from cleanup startup and let non-interactive stop --force fall back to AppHost discovery when no running AppHost is found. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
Attempt the best-effort DCP server stop even when waited resource cleanup fails, while still propagating the cleanup exception. Add coverage for the fallback stop attempt. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
| var resourcesCreated = await WaitForAppHostResourcesCreatedAsync( | ||
| backchannel, | ||
| pendingRun, | ||
| startupStartTimestamp, | ||
| startupTimeout, | ||
| cancellationToken).ConfigureAwait(false); |
| return CliExitCodes.InvalidCommand; | ||
| } | ||
|
|
||
| return await _cleanupLauncher.CleanupAsync(project, appHostFile, timeoutSeconds, stopResult.AppHostArguments, cancellationToken).ConfigureAwait(false); |
This comment has been minimized.
This comment has been minimized.
Treat non-interactive stop --force with only out-of-scope AppHosts the same as no matching running AppHost so local project discovery can still drive cleanup. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
| return CliExitCodes.InvalidCommand; | ||
| } | ||
|
|
||
| return await _cleanupLauncher.CleanupAsync(project, appHostFile, timeoutSeconds, stopResult.AppHostArguments, cancellationToken).ConfigureAwait(false); |
| NoBuild = false, | ||
| NoRestore = false, |
Keep cleanup relaunches from disabling AppHost launch profiles, and cover that profile args and environment still flow while cleanup settings are present. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
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 51 changed files. Selected test projects (54 / 100)
Selected jobs (5)
How these were chosen — grouped by what changed
🔧 show 38
🔧 🧪 📦 affected project 📦 affected project 🔧 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 Job reasons
Selection computed for commit |
| ApplyResourceCleanupEnvironmentOverrides(env, context.EnvironmentVariables); | ||
| if (directRun is not null) | ||
| { | ||
| ApplyResourceCleanupEnvironmentOverrides(directRun.Environment, context.EnvironmentVariables); |
| if (treatNotRunningAsSuccess) | ||
| { | ||
| InteractionService.DisplayMessage(KnownEmojis.Information, SharedCommandStrings.AppHostNotRunning); | ||
| return new StopAppHostResult(CliExitCodes.Success, null, []); | ||
| } |
| var environmentVariables = new Dictionary<string, string> | ||
| { | ||
| [KnownConfigNames.DcpResourceCleanupMode] = "true", | ||
| [KnownConfigNames.DcpWaitForResourceCleanup] = "true" | ||
| }; |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
Description
This adds the
aspire stop --forceflow for cleaning up persistent DCP resources without exposing the behavior throughaspire runoraspire start. The command still stops the running AppHost normally first, then relaunches the AppHost internally in cleanup mode when the AppHost SDK supports the new DCP lifecycle mode.User-facing usage
Users can force cleanup of persistent resources for an AppHost with:
If the AppHost uses an Aspire.Hosting SDK older than 13.5.0 or the version cannot be determined, the command still performs the normal stop and warns that persistent resource cleanup was skipped.
Implementation notes
The hosting side now emits DCP resource lifecycle
modevalues, includingpersistentandcleanup, and uses DCP 0.25.4 as the minimum orchestration package version. Cleanup mode setsstop=truefor container and executable resources so DCP removes persistent resources during the internal cleanup launch.The CLI side adds a dedicated cleanup launcher used only by
aspire stop --force, propagates the cleanup flag through guest AppHosts, and gates cleanup on Aspire.Hosting 13.5.0 or newer while allowing local/prerelease 13.5.0 builds.Validation
Fixes # (issue)
Checklist
<remarks />and<code />elements on your triple slash comments?