Skip to content

Expose Blazor gateway and Dockerfile factory APIs to ATS#17420

Merged
sebastienros merged 4 commits into
mainfrom
sebros/implement-ats-polyglot-apis
May 25, 2026
Merged

Expose Blazor gateway and Dockerfile factory APIs to ATS#17420
sebastienros merged 4 commits into
mainfrom
sebros/implement-ats-polyglot-apis

Conversation

@sebastienros
Copy link
Copy Markdown
Contributor

Description

Adds ATS/polyglot AppHost coverage for a subset of APIs identified in the issue #17049 playground audit. Scope is intentionally restricted to exposing existing public C# APIs to ATS — no new public API surface is invented. Other audit candidates (Kusto WithControlCommand, YARP WithConfigFile, Foundry/Kubernetes gaps) were investigated but did not have an existing public counterpart that could be exposed without introducing new API surface, so they are deferred.

Source changes

  • Aspire.Hosting.Blazor: tag the existing public AddBlazorGateway, WithBlazorClientApp, and AddBlazorWasmApp (exported as addBlazorWasmProject) with [AspireExport]. AddBlazorWasmApp also gains [ResourceName] on its name parameter so ATS-generated SDKs honor naming conventions.
  • Aspire.Hosting: add internal WithDockerfileFactoryForPolyglot / AddDockerfileFactoryForPolyglot shims tagged [AspireExport]. These wrap the existing public WithDockerfileFactory / AddDockerfileFactory methods, whose signature takes Func<DockerfileFactoryContext, Task<string>>DockerfileFactoryContext exposes .NET-only types (IServiceProvider, IResource) and is not ATS-conventional, so the shims expose a parameterless Func<Task<string>> callback shape that polyglot callers can implement.

Polyglot validation

Each newly exported API is exercised across all four polyglot languages, with fixtures arranged 1:1 against the source changes:

  • tests/PolyglotAppHosts/Aspire.Hosting.Blazor/{Go,Java,Python,TypeScript} — new fixture tree covering addBlazorGateway, withBlazorClientApp, and addBlazorWasmProject.
  • tests/PolyglotAppHosts/Aspire.Hosting/{Go,Java,Python,TypeScript}withDockerfileFactory / addDockerfileFactory usage validation.

Per-language fixture builds (tsc --noEmit, javac --enable-preview --source 25, go build, Python compile) were validated locally against a regenerated ATS SDK during development. dotnet build of Aspire.Hosting and Aspire.Hosting.Blazor succeeds with 0 warnings and 0 errors.

Fixes # (issue)

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

Adds ATS/polyglot AppHost coverage for APIs identified in the issue
#17049 playground audit, restricted to existing public C# APIs:

- Aspire.Hosting.Blazor: tag existing public AddBlazorGateway,
  WithBlazorClientApp, and AddBlazorWasmApp (exported as
  addBlazorWasmProject) with [AspireExport]. AddBlazorWasmApp also
  gains [ResourceName] on its name parameter.

- Aspire.Hosting: add internal WithDockerfileFactoryForPolyglot and
  AddDockerfileFactoryForPolyglot shims tagged [AspireExport] that
  wrap the existing public WithDockerfileFactory/AddDockerfileFactory
  methods. The existing public signature takes
  Func<DockerfileFactoryContext, Task<string>>, which exposes .NET-only
  types and is not ATS-conventional, so the shims expose a
  parameterless Func<Task<string>> callback shape instead.

Polyglot AppHost fixtures exercise each newly exported export across
all four supported languages (Go, Java, Python, TypeScript):

- tests/PolyglotAppHosts/Aspire.Hosting.Blazor/{Go,Java,Python,TypeScript}
- tests/PolyglotAppHosts/Aspire.Hosting/{Go,Java,Python,TypeScript}
  (Dockerfile factory usage)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 24, 2026 00:21
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 24, 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/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 17420

Or

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

Copy link
Copy Markdown
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

This PR expands Aspire Type System (ATS) / polyglot AppHost coverage by exporting existing Blazor gateway APIs and by introducing ATS-exportable shims for Dockerfile factory APIs whose original .NET callback context isn’t polyglot-friendly. It also adds new polyglot fixtures across Go/Java/Python/TypeScript to validate the newly exported surface.

Changes:

  • Export Blazor gateway and WASM project APIs to ATS (including applying [ResourceName] where needed for naming conventions).
  • Add internal ATS-exported shims for addDockerfileFactory / withDockerfileFactory that use a polyglot-friendly Func<Task<string>> callback shape.
  • Add/update polyglot AppHost fixtures to exercise the exported APIs across supported languages.

Reviewed changes

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

Show a summary per file
File Description
tests/PolyglotAppHosts/Aspire.Hosting/TypeScript/apphost.mts Adds TypeScript fixture usage of addDockerfileFactory / withDockerfileFactory.
tests/PolyglotAppHosts/Aspire.Hosting/Python/apphost.py Adds Python fixture usage of add_dockerfile_factory / with_dockerfile_factory.
tests/PolyglotAppHosts/Aspire.Hosting/Java/AppHost.java Adds Java fixture usage of addDockerfileFactory / withDockerfileFactory.
tests/PolyglotAppHosts/Aspire.Hosting/Go/apphost.go Adds Go fixture usage of AddDockerfileFactory / WithDockerfileFactory.
tests/PolyglotAppHosts/Aspire.Hosting.Blazor/TypeScript/tsconfig.json New TS config for Blazor polyglot fixture compilation.
tests/PolyglotAppHosts/Aspire.Hosting.Blazor/TypeScript/package.json New TS package setup for Blazor polyglot fixture compilation.
tests/PolyglotAppHosts/Aspire.Hosting.Blazor/TypeScript/aspire.config.json New TS Aspire config referencing Aspire.Hosting.Blazor.
tests/PolyglotAppHosts/Aspire.Hosting.Blazor/TypeScript/apphost.mts New TypeScript Blazor fixture exercising gateway + WASM project APIs.
tests/PolyglotAppHosts/Aspire.Hosting.Blazor/Python/pylock.apphost.toml New Python lock metadata for Blazor polyglot fixture.
tests/PolyglotAppHosts/Aspire.Hosting.Blazor/Python/aspire.config.json New Python Aspire config referencing Aspire.Hosting.Blazor.
tests/PolyglotAppHosts/Aspire.Hosting.Blazor/Python/apphost.py New Python Blazor fixture exercising gateway + WASM project APIs.
tests/PolyglotAppHosts/Aspire.Hosting.Blazor/Python/apphost_requirements.txt New fallback pip requirements file for Python Blazor fixture.
tests/PolyglotAppHosts/Aspire.Hosting.Blazor/Java/aspire.config.json New Java Aspire config (enables experimental polyglot Java) referencing Aspire.Hosting.Blazor.
tests/PolyglotAppHosts/Aspire.Hosting.Blazor/Java/AppHost.java New Java Blazor fixture exercising gateway + WASM project APIs.
tests/PolyglotAppHosts/Aspire.Hosting.Blazor/Go/go.mod New Go module file for Blazor polyglot fixture.
tests/PolyglotAppHosts/Aspire.Hosting.Blazor/Go/aspire.config.json New Go Aspire config referencing Aspire.Hosting.Blazor.
tests/PolyglotAppHosts/Aspire.Hosting.Blazor/Go/apphost.go New Go Blazor fixture exercising gateway + WASM project APIs.
src/Aspire.Hosting/ContainerResourceBuilderExtensions.cs Adds ATS-exported internal Dockerfile factory shims for polyglot callbacks.
src/Aspire.Hosting.Blazor/Resources/BlazorWasmAppResource.cs Exports BlazorWasmAppResource to ATS (suppresses experimental warning).
src/Aspire.Hosting.Blazor/BlazorGatewayExtensions.cs Exports Blazor gateway APIs and applies [ResourceName] where needed.

Comment thread src/Aspire.Hosting/ContainerResourceBuilderExtensions.cs Outdated
sebastienros and others added 3 commits May 23, 2026 17:29
Drops the internal *ForPolyglot shims in favor of exporting the
existing public WithDockerfileFactory<T> and AddDockerfileFactory
async overloads directly via [AspireExport].

DockerfileFactoryContext is now [AspireExport]-tagged at the class
level with its Resource property exposed to polyglot callers; the
.NET-only Services (IServiceProvider) and CancellationToken stay
unexported. This mirrors how EnvironmentCallbackContext is exposed
to polyglot hosts. The synchronous Func<DockerfileFactoryContext,
string> overloads remain ignored with the same reason used elsewhere
(polyglot uses the async overload).

Polyglot fixtures in tests/PolyglotAppHosts/Aspire.Hosting/{Go,Java,
Python,TypeScript} are updated to use the new context-receiving
callback signature.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The newly [AspireExport]-ed WithDockerfileFactory/AddDockerfileFactory APIs
and the DockerfileFactoryContext type cause the polyglot generators to emit
additional capability bindings. Refresh the affected Verify snapshots so the
Hosting.CodeGeneration.{Go,Java,Python,Rust,TypeScript} test jobs pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

CLI E2E Tests unknown — 96 passed, 0 failed, 5 unknown (commit dc50fe1)

View all recordings
Status Test Recording
AddPackageInteractiveWhileAppHostRunningDetached ▶️ View recording
AddPackageWhileAppHostRunningDetached ▶️ View recording
AgentCommands_AllHelpOutputs_AreCorrect ▶️ View recording
AgentInitCommand_DefaultSelection_InstallsDefaultSkills ▶️ View recording
AgentInitCommand_MigratesDeprecatedConfig ▶️ View recording
AgentMcpListStructuredLogsFromStarterAppCore ▶️ View recording
AllPublishMethodsBuildDockerImages ▶️ View recording
AspireAddPackageVersionToDirectoryPackagesProps ▶️ View recording
AspireInitSingleFileAppHostRunsViaDotnetRunAppHost ▶️ View recording
AspireInitWithExistingAppHostDirRecreatesMissingNuGetConfigAndPreservesFiles ▶️ View recording
AspireInitWithSolutionFileGeneratesAppHostThatBuildsAgainstChannelHive ▶️ View recording
AspireStartUpdatesStaleTypeScriptAppHostPath ▶️ View recording
AspireUpdateRemovesAppHostPackageVersionFromDirectoryPackagesProps ▶️ View recording
AspireUpdateRemovesOrphanAppHostPackageVersionWhenSdkAlreadyCurrent ▶️ View recording
Banner_DisplayedOnFirstRun ▶️ View recording
Banner_DisplayedWithExplicitFlag ▶️ View recording
Banner_NotDisplayedWithNoLogoFlag ▶️ View recording
CertificatesClean_RemovesCertificates ▶️ View recording
CertificatesTrust_WithNoCert_CreatesAndTrustsCertificate ▶️ View recording
CertificatesTrust_WithUntrustedCert_TrustsCertificate ▶️ View recording
ConfigSetGet_CreatesNestedJsonFormat ▶️ View recording
CreateAndRunAspireStarterProject ▶️ View recording
CreateAndRunAspireStarterProjectWithBundle ▶️ View recording
CreateAndRunEmptyAppHostProject ▶️ View recording
CreateAndRunJavaEmptyAppHostProject ▶️ View recording
CreateAndRunJsReactProject ▶️ View recording
CreateAndRunPythonReactProject ▶️ View recording
CreateAndRunTypeScriptEmptyAppHostProject ▶️ View recording
CreateAndRunTypeScriptStarterProject ▶️ View recording
CreateJavaAppHostWithViteApp ▶️ View recording
CreateTypeScriptAppHostWithViteApp_UsesConfiguredToolchain ▶️ View recording
DashboardRunWithAgentMcpCore ▶️ View recording
DashboardRunWithOtelTracesReturnsNoTracesCore ▶️ View recording
DeployK8sBasicApiService ▶️ View recording
DeployK8sWithExternalHelmChart ▶️ View recording
DeployK8sWithGarnet ▶️ View recording
DeployK8sWithMongoDB ▶️ View recording
DeployK8sWithMySql ▶️ View recording
DeployK8sWithPostgres ▶️ View recording
DeployK8sWithRabbitMQ ▶️ View recording
DeployK8sWithRedis ▶️ View recording
DeployK8sWithSqlServer ▶️ View recording
DeployK8sWithValkey ▶️ View recording
DeployTypeScriptAppToKubernetes ▶️ View recording
DescribeCommandResolvesReplicaNames ▶️ View recording
DescribeCommandShowsRunningResources ▶️ View recording
DetachFormatJsonProducesValidJson ▶️ View recording
DetachFormatJsonProducesValidJsonWhenRestartingExistingInstance ▶️ View recording
DoListStepsShowsPipelineSteps ▶️ View recording
DocsCommand_RendersInteractiveMarkdownFromLocalSource ▶️ View recording
DoctorCommand_DetectsDeprecatedAgentConfig ▶️ View recording
DoctorCommand_TypeScriptAppHostReportsMissingConfiguredToolchain ▶️ View recording
DoctorCommand_WithSslCertDir_ShowsTrusted ▶️ View recording
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted ▶️ View recording
GeneratedAspireDevScript_StartsWatchMode_WithConfiguredToolchain ▶️ View recording
GlobalMigration_HandlesCommentsAndTrailingCommas ▶️ View recording
GlobalMigration_HandlesMalformedLegacyJson ▶️ View recording
GlobalMigration_PreservesAllValueTypes ▶️ View recording
GlobalMigration_SkipsWhenNewConfigExists ▶️ View recording
GlobalSettings_MigratedFromLegacyFormat ▶️ View recording
InitTypeScriptAppHost_AugmentsExistingViteRepoAtRoot ▶️ View recording
InteractiveCSharpInitCreatesExpectedFiles ▶️ View recording
InvalidAppHostPathWithComments_IsHealedOnRun ▶️ View recording
JavaScriptHostingApisRunFromTypeScriptAppHost ▶️ View recording
LatestCliCanStartStableChannelAppHost ▶️ View recording
LatestCliCanStartStableChannelTypeScriptAppHost ▶️ View recording
LegacySettingsMigration_AdjustsRelativeAppHostPath ▶️ View recording
LogLevelTrace_ProducesTraceEntriesInCliLogFile ▶️ View recording
LogsCommandShowsResourceLogs ▶️ View recording
OtelLogsReturnsStructuredLogsFromStarterApp ▶️ View recording
OtelLogsReturnsStructuredLogsFromStarterAppIsolated ▶️ View recording
PsCommandListsRunningAppHost ▶️ View recording
PsFormatJsonOutputsOnlyJsonToStdout ▶️ View recording
PublishJavaScriptPatternsGeneratesExpectedDockerComposeArtifacts ▶️ View recording
PublishWithConfigureEnvFileUpdatesEnvOutput ▶️ View recording
PublishWithDockerComposeServiceCallbackSucceeds ▶️ View recording
PublishWithoutOutputPathUsesAppHostDirectoryDefault ▶️ View recording
ResourceCommand_FailedExecution_DisplaysAppHostLogPathAndLogContainsEntries ▶️ View recording
ResourceCommand_FailsWhenInteractionServiceIsRequired ▶️ View recording
ResourceCommand_SetAndDeleteParameterUpdatesDescribeOutput ▶️ View recording
RestoreGeneratesSdkFiles ▶️ View recording
RestoreGeneratesSdkFiles_WithConfiguredToolchain ▶️ View recording
RestoreRefreshesGeneratedSdkAfterAddingIntegration ▶️ View recording
RestoreSupportsConfigOnlyHelperPackageAndCrossPackageTypes ▶️ View recording
RunFromParentDirectory_UsesExistingConfigNearAppHost ▶️ View recording
RunPublishFailureScenarioAsync ▶️ View recording
RunReportsSyntaxErrorsForDotNetAppHost ▶️ View recording
RunReportsSyntaxErrorsForTypeScriptAppHost ▶️ View recording
SecretCrudOnDotNetAppHost ▶️ View recording
SecretCrudOnTypeScriptAppHost ▶️ View recording
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels ▶️ View recording
StartAndWaitForTypeScriptSqlServerAppHostWithNativeAssets ▶️ View recording
StartReportsSyntaxErrorsForDotNetAppHost ▶️ View recording
StartReportsSyntaxErrorsForTypeScriptAppHost ▶️ View recording
StopAllAppHostsFromAppHostDirectory ▶️ View recording
StopJavaPolyglotAppHostUsingApphostDirectory ▶️ View recording
StopNonInteractiveSingleAppHost ▶️ View recording
StopTypeScriptPolyglotAppHostUsingApphostDirectory ▶️ View recording
StopWithNoRunningAppHostExitsSuccessfully ▶️ View recording
UnAwaitedChainsCompileWithAutoResolvePromises ▶️ View recording
UpdateProjectChannelToStable_TypeScript_PicksUpStablePackages ▶️ View recording

📹 Recordings uploaded automatically from CI run #26347971530

@davidfowl
Copy link
Copy Markdown
Contributor

Where's the pr-testing report?

@mitchdenny
Copy link
Copy Markdown
Member

PR Testing Report (dogfood + codegen)

Result: ✅ Verified

CLI version check

  • Installed from dogfood comment: 13.4.0-pr.17420.gdc50fe14 — matches PR head dc50fe14.

Scenario 1 — Codegen unit tests (5 ATS languages)

All 187 tests passed, including TwoPassScanningGeneratedAspire and HostingContainerResourceCapabilities which directly exercise the new [AspireExport] surface.

Project Passed Duration
Go.Tests 23/23 5.4s
Java.Tests 23/23 5.6s
Python.Tests 22/22 4.7s
Rust.Tests 23/23 4.2s
TypeScript.Tests 96/96 9.9s

Scenario 2 — PR CLI dogfood smoke test

  • aspire new aspire-empty --language csharp → project created, apphost.cs references Aspire.AppHost.Sdk@13.4.0-pr.17420.gdc50fe14
  • aspire run → AppHost built, dashboard came up on https://localhost:17281, clean shutdown ✅

Notes for the author

  1. PR description vs. code mismatch. The description says internal WithDockerfileFactoryForPolyglot / AddDockerfileFactoryForPolyglot shims were added that expose a parameterless Func<Task<string>> to polyglot callers. The actual diff in src/Aspire.Hosting/ContainerResourceBuilderExtensions.cs just flips [AspireExportIgnore][AspireExport] on the existing public Func<DockerfileFactoryContext, Task<string>> overloads (plus [AspireExport] on DockerfileFactoryContext / .Resource). Polyglot callbacks therefore receive the full DockerfileFactoryContext — matching the fixtures in tests/PolyglotAppHosts/Aspire.Hosting/{Go,Java,Python,TypeScript} — not the shape described in the PR body. Worth updating the description before merge.

  2. No aspire-starter (C#) template in the PR hive. Only aspire-ts-starter, aspire-empty, aspire-ts-empty, aspire-py-starter were listed. Appears unrelated to this PR but flagging it in case it's unexpected.

Tested locally on macOS via pr-testing skill.

@sebastienros sebastienros merged commit 7b915a0 into main May 25, 2026
311 checks passed
@sebastienros sebastienros deleted the sebros/implement-ats-polyglot-apis branch May 25, 2026 02:35
@microsoft-github-policy-service microsoft-github-policy-service Bot added this to the 13.4 milestone May 25, 2026
@github-actions github-actions Bot added this to the 13.4 milestone May 25, 2026
aspire-repo-bot Bot added a commit to microsoft/aspire.dev that referenced this pull request May 25, 2026
Document the newly polyglot-exported APIs from microsoft/aspire#17420:

- Add Blazor hosting integration page (integrations/dotnet/blazor-hosting.mdx)
  covering AddBlazorGateway, WithBlazorClientApp, and AddBlazorWasmProject
  with C# and TypeScript code examples
- Update app-host/withdockerfile.mdx to add a 'Generate a Dockerfile with a
  factory function' section covering AddDockerfileFactory / WithDockerfileFactory
  with C# and TypeScript examples
- Add Blazor hosting entry to the integrations sidebar

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@aspire-repo-bot
Copy link
Copy Markdown
Contributor

Pull request created: #1061

Generated by PR Documentation Check

@aspire-repo-bot
Copy link
Copy Markdown
Contributor

📝 Documentation has been drafted in microsoft/aspire.dev#1061 targeting release/13.4.

A draft documentation PR has been opened on microsoft/aspire.dev targeting release/13.4 to document the new polyglot AppHost APIs introduced by this PR:

  • New page integrations/dotnet/blazor-hosting: documents AddBlazorWasmProject, AddBlazorGateway, and WithBlazorClientApp with C# and TypeScript examples.
  • Updated page app-host/withdockerfile: adds a "Generate a Dockerfile with a factory function" section for AddDockerfileFactory / WithDockerfileFactory with C# and TypeScript examples.
  • Sidebar: adds "Blazor hosting" entry to the .NET integrations section.

Triggered signal: pr_body_has_cli_flag_mention (false positive — PR body mentions tsc --noEmit and javac --enable-preview --source 25 as build validation commands, not Aspire CLI flags). The change is user-facing because it exposes addBlazorGateway, addBlazorWasmProject, addDockerfileFactory, and related factory APIs to TypeScript/Go/Java/Python polyglot AppHosts for the first time.

Note

This draft PR needs human review before merging.

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