Skip to content

Add more status indicators while work is in-progress#14834

Merged
radical merged 7 commits intorelease/13.2from
jamesnk/command-status
Mar 2, 2026
Merged

Add more status indicators while work is in-progress#14834
radical merged 7 commits intorelease/13.2from
jamesnk/command-status

Conversation

@JamesNK
Copy link
Member

@JamesNK JamesNK commented Mar 2, 2026

Description

PR changes:

  • Add more status indicators while work is in-progress in commands
  • Add status indicators while projects are created in templates
  • Fixed bad path combine on Windows for new project path
  • In NewCommand, print a message with the selected template (currently cleared when a value is selected)

Fixes #14762

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
  • Does the change require an update in our Aspire docs?

@JamesNK JamesNK requested review from Copilot, davidfowl and mitchdenny and removed request for Copilot and mitchdenny March 2, 2026 04:04
@github-actions
Copy link
Contributor

github-actions bot commented Mar 2, 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 -- 14834

Or

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

@JamesNK
Copy link
Member Author

JamesNK commented Mar 2, 2026

@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.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 2, 2026

🎬 CLI E2E Test Recordings

The following terminal recordings are available for commit 971c2a9:

Test Recording
AddPackageInteractiveWhileAppHostRunningDetached ▶️ View Recording
AddPackageWhileAppHostRunningDetached ▶️ View Recording
AgentCommands_AllHelpOutputs_AreCorrect ▶️ View Recording
AgentInitCommand_MigratesDeprecatedConfig ▶️ View Recording
AgentInitCommand_WithMalformedMcpJson_ShowsErrorAndExitsNonZero ▶️ View Recording
AspireUpdateRemovesAppHostPackageVersionFromDirectoryPackagesProps ▶️ 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
CreateAndRunTypeScriptStarterProject ▶️ View Recording
CreateEmptyAppHostProject ▶️ View Recording
CreateStartAndStopAspireProject ▶️ View Recording
CreateStartWaitAndStopAspireProject ▶️ View Recording
CreateTypeScriptAppHostWithViteApp ▶️ View Recording
DescribeCommandResolvesReplicaNames ▶️ View Recording
DescribeCommandShowsRunningResources ▶️ View Recording
DetachFormatJsonProducesValidJson ▶️ View Recording
DoctorCommand_DetectsDeprecatedAgentConfig ▶️ View Recording
DoctorCommand_WithSslCertDir_ShowsTrusted ▶️ View Recording
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted ▶️ View Recording
LogsCommandShowsResourceLogs ▶️ View Recording
PsCommandListsRunningAppHost ▶️ View Recording
PsFormatJsonOutputsOnlyJsonToStdout ▶️ View Recording
SecretCrudOnDotNetAppHost ▶️ View Recording
SecretCrudOnTypeScriptAppHost ▶️ View Recording
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels ▶️ View Recording
StopAllAppHostsFromAppHostDirectory ▶️ View Recording
StopAllAppHostsFromUnrelatedDirectory ▶️ View Recording
StopNonInteractiveMultipleAppHostsShowsError ▶️ View Recording
StopNonInteractiveSingleAppHost ▶️ View Recording
StopWithNoRunningAppHostExitsSuccessfully ❌ Upload failed

📹 Recordings uploaded automatically from CI run #22570118178

Copilot AI review requested due to automatic review settings March 2, 2026 04:48
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

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

  • ShowStatusAsync already accepts Func<Task<T>>, so the async () => 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 ShowStatusAsync call wraps an async method using async () => 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 to ShowStatusAsync is 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 ShowStatusAsync usages wrap a Func<Task> by returning a dummy 0 to satisfy the generic Task<T> signature. Consider adding a ShowStatusAsync(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 ShowStatusAsync call returns a dummy 0 purely to fit the Func<Task<T>> signature. Consider adding a Func<Task> overload for ShowStatusAsync (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 ShowStatusAsync usage needs an unused return 0; to satisfy the generic signature. Consider adding a ShowStatusAsync(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);

@davidfowl
Copy link
Member

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

@JamesNK
Copy link
Member Author

JamesNK commented Mar 2, 2026

@davidfowl Added to templates:

create-project-status

// 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(
Copy link
Member

Choose a reason for hiding this comment

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

This flickers because its fast. I wonder if we should avoid the status if the underlying task finishes quicky.

Copy link
Member Author

Choose a reason for hiding this comment

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

Definitely. Some of these were added by AI.

I'll remove it.

@davidfowl
Copy link
Member

aspire start / run --detached, needs some status indicators

Screen.Recording.2026-03-02.at.8.06.51.AM.mov

@radical radical merged commit 3f86164 into release/13.2 Mar 2, 2026
680 of 685 checks passed
@radical radical deleted the jamesnk/command-status branch March 2, 2026 22:30
@dotnet-policy-service dotnet-policy-service bot added this to the 13.2 milestone Mar 2, 2026
mitchdenny pushed a commit that referenced this pull request Mar 5, 2026
* Display status in more places in CLI

* Update

* Update

* Update

* Update

* Add status to templates

* Fix emoji
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.

4 participants