Skip to content

Fix AspireExport coverage for hosting integrations#15114

Merged
sebastienros merged 10 commits intorelease/13.2from
sebros/allexports
Mar 11, 2026
Merged

Fix AspireExport coverage for hosting integrations#15114
sebastienros merged 10 commits intorelease/13.2from
sebros/allexports

Conversation

@sebastienros
Copy link
Copy Markdown
Contributor

Description

  • enable the AspireExport analyzer from src/Directory.Build.targets for Aspire.Hosting.* projects
  • fix the analyzer diagnostics across the affected hosting integrations by adding explicit exports/ignores, DTO/resource exposure where needed, and collision-safe export IDs
  • add ATS-friendly overloads for the remaining incompatible YARP and Web PubSub polyglot surfaces
  • validate the touched projects and re-run the full hosting-project analyzer sweep, which now reports zero remaining ASPIREEXPORT diagnostics

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

Enable the AspireExport analyzer for Aspire.Hosting projects and resolve the diagnostics it reported across the affected integrations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 10, 2026 23:39
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 10, 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 -- 15114

Or

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

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 turns on the Aspire.Hosting.Analyzers (AspireExport/ATS compatibility analyzer) for all Aspire.Hosting.* projects under src/, then updates multiple hosting integrations to eliminate ASPIREEXPORT diagnostics by explicitly exporting, ignoring, or making ATS-friendly overloads/DTOs available for polyglot SDK generation.

Changes:

  • Enable Aspire.Hosting.Analyzers as an analyzer reference for Aspire.Hosting.* projects via src/Directory.Build.targets.
  • Add/adjust [AspireExport] / [AspireExportIgnore] attributes and collision-safe export IDs across hosting integrations.
  • Add ATS-friendly overloads (notably in YARP path transforms and Azure Web PubSub event handler APIs) and mark required option/model types as [AspireDto].

Reviewed changes

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

Show a summary per file
File Description
src/Directory.Build.targets Adds conditional analyzer ProjectReference so Aspire.Hosting.* projects run the AspireExport analyzer by default.
src/Aspire.Hosting.Yarp/ConfigurationBuilder/Transforms/PathTransformExtensions.cs Ignores PathString overloads for polyglot and introduces string-based ATS-friendly overloads with exports.
src/Aspire.Hosting.Python/PythonAppResourceBuilderExtensions.cs Exports WithDebugging for polyglot use.
src/Aspire.Hosting.Maui/MauiHostingExtensions.cs Marks MAUI hosting services hook as not available for polyglot ([AspireExportIgnore]).
src/Aspire.Hosting.DevTunnels/DevTunnelOptions.cs Marks DevTunnelOptions as [AspireDto] for ATS serialization.
src/Aspire.Hosting.Azure/ExistingAzureResourceExtensions.cs Adjusts export ID to be collision-safe while preserving generated method name via MethodName.
src/Aspire.Hosting.Azure/AzureUserAssignedIdentityExtensions.cs Adjusts export ID to be collision-safe while preserving generated method name via MethodName.
src/Aspire.Hosting.Azure.WebPubSub/AzureWebPubSubExtensions.cs Ignores ATS-incompatible overloads and adds an ATS-friendly exported event handler overload (no auth settings).
src/Aspire.Hosting.Azure.Network/AzureVirtualNetworkExtensions.cs Adds exports for VNet/subnet APIs and related helpers; introduces collision-safe IDs where needed.
src/Aspire.Hosting.Azure.Network/AzureSecurityRule.cs Marks AzureSecurityRule as [AspireDto] for ATS serialization.
src/Aspire.Hosting.Azure.Network/AzurePublicIPAddressExtensions.cs Exports AddPublicIPAddress for polyglot usage.
src/Aspire.Hosting.Azure.Network/AzurePrivateEndpointExtensions.cs Exports AddPrivateEndpoint for polyglot usage.
src/Aspire.Hosting.Azure.Network/AzureNetworkSecurityGroupExtensions.cs Exports NSG creation and security rule APIs.
src/Aspire.Hosting.Azure.Network/AzureNatGatewayExtensions.cs Exports NAT gateway creation and public IP association APIs.
src/Aspire.Hosting.Azure.ContainerRegistry/AzureContainerRegistryExtensions.cs Adjusts export ID for WithAzureContainerRegistry to be collision-safe.
src/Aspire.Hosting.Azure.AIFoundry/AzureAIFoundryExtensions.cs Adds exports for AI Foundry APIs and ignores ATS-incompatible overload(s) where needed.
src/Aspire.Hosting.Azure.AIFoundry/AzureAIFoundryDeploymentResource.cs Exposes deployment resource properties to ATS and ignores the non-polyglot Parent property.
src/Aspire.Hosting.Azure.AIFoundry/AIFoundryModel.cs Marks AIFoundryModel as [AspireDto] for ATS serialization.

Co-authored-by: Eric Erhardt <eric.erhardt@microsoft.com>
/// Adds the transform which sets the request path with the given value.
/// </summary>
[AspireExport("withTransformPathSet", Description = "Adds the transform which sets the request path with the given value.")]
/// <remarks>This overload is not available in polyglot app hosts. Use the string-based overload instead.</remarks>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think these remarks provide any value since it doesn't apply to C# and the AspireExportIgnore won't expose them in other languages.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We decided to remove them once we have a story for polyglot documentation

sebastienros and others added 3 commits March 10, 2026 17:08
Exclude helper Aspire.Hosting projects from the shared analyzer wiring so AppHostAnalyzer only runs on the intended integration-style projects.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This reverts commit 173298d.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Make AppHostAnalyzer skip model-name analysis when Aspire.Hosting model-name types are unavailable, and add a regression test covering projects without the Aspire.Hosting reference.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
sebastienros and others added 2 commits March 11, 2026 08:26
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

github-actions bot commented Mar 11, 2026

🎬 CLI E2E Test Recordings

The following terminal recordings are available for commit 476a1bf:

Test Recording
AddPackageInteractiveWhileAppHostRunningDetached ▶️ View Recording
AddPackageWhileAppHostRunningDetached ▶️ View Recording
AgentCommands_AllHelpOutputs_AreCorrect ▶️ View Recording
AgentInitCommand_DefaultSelection_InstallsSkillOnly ▶️ View Recording
AgentInitCommand_MigratesDeprecatedConfig ▶️ View Recording
AspireAddPackageVersionToDirectoryPackagesProps ▶️ 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
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
RunWithMissingAwaitShowsHelpfulError ▶️ View Recording
SecretCrudOnDotNetAppHost ❌ Upload failed
SecretCrudOnTypeScriptAppHost ❌ Upload failed
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels ❌ Upload failed
StopAllAppHostsFromAppHostDirectory ❌ Upload failed
StopAllAppHostsFromUnrelatedDirectory ❌ Upload failed
StopNonInteractiveMultipleAppHostsShowsError ▶️ View Recording
StopNonInteractiveSingleAppHost ▶️ View Recording
StopWithNoRunningAppHostExitsSuccessfully ▶️ View Recording
TypeScriptAppHostWithProjectReferenceIntegration ▶️ View Recording

📹 Recordings uploaded automatically from CI run #22967699685

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
/// <param name="endpoint">The endpoint target for this cluster.</param>
/// <returns></returns>
/// <remarks>This overload is not available in polyglot app hosts. Use the <c>addClusterFromEndpoint</c> helper instead.</remarks>
[AspireExportIgnore(Reason = "Use the explicit static export to avoid AddCluster capability ID collisions in polyglot app hosts.")]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Would it make sense to not ExposeMethods and just use the extensions for everything?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Outdated

/// <param name="builder">The builder instance.</param>
/// <param name="cluster">The target cluster for this route.</param>
/// <returns></returns>
public static YarpRoute AddRoute(this IYarpConfigurationBuilder builder, YarpCluster cluster)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why aren't we exposing the rest of these methods?

IMethodSymbol targetMethod,
[NotNullWhen(true)] out (IParameterSymbol ModelNameParameter, ModelType[] ModelTypes)[]? parameterData)
{
if (!wellKnownTypes.TryGet(WellKnownTypeData.WellKnownType.Aspire_Hosting_ApplicationModel_IModelNameParameter, out var modelNameParameter) ||
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

When is this analyzer used, but these types can't be found?

/// <param name="builder">The builder instance.</param>
/// <param name="cluster">The target cluster for this route.</param>
/// <returns></returns>
public static YarpRoute AddRoute(this IYarpConfigurationBuilder builder, YarpCluster cluster)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why isn't the analyzer flagging these methods?

sebastienros and others added 2 commits March 11, 2026 10:47
Refresh the YARP validation playground to use the exported helper surface and update code generation snapshots for the current exported APIs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
/// <param name="builder">The builder instance.</param>
/// <param name="resource">The resource target for this cluster.</param>
/// <returns>The created cluster.</returns>
[AspireExport("addClusterFromResource", MethodName = "addCluster", Description = "Adds a YARP cluster for a resource that supports service discovery.")]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why is this one have a MethodName?

@sebastienros sebastienros merged commit 83ff268 into release/13.2 Mar 11, 2026
498 of 501 checks passed
@sebastienros sebastienros deleted the sebros/allexports branch March 11, 2026 19:24
@dotnet-policy-service dotnet-policy-service bot added this to the 13.2 milestone Mar 11, 2026
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.

3 participants