Skip to content

Create aspire restore command and polyglot playground tests#14753

Open
sebastienros wants to merge 8 commits intorelease/13.2from
sebros/aspire-restore
Open

Create aspire restore command and polyglot playground tests#14753
sebastienros wants to merge 8 commits intorelease/13.2from
sebros/aspire-restore

Conversation

@sebastienros
Copy link
Member

Create aspire restore command to generate polyglot apps only, without requiring to either run it or add an integration.

Then using it for the playground apps validation by generating and ensuring tsc succeeds on it.

@sebastienros sebastienros requested review from Copilot and davidfowl and removed request for Copilot February 27, 2026 00:10
@github-actions
Copy link
Contributor

github-actions bot commented Feb 27, 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 -- 14753

Or

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

@github-actions
Copy link
Contributor

github-actions bot commented Feb 27, 2026

🎬 CLI E2E Test Recordings

The following terminal recordings are available for commit 0ef023b:

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
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
RestoreGeneratesSdkFiles ▶️ View Recording
SecretCrudOnDotNetAppHost ▶️ View Recording
SecretCrudOnTypeScriptAppHost ❌ Upload failed
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels ❌ Upload failed
StopAllAppHostsFromAppHostDirectory ▶️ View Recording
StopAllAppHostsFromUnrelatedDirectory ▶️ View Recording
StopNonInteractiveMultipleAppHostsShowsError ▶️ View Recording
StopNonInteractiveSingleAppHost ▶️ View Recording
StopWithNoRunningAppHostExitsSuccessfully ▶️ View Recording

📹 Recordings uploaded automatically from CI run #22526918226

Fix CLI test failures caused by missing RestoreCommand DI registration
in CliTestHelper.cs, which is needed since RootCommand now depends on it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 27, 2026 00:55
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

Adds a new aspire restore CLI command to regenerate polyglot SDK code for non-.NET AppHost projects, and introduces validation that the generated TypeScript SDK remains compilable across playground samples.

Changes:

  • Introduces aspire restore (polyglot-only) and wires it into DI and the root command when polyglot support is enabled.
  • Updates polyglot project codegen flow to return success/failure from SDK regeneration and propagates that to callers.
  • Adds E2E + CI/Docker validation to ensure TypeScript SDK generation works and TypeScript playground apps type-check with tsc.

Reviewed changes

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

Show a summary per file
File Description
tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs Registers RestoreCommand in the CLI test service collection.
tests/Aspire.Cli.EndToEnd.Tests/TypeScriptCodegenValidationTests.cs New E2E test that creates a TS AppHost, adds integrations, runs aspire restore, and validates generated SDK files.
src/Aspire.Cli/Projects/GuestAppHostProject.cs Makes SDK regeneration return bool and propagates failure to add/update flows.
src/Aspire.Cli/Program.cs Registers RestoreCommand in the production DI container.
src/Aspire.Cli/Commands/RootCommand.cs Adds restore subcommand under the polyglot feature flag gate.
src/Aspire.Cli/Commands/RestoreCommand.cs New implementation of aspire restore for guest (non-.NET) AppHosts.
.github/workflows/polyglot-validation/test-typescript-playground.sh New script to run aspire restore + tsc --noEmit across TS playground apps.
.github/workflows/polyglot-validation/Dockerfile.typescript Updates TS validation container to run the new playground validation script.
Comments suppressed due to low confidence (3)

src/Aspire.Cli/Commands/RestoreCommand.cs:46

  • RestoreCommand keeps both the base InteractionService property and a separate _interactionService field, then mixes the two. This is redundant and makes it harder to reason about which interaction service is being used (especially for extension-host scenarios). Consider removing the field and consistently using InteractionService (or consistently using the injected field) throughout the command.
    private readonly IProjectLocator _projectLocator;
    private readonly IAppHostProjectFactory _projectFactory;
    private readonly IInteractionService _interactionService;
    private readonly ILogger<RestoreCommand> _logger;

    private static readonly OptionWithLegacy<FileInfo?> s_appHostOption = new("--apphost", "--project", SharedCommandStrings.AppHostOptionDescription);

    public RestoreCommand(
        IProjectLocator projectLocator,
        IAppHostProjectFactory projectFactory,
        IFeatures features,
        ICliUpdateNotifier updateNotifier,
        CliExecutionContext executionContext,
        IInteractionService interactionService,
        ILogger<RestoreCommand> logger,
        AspireCliTelemetry telemetry)
        : base("restore", "Regenerate polyglot SDK code for a non-.NET AppHost project.", features, updateNotifier, executionContext, interactionService, telemetry)
    {
        _projectLocator = projectLocator;
        _projectFactory = projectFactory;
        _interactionService = interactionService;
        _logger = logger;

src/Aspire.Cli/Commands/RestoreCommand.cs:84

  • RestoreCommand depends on the concrete GuestAppHostProject type (and its BuildAndGenerateSdkAsync method) via a downcast. That makes the command harder to extend to other non-.NET AppHost project types and tightly couples Commands to an implementation detail. Consider introducing an interface/abstraction for “SDK restore/regeneration” (implemented by guest projects) and using that instead of the concrete cast.
            var project = _projectFactory.TryGetProject(effectiveAppHostFile);

            if (project is null)
            {
                InteractionService.DisplayError("Unrecognized app host type.");
                return ExitCodeConstants.FailedToFindProject;
            }

            if (project is not GuestAppHostProject guestProject)
            {
                InteractionService.DisplayError("The restore command is only supported for polyglot (non-.NET) AppHost projects.");
                return ExitCodeConstants.InvalidCommand;
            }

src/Aspire.Cli/Commands/RestoreCommand.cs:92

  • The ShowStatusAsync callback uses an async () => await ... wrapper. Since BuildAndGenerateSdkAsync already returns a Task<bool>, this extra async/await adds noise and can slightly obscure exception propagation; consider passing the task-returning delegate directly.
            var success = await _interactionService.ShowStatusAsync(
                ":gear:  Restoring polyglot SDK code...",
                async () => await guestProject.BuildAndGenerateSdkAsync(directory, cancellationToken));

Enable 'set -euo pipefail' and avoid piping npm install output through
tail, which masked failures. Now captures output first, checks exit
code, then displays the tail on success or more context on failure.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@davidfowl
Copy link
Member

Lets decide what this will do for .NET as well.

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