Add more status indicators while work is in-progress#14834
Add more status indicators while work is in-progress#14834radical merged 7 commits intorelease/13.2from
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 14834Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 14834" |
|
@davidfowl I don't know of a good way to unit test status output. Can you check the scenario you originally noticed this problem in the CLI, and see if is fixed. |
🎬 CLI E2E Test RecordingsThe following terminal recordings are available for commit
📹 Recordings uploaded automatically from CI run #22570118178 |
There was a problem hiding this comment.
Pull request overview
Improves Aspire CLI UX by adding additional in-progress status indicators (spinners/subtle messages depending on TTY) during longer-running operations, and by re-printing the selected template after the aspire new template prompt clears the selection.
Changes:
- Add new localized resource strings for update/extract/regenerate/template-resolution and “checking for running instances” statuses.
- Wrap several operations in
InteractionService.ShowStatusAsync(...)to show progress only while work is running. - In
NewCommand, re-print the selected template after the selection prompt completes.
Reviewed changes
Copilot reviewed 63 out of 67 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.zh-Hant.xlf | Add new Update progress/status string IDs. |
| src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.zh-Hans.xlf | Add new Update progress/status string IDs. |
| src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.tr.xlf | Add new Update progress/status string IDs. |
| src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.ru.xlf | Add new Update progress/status string IDs. |
| src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.pt-BR.xlf | Add new Update progress/status string IDs. |
| src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.pl.xlf | Add new Update progress/status string IDs. |
| src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.ko.xlf | Add new Update progress/status string IDs. |
| src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.ja.xlf | Add new Update progress/status string IDs. |
| src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.it.xlf | Add new Update progress/status string IDs. |
| src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.fr.xlf | Add new Update progress/status string IDs. |
| src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.es.xlf | Add new Update progress/status string IDs. |
| src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.de.xlf | Add new Update progress/status string IDs. |
| src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.cs.xlf | Add new Update progress/status string IDs. |
| src/Aspire.Cli/Resources/xlf/NewCommandStrings.zh-Hant.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/NewCommandStrings.zh-Hans.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/NewCommandStrings.tr.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/NewCommandStrings.ru.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/NewCommandStrings.pt-BR.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/NewCommandStrings.pl.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/NewCommandStrings.ko.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/NewCommandStrings.ja.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/NewCommandStrings.it.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/NewCommandStrings.fr.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/NewCommandStrings.es.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/NewCommandStrings.de.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/NewCommandStrings.cs.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/InitCommandStrings.zh-Hant.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/InitCommandStrings.zh-Hans.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/InitCommandStrings.tr.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/InitCommandStrings.ru.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/InitCommandStrings.pt-BR.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/InitCommandStrings.pl.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/InitCommandStrings.ko.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/InitCommandStrings.ja.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/InitCommandStrings.it.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/InitCommandStrings.fr.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/InitCommandStrings.es.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/InitCommandStrings.de.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/InitCommandStrings.cs.xlf | Add new “resolving template version” string ID. |
| src/Aspire.Cli/Resources/xlf/AddCommandStrings.zh-Hant.xlf | Add new “checking for running instances” string ID. |
| src/Aspire.Cli/Resources/xlf/AddCommandStrings.zh-Hans.xlf | Add new “checking for running instances” string ID. |
| src/Aspire.Cli/Resources/xlf/AddCommandStrings.tr.xlf | Add new “checking for running instances” string ID. |
| src/Aspire.Cli/Resources/xlf/AddCommandStrings.ru.xlf | Add new “checking for running instances” string ID. |
| src/Aspire.Cli/Resources/xlf/AddCommandStrings.pt-BR.xlf | Add new “checking for running instances” string ID. |
| src/Aspire.Cli/Resources/xlf/AddCommandStrings.pl.xlf | Add new “checking for running instances” string ID. |
| src/Aspire.Cli/Resources/xlf/AddCommandStrings.ko.xlf | Add new “checking for running instances” string ID. |
| src/Aspire.Cli/Resources/xlf/AddCommandStrings.ja.xlf | Add new “checking for running instances” string ID. |
| src/Aspire.Cli/Resources/xlf/AddCommandStrings.it.xlf | Add new “checking for running instances” string ID. |
| src/Aspire.Cli/Resources/xlf/AddCommandStrings.fr.xlf | Add new “checking for running instances” string ID. |
| src/Aspire.Cli/Resources/xlf/AddCommandStrings.es.xlf | Add new “checking for running instances” string ID. |
| src/Aspire.Cli/Resources/xlf/AddCommandStrings.de.xlf | Add new “checking for running instances” string ID. |
| src/Aspire.Cli/Resources/xlf/AddCommandStrings.cs.xlf | Add new “checking for running instances” string ID. |
| src/Aspire.Cli/Resources/UpdateCommandStrings.resx | Add new Update status strings. |
| src/Aspire.Cli/Resources/UpdateCommandStrings.Designer.cs | Expose new Update status strings on the strongly-typed resource class. |
| src/Aspire.Cli/Resources/NewCommandStrings.resx | Add new NewCommand status string. |
| src/Aspire.Cli/Resources/NewCommandStrings.Designer.cs | Expose new NewCommand status string on the strongly-typed resource class. |
| src/Aspire.Cli/Resources/InitCommandStrings.resx | Add new InitCommand status string. |
| src/Aspire.Cli/Resources/InitCommandStrings.Designer.cs | Expose new InitCommand status string on the strongly-typed resource class. |
| src/Aspire.Cli/Resources/AddCommandStrings.resx | Add new AddCommand status string. |
| src/Aspire.Cli/Resources/AddCommandStrings.Designer.cs | Expose new AddCommand status string on the strongly-typed resource class. |
| src/Aspire.Cli/Projects/ProjectUpdater.cs | Show an “Applying updates…” status during update-step execution. |
| src/Aspire.Cli/Projects/GuestAppHostProject.cs | Show status while regenerating SDK code and emit a completion line. |
| src/Aspire.Cli/Commands/UpdateCommand.cs | Add status while checking channels and extracting a downloaded CLI archive. |
| src/Aspire.Cli/Commands/RunCommand.cs | Add status while checking/stopping running instances before run. |
| src/Aspire.Cli/Commands/NewCommand.cs | Add template-version resolution status and re-print the selected template after prompt clears. |
| src/Aspire.Cli/Commands/InitCommand.cs | Add status while resolving template channels/versions. |
| src/Aspire.Cli/Commands/AddCommand.cs | Add status while checking/stopping running instances before dotnet add package. |
Files not reviewed (4)
- src/Aspire.Cli/Resources/AddCommandStrings.Designer.cs: Language not supported
- src/Aspire.Cli/Resources/InitCommandStrings.Designer.cs: Language not supported
- src/Aspire.Cli/Resources/NewCommandStrings.Designer.cs: Language not supported
- src/Aspire.Cli/Resources/UpdateCommandStrings.Designer.cs: Language not supported
Comments suppressed due to low confidence (6)
src/Aspire.Cli/Commands/UpdateCommand.cs:157
ShowStatusAsyncalready acceptsFunc<Task<T>>, so theasync () => await ...lambda is redundant here and adds an extra state machine allocation. Consider passing the task-returning method directly (e.g.,() => _packagingService.GetChannelsAsync(cancellationToken)).
var allChannels = await InteractionService.ShowStatusAsync(
UpdateCommandStrings.CheckingForUpdates,
async () => await _packagingService.GetChannelsAsync(cancellationToken));
src/Aspire.Cli/Commands/RunCommand.cs:211
- This
ShowStatusAsynccall wraps an async method usingasync () => await ..., which is redundant and introduces an extra state machine. Consider passing the task-returning call directly (e.g.,() => project.FindAndStopRunningInstanceAsync(...)).
var runningInstanceResult = await InteractionService.ShowStatusAsync(
RunCommandStrings.CheckingForRunningInstances,
async () => await project.FindAndStopRunningInstanceAsync(effectiveAppHostFile, ExecutionContext.HomeDirectory, cancellationToken));
src/Aspire.Cli/Commands/AddCommand.cs:220
- The
async () => await ...wrapper passed toShowStatusAsyncis redundant and allocates an extra state machine. Consider passing the task-returning method directly to reduce overhead.
var runningInstanceResult = await InteractionService.ShowStatusAsync(
AddCommandStrings.CheckingForRunningInstances,
async () => await project.FindAndStopRunningInstanceAsync(
effectiveAppHostProjectFile,
ExecutionContext.HomeDirectory,
cancellationToken));
src/Aspire.Cli/Projects/ProjectUpdater.cs:134
- Several new
ShowStatusAsyncusages wrap aFunc<Task>by returning a dummy0to satisfy the genericTask<T>signature. Consider adding aShowStatusAsync(string, Func<Task>, ...)overload (or an extension) so call sites don’t need to manufacture an unused return value, which would simplify this block.
await interactionService.ShowStatusAsync(
UpdateCommandStrings.ApplyingUpdates,
async () =>
{
foreach (var updateStep in updateSteps)
{
interactionService.DisplaySubtleMessage(string.Format(CultureInfo.InvariantCulture, UpdateCommandStrings.ExecutingUpdateStepFormat, updateStep.Description));
await updateStep.Callback();
}
return 0;
});
src/Aspire.Cli/Projects/GuestAppHostProject.cs:973
- This
ShowStatusAsynccall returns a dummy0purely to fit theFunc<Task<T>>signature. Consider adding aFunc<Task>overload forShowStatusAsync(or a helper) to avoid unused return values and keep call sites clearer.
await _interactionService.ShowStatusAsync(
UpdateCommandStrings.RegeneratingSdkCode,
async () =>
{
await BuildAndGenerateSdkAsync(directory, cancellationToken);
return 0;
});
src/Aspire.Cli/Commands/UpdateCommand.cs:359
- This
ShowStatusAsyncusage needs an unusedreturn 0;to satisfy the generic signature. Consider adding aShowStatusAsync(string, Func<Task>, ...)overload so async, non-returning work like extraction doesn’t need a fabricated return value.
await InteractionService.ShowStatusAsync(
UpdateCommandStrings.ExtractingNewCli,
async () =>
{
await ArchiveHelper.ExtractAsync(archivePath, tempExtractDir, cancellationToken);
return 0;
},
KnownEmojis.Package);
|
The specific templates in aspire new need some spinners after selecting the name and output path: Screen.Recording.2026-03-01.at.11.13.49.PM.mov |
|
@davidfowl Added to templates: |
| // to make sure we don't ever break flow. It should mostly stop | ||
| // just fine though. | ||
| var runningInstanceResult = await project.FindAndStopRunningInstanceAsync(effectiveAppHostFile, ExecutionContext.HomeDirectory, cancellationToken); | ||
| var runningInstanceResult = await InteractionService.ShowStatusAsync( |
There was a problem hiding this comment.
This flickers because its fast. I wonder if we should avoid the status if the underlying task finishes quicky.
There was a problem hiding this comment.
Definitely. Some of these were added by AI.
I'll remove it.
|
aspire start / run --detached, needs some status indicators Screen.Recording.2026-03-02.at.8.06.51.AM.mov |
* Display status in more places in CLI * Update * Update * Update * Update * Add status to templates * Fix emoji

Description
PR changes:
Fixes #14762
Checklist
<remarks />and<code />elements on your triple slash comments?aspire.devissue: