[Automated] Update API Surface Area - #17846
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 17846Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 17846" |
|
❓ CLI E2E Tests unknown — 110 passed, 0 failed, 2 unknown (commit View all recordings
📹 Recordings uploaded automatically from CI run #26838658119 |
fe197aa to
ac810bc
Compare
cfe8b79 to
346b8cc
Compare
fe5a901 to
84fffd3
Compare
84fffd3 to
b8f9bdf
Compare
e88df30 to
641f06c
Compare
641f06c to
08720bf
Compare
08720bf to
f6dcb52
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (6)
src/Aspire.Hosting/api/Aspire.Hosting.cs:633
- The
Experimental(\"ASPIREINTERACTION001\")marker appears to have been removed from theIInteractionServicetype and many related interaction types, but is still applied toPromptProgressAsync(and some new progress types). This creates inconsistent analyzer behavior where older interaction APIs may become implicitly non-experimental while new ones remain experimental. If the interaction surface is intended to remain experimental, re-apply the attribute at the interface/type level (or consistently on all relevant members); if it’s intended to be stable now, remove the experimental marker from the newly added progress APIs to match.
public partial interface IInteractionService
{
bool IsAvailable { get; }
src/Aspire.Hosting/api/Aspire.Hosting.cs:643
- The
Experimental(\"ASPIREINTERACTION001\")marker appears to have been removed from theIInteractionServicetype and many related interaction types, but is still applied toPromptProgressAsync(and some new progress types). This creates inconsistent analyzer behavior where older interaction APIs may become implicitly non-experimental while new ones remain experimental. If the interaction surface is intended to remain experimental, re-apply the attribute at the interface/type level (or consistently on all relevant members); if it’s intended to be stable now, remove the experimental marker from the newly added progress APIs to match.
[System.Diagnostics.CodeAnalysis.Experimental("ASPIREINTERACTION001", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")]
System.Threading.Tasks.Task<InteractionResult<bool>> PromptProgressAsync(string message, string? title = null, ProgressInteractionOptions? options = null, System.Threading.CancellationToken cancellationToken = default);
}
src/Aspire.Hosting/api/Aspire.Hosting.cs:157
- The
[AspireExportIgnore]reason states thatContainerFileSystemCallbackContexthas factory methods (createFile/createDirectory/createCertificateFile), but in this API file theContainerFileSystemCallbackContexttype (as shown later in the diff) only contains properties and no such factory methods. If those factory methods don’t exist on the public context type, the reason string should be updated to avoid referencing non-existent API; if they do exist, they should appear on the exported surface (or the reason should reference the correct type that provides them).
[AspireExportIgnore(Reason = "Exposed to ATS via the WithContainerFilesCallbackExport shim, which accepts integer file-mode options and lets polyglot callbacks build the IEnumerable<ContainerFileSystemItem> result through ContainerFileSystemCallbackContext factory methods (createFile/createDirectory/createCertificateFile).")]
public static ApplicationModel.IResourceBuilder<T> WithContainerFiles<T>(this ApplicationModel.IResourceBuilder<T> builder, string destinationPath, System.Func<ApplicationModel.ContainerFileSystemCallbackContext, System.Threading.CancellationToken, System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<ApplicationModel.ContainerFileSystemItem>>> callback, int? defaultOwner = null, int? defaultGroup = null, System.IO.UnixFileMode? umask = null)
src/Aspire.Hosting.Foundry/api/Aspire.Hosting.Foundry.cs:105
- The ignore reason on the convenience overload says 'polyglot hosts must pass protocol and version explicitly', but the overload that does accept
protocolandprotocolVersionis also marked[AspireExportIgnore]in this diff hunk. If polyglot hosts are expected to be able to specify protocol/version via an exported API, consider exporting an ATS-friendly overload (or adjusting the reason text to reflect the actual supported polyglot entry point, e.g., the exported DTO/dispatcher shape).
public static ApplicationModel.IResourceBuilder<T> AsHostedAgent<T>(this ApplicationModel.IResourceBuilder<T> builder, ApplicationModel.IResourceBuilder<Foundry.AzureCognitiveServicesProjectResource>? project, Foundry.HostedAgentProtocol protocol, string protocolVersion, System.Action<Foundry.HostedAgentConfiguration>? configure = null)
where T : ApplicationModel.IResourceWithEndpoints, ApplicationModel.IResourceWithEnvironment, ApplicationModel.IComputeResource { throw null; }
[AspireExportIgnore(Reason = "C# convenience overload; polyglot hosts must pass protocol and version explicitly.")]
public static ApplicationModel.IResourceBuilder<T> AsHostedAgent<T>(this ApplicationModel.IResourceBuilder<T> builder, ApplicationModel.IResourceBuilder<Foundry.AzureCognitiveServicesProjectResource>? project, System.Action<Foundry.HostedAgentConfiguration>? configure = null)
where T : ApplicationModel.IResourceWithEndpoints, ApplicationModel.IResourceWithEnvironment, ApplicationModel.IComputeResource { throw null; }
src/Aspire.Hosting/api/Aspire.Hosting.cs:688
- Introducing a public
FilePathonInteractionFilerisks unintentionally exposing server-local filesystem paths (e.g., in logs/telemetry or UI rendering), which can leak sensitive environment details. Consider avoiding the raw path in the public API (e.g., make it internal, or expose a safer identifier +OpenRead()/ReadAllBytesAsync()only), or at minimum explicitly document thatFilePathis server-local and should not be surfaced to untrusted clients.
public sealed partial class InteractionFile
{
internal InteractionFile() { }
public string FilePath { get { throw null; } }
src/Aspire.Hosting/api/Aspire.Hosting.cs:694
- Introducing a public
FilePathonInteractionFilerisks unintentionally exposing server-local filesystem paths (e.g., in logs/telemetry or UI rendering), which can leak sensitive environment details. Consider avoiding the raw path in the public API (e.g., make it internal, or expose a safer identifier +OpenRead()/ReadAllBytesAsync()only), or at minimum explicitly document thatFilePathis server-local and should not be surfaced to untrusted clients.
public System.IO.Stream OpenRead() { throw null; }
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (3)
src/Aspire.Hosting/api/Aspire.Hosting.cs:667
- With
AspireExport(ExposeProperties = true)onInputsDialogValidationContext, theServicesproperty will be part of the exported surface. Since it is typed asIServiceProvider(a runtime .NET type), this appears to reintroduce the exact ATS/polyglot incompatibility that the previously-presentAspireExportIgnorecomment indicated. Consider restoring[AspireExportIgnore]forServices(or replacing it with an ATS-safe abstraction) so the exported surface remains representable.
[AspireExport(ExposeProperties = true)]
public sealed partial class InputsDialogValidationContext
{
src/Aspire.Hosting/api/Aspire.Hosting.cs:672
- With
AspireExport(ExposeProperties = true)onInputsDialogValidationContext, theServicesproperty will be part of the exported surface. Since it is typed asIServiceProvider(a runtime .NET type), this appears to reintroduce the exact ATS/polyglot incompatibility that the previously-presentAspireExportIgnorecomment indicated. Consider restoring[AspireExportIgnore]forServices(or replacing it with an ATS-safe abstraction) so the exported surface remains representable.
public required System.IServiceProvider Services { get { throw null; } init { } }
src/Aspire.Hosting/api/Aspire.Hosting.cs:1910
- Marking
ContainerBuildOptionsCallbackContextwithAspireExport(ExposeProperties = true)risks exporting members that are inherently .NET-runtime-specific (IResource,IServiceProvider,ILogger, etc.). This conflicts with the earlier rationale for ignoring similar APIs for ATS. A safer approach is to avoidExposeProperties = truehere and instead explicitly export only ATS-safe properties/methods (and/or addAspireExportIgnoreto runtime-typed members).
[System.Diagnostics.CodeAnalysis.Experimental("ASPIREPIPELINES003", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")]
[AspireExport(ExposeProperties = true)]
public sealed partial class ContainerBuildOptionsCallbackContext
{
public ContainerBuildOptionsCallbackContext(IResource resource, System.IServiceProvider services, Microsoft.Extensions.Logging.ILogger logger, System.Threading.CancellationToken cancellationToken, DistributedApplicationExecutionContext executionContext) { }
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated no new comments.
Suppressed comments (8)
src/Aspire.Hosting/api/Aspire.Hosting.cs:1
- These contexts now expose both
ServiceProvider(obsolete) andServicesbut the obsolete alias isn’t marked withAspireExportIgnore(unlikeExecuteCommandContext.ServiceProvider). If these contexts are part of the exported polyglot surface, this likely results in duplicated/ambiguous service-provider bindings. Recommend consistently applyingAspireExportIgnoreto the obsoleteServiceProvideraliases so polyglot consumers only seeServices.
//------------------------------------------------------------------------------
src/Aspire.Hosting/api/Aspire.Hosting.cs:2867
- These contexts now expose both
ServiceProvider(obsolete) andServicesbut the obsolete alias isn’t marked withAspireExportIgnore(unlikeExecuteCommandContext.ServiceProvider). If these contexts are part of the exported polyglot surface, this likely results in duplicated/ambiguous service-provider bindings. Recommend consistently applyingAspireExportIgnoreto the obsoleteServiceProvideraliases so polyglot consumers only seeServices.
[System.Obsolete("Use Services instead.")]
public System.IServiceProvider ServiceProvider { get { throw null; } init { } }
public required System.IServiceProvider Services { get { throw null; } init { } }
}
public sealed partial class HttpCommandResultContext
{
public InteractionInputCollection Arguments { get { throw null; } init { } }
public required System.Threading.CancellationToken CancellationToken { get { throw null; } init { } }
public required EndpointReference Endpoint { get { throw null; } init { } }
src/Aspire.Hosting/api/Aspire.Hosting.cs:2004
- In an
[AspireExport]surface, keeping bothServiceProvider(obsolete) andServicesrisks exporting two equivalent service-provider properties to polyglot/ATS consumers, creating ambiguity and extra surface area. Consider addingAspireExportIgnoreto the obsoleteServiceProvideralias (while keeping it for C# source compatibility) soServicesis the single exported entry point.
[AspireExport]
public sealed partial class ContainerFileSystemCallbackContext
{
[System.Diagnostics.CodeAnalysis.Experimental("ASPIRECERTIFICATES001", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")]
[AspireExportIgnore(Reason = "HttpsCertificateContext is an experimental certificate-specific type that is not yet part of the ATS surface.")]
public ContainerFileSystemCallbackHttpsCertificateContext? HttpsCertificateContext { get { throw null; } set { } }
[AspireExport]
public required IResource Model { get { throw null; } init { } }
[System.Obsolete("Use Services instead.")]
public System.IServiceProvider ServiceProvider { get { throw null; } init { } }
[AspireExport]
public required System.IServiceProvider Services { get { throw null; } init { } }
src/Aspire.Hosting/api/Aspire.Hosting.cs:2877
- These contexts now expose both
ServiceProvider(obsolete) andServicesbut the obsolete alias isn’t marked withAspireExportIgnore(unlikeExecuteCommandContext.ServiceProvider). If these contexts are part of the exported polyglot surface, this likely results in duplicated/ambiguous service-provider bindings. Recommend consistently applyingAspireExportIgnoreto the obsoleteServiceProvideraliases so polyglot consumers only seeServices.
public required System.Net.Http.HttpResponseMessage Response { get { throw null; } init { } }
[System.Obsolete("Use Services instead.")]
public System.IServiceProvider ServiceProvider { get { throw null; } init { } }
public required System.IServiceProvider Services { get { throw null; } init { } }
src/Aspire.Hosting/api/Aspire.Hosting.cs:3525
- As with other callback contexts, consider marking the obsolete
ServiceProvideralias withAspireExportIgnoreto avoid exporting bothserviceProviderandservicesto polyglot consumers. This keeps the polyglot contract smaller and reduces confusion while retaining C# compatibility via the obsolete property.
public InteractionInputCollection Arguments { get { throw null; } init { } }
public required System.Threading.CancellationToken CancellationToken { get { throw null; } init { } }
src/Aspire.Hosting/api/Aspire.Hosting.cs:3539
- As with other callback contexts, consider marking the obsolete
ServiceProvideralias withAspireExportIgnoreto avoid exporting bothserviceProviderandservicesto polyglot consumers. This keeps the polyglot contract smaller and reduces confusion while retaining C# compatibility via the obsolete property.
public required string ResourceName { get { throw null; } init { } }
[System.Obsolete("Use Services instead.")]
public System.IServiceProvider ServiceProvider { get { throw null; } init { } }
public required System.IServiceProvider Services { get { throw null; } init { } }
src/Aspire.Hosting/api/Aspire.Hosting.cs:700
- Exposing a server-local
FilePathon a publicly returned interaction result object can unintentionally leak internal filesystem details (absolute paths, usernames, directory structure) to consumers and logs. If callers only need to read file contents, consider removingFilePathfrom the public surface (or making it non-sensitive, e.g., a display name), and rely onOpenRead()/ReadAllBytesAsync()for access.
public sealed partial class InteractionFile
{
internal InteractionFile() { }
public string FilePath { get { throw null; } }
public string Id { get { throw null; } }
public string Name { get { throw null; } }
public System.IO.Stream OpenRead() { throw null; }
src/Aspire.Hosting.Go/api/Aspire.Hosting.Go.cs:21
- The new optional
logOutput = \"\"default is ambiguous: an empty string can mean either “not specified” or “explicitly specify an empty log-output value”, and downstream command-line generation can end up emitting an invalid/undesired--log-output=. Consider changing this parameter tostring? logOutput = null(or moving these flags into an options DTO) so callers can omit the setting cleanly.
public static ApplicationModel.IResourceBuilder<T> WithDelveServer<T>(this ApplicationModel.IResourceBuilder<T> builder, int port = 2345, bool acceptMulticlient = true, bool? onlySameUser = null, bool continueOnStart = false, bool log = false, string logOutput = "")
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated 1 comment.
Suppressed comments (8)
src/Aspire.Hosting/api/Aspire.Hosting.cs:1
- The
Experimentalmarker was removed from theIInteractionServicetype but is now applied only toPromptProgressAsync. This creates inconsistent analyzer/diagnostic behavior: callers may no longer see the experimental warning when using the otherPrompt*APIs even though they are part of the same interaction surface. Consider either keeping theExperimentalattribute on the interface (so all members are consistently marked) or applying it to each experimental member.
//------------------------------------------------------------------------------
src/Aspire.Hosting/api/Aspire.Hosting.cs:2844
Argumentsis non-nullable but not markedrequiredwhile many other init-only properties in these context types arerequired. That creates an inconsistent contract and allows consumers to instantiate these types without initializingArguments(leading to null-state issues). If these contexts are framework-constructed only, consider makingArgumentsget-only; otherwise mark itrequired(or make it nullable if legitimately optional).
public InteractionInputCollection Arguments { get { throw null; } init { } }
public required System.Threading.CancellationToken CancellationToken { get { throw null; } init { } }
src/Aspire.Hosting/api/Aspire.Hosting.cs:2857
Argumentsis non-nullable but not markedrequiredwhile many other init-only properties in these context types arerequired. That creates an inconsistent contract and allows consumers to instantiate these types without initializingArguments(leading to null-state issues). If these contexts are framework-constructed only, consider makingArgumentsget-only; otherwise mark itrequired(or make it nullable if legitimately optional).
[System.Obsolete("Use Services instead.")]
public System.IServiceProvider ServiceProvider { get { throw null; } init { } }
public required System.IServiceProvider Services { get { throw null; } init { } }
src/Aspire.Hosting/api/Aspire.Hosting.cs:2864
Argumentsis non-nullable but not markedrequiredwhile many other init-only properties in these context types arerequired. That creates an inconsistent contract and allows consumers to instantiate these types without initializingArguments(leading to null-state issues). If these contexts are framework-constructed only, consider makingArgumentsget-only; otherwise mark itrequired(or make it nullable if legitimately optional).
public InteractionInputCollection Arguments { get { throw null; } init { } }
public required System.Threading.CancellationToken CancellationToken { get { throw null; } init { } }
src/Aspire.Hosting/api/Aspire.Hosting.cs:2877
Argumentsis non-nullable but not markedrequiredwhile many other init-only properties in these context types arerequired. That creates an inconsistent contract and allows consumers to instantiate these types without initializingArguments(leading to null-state issues). If these contexts are framework-constructed only, consider makingArgumentsget-only; otherwise mark itrequired(or make it nullable if legitimately optional).
[System.Obsolete("Use Services instead.")]
public System.IServiceProvider ServiceProvider { get { throw null; } init { } }
public required System.IServiceProvider Services { get { throw null; } init { } }
src/Aspire.Hosting/api/Aspire.Hosting.cs:3524
Argumentsis non-nullable but not markedrequiredwhile many other init-only properties in these context types arerequired. That creates an inconsistent contract and allows consumers to instantiate these types without initializingArguments(leading to null-state issues). If these contexts are framework-constructed only, consider makingArgumentsget-only; otherwise mark itrequired(or make it nullable if legitimately optional).
public InteractionInputCollection Arguments { get { throw null; } init { } }
public required System.Threading.CancellationToken CancellationToken { get { throw null; } init { } }
src/Aspire.Hosting/api/Aspire.Hosting.cs:3539
Argumentsis non-nullable but not markedrequiredwhile many other init-only properties in these context types arerequired. That creates an inconsistent contract and allows consumers to instantiate these types without initializingArguments(leading to null-state issues). If these contexts are framework-constructed only, consider makingArgumentsget-only; otherwise mark itrequired(or make it nullable if legitimately optional).
[System.Obsolete("Use Services instead.")]
public System.IServiceProvider ServiceProvider { get { throw null; } init { } }
public required System.IServiceProvider Services { get { throw null; } init { } }
src/Aspire.Hosting/api/Aspire.Hosting.cs:2004
ServiceProvideris now an obsolete alias forServices, but both are independently init-settable, which allows them to diverge (andServiceProvideris non-nullable yet notrequired). To enforce the intended alias behavior, consider makingServiceProviderget-only and forward toServices(or otherwise ensure the two cannot be set inconsistently in the public contract).
[AspireExport]
public required IResource Model { get { throw null; } init { } }
[System.Obsolete("Use Services instead.")]
public System.IServiceProvider ServiceProvider { get { throw null; } init { } }
[AspireExport]
public required System.IServiceProvider Services { get { throw null; } init { } }
| public object ResourceGroup { get { throw null; } } | ||
| public bool IsTenantScope { get { throw null; } } | ||
|
|
||
| public object? ResourceGroup { get { throw null; } } |
There was a problem hiding this comment.
Is this considered a breaking change?
There was a problem hiding this comment.
Changing a readable public property from object to object? is a source-level breaking API contract change because callers must now account for null. It is not binary-breaking because nullable annotations do not change the CLR type. If it can actually return null, it is also behaviorally breaking because the range of returned values increased. See Microsoft’s nullable reference type guidance and .NET compatibility rules.
There was a problem hiding this comment.
Sébastien Ros (sebastienros)
left a comment
There was a problem hiding this comment.
API review findings — see the six inline comments for details.
|
|
||
| public object? Subscription { get { throw null; } } | ||
|
|
||
| public static AzureBicepResourceScope ForSubscription(object subscription) { throw null; } |
There was a problem hiding this comment.
❌ [Naming] ForSubscription and ForTenant are static factory methods, but neither name is a verb phrase. Rename them to CreateForSubscription and CreateForTenant to follow .NET member naming conventions.
API Review Summary2 errors, 9 warnings, 0 info across 6 API files. Top areas of concern:
Each finding is posted as a separate review comment for discussion. |
Sébastien Ros (sebastienros)
left a comment
There was a problem hiding this comment.
Additional API review findings traced from the ATS surface review.
| [AspireExport] | ||
| public static ApplicationModel.IResourceBuilder<Kubernetes.KubernetesPersistentVolumeResource> WithAccessMode(this ApplicationModel.IResourceBuilder<Kubernetes.KubernetesPersistentVolumeResource> builder, Kubernetes.PersistentVolumeAccessMode accessMode) { throw null; } | ||
|
|
||
| [AspireExport("withPvCapacityParam")] |
There was a problem hiding this comment.
ParameterResource overloads are exported as withPvCapacityParam and withPvStorageClassParam, while their literal overloads are withCapacity and withStorageClass. Keep overload naming parallel by using withCapacityParam / withStorageClassParam, or consistently use the full PersistentVolume term for both forms.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated 2 comments.
Suppressed comments (6)
src/Aspire.Hosting/api/Aspire.Hosting.cs:1
- The
Experimental(\"ASPIREINTERACTION001\")marker was removed from the interaction types (e.g.,IInteractionService,InputLoadOptions,InteractionInput, etc.) and is now applied only toPromptProgressAsync. If the entire interaction surface is still considered experimental, this change makes most of the API appear stable (warnings no longer emitted) while still evolving (e.g., newInputType.File,InteractionFile, progress types). Consider restoring theExperimentalattribute at the type level (or applying it consistently across all interaction-related public types) to keep the API stability signaling accurate.
//------------------------------------------------------------------------------
src/Aspire.Hosting/api/Aspire.Hosting.cs:2004
- The obsolete
ServiceProvideralias is not marked withAspireExportIgnore, unlike other contexts in this diff (e.g.,ExecuteCommandContext.ServiceProvider/UpdateCommandStateContext.ServiceProvider). If the type is exported to ATS, this likely exposes two service-provider properties and undermines the intent of the rename. Consider addingAspireExportIgnoretoServiceProvider(keeping it for .NET source compatibility) and exporting onlyServicesfor polyglot surfaces.
[AspireExport]
public required IResource Model { get { throw null; } init { } }
[System.Obsolete("Use Services instead.")]
public System.IServiceProvider ServiceProvider { get { throw null; } init { } }
[AspireExport]
public required System.IServiceProvider Services { get { throw null; } init { } }
src/Aspire.Hosting/api/Aspire.Hosting.cs:649
- The
Experimental(\"ASPIREINTERACTION001\")marker was removed from the interaction types (e.g.,IInteractionService,InputLoadOptions,InteractionInput, etc.) and is now applied only toPromptProgressAsync. If the entire interaction surface is still considered experimental, this change makes most of the API appear stable (warnings no longer emitted) while still evolving (e.g., newInputType.File,InteractionFile, progress types). Consider restoring theExperimentalattribute at the type level (or applying it consistently across all interaction-related public types) to keep the API stability signaling accurate.
[System.Diagnostics.CodeAnalysis.Experimental("ASPIREINTERACTION001", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")]
System.Threading.Tasks.Task<InteractionResult<bool>> PromptProgressAsync(string message, string? title = null, ProgressInteractionOptions? options = null, System.Threading.CancellationToken cancellationToken = default);
}
src/Aspire.Hosting.Kubernetes/api/Aspire.Hosting.Kubernetes.cs:187
AddPersistentVolumeis exported and returnsIResourceBuilder<KubernetesPersistentVolumeResource>, butKubernetesPersistentVolumeResourceis not annotated withAspireExport(contrast withKubernetesResourcewhich is[AspireExport(ExposeProperties = true)]). If polyglot hosts are expected to consume the returned resource/builder, the resource type typically needs an export annotation/projection; otherwise ATS bindings may be incomplete or inconsistent. Consider adding an appropriateAspireExportattribute (and exporting any required properties) forKubernetesPersistentVolumeResource.
[System.Diagnostics.CodeAnalysis.Experimental("ASPIRECOMPUTE002", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")]
public static partial class KubernetesPersistentVolumeExtensions
{
[AspireExport]
public static ApplicationModel.IResourceBuilder<Kubernetes.KubernetesPersistentVolumeResource> AddPersistentVolume(this ApplicationModel.IResourceBuilder<Kubernetes.KubernetesEnvironmentResource> builder, string name) { throw null; }
src/Aspire.Hosting.Kubernetes/api/Aspire.Hosting.Kubernetes.cs:422
AddPersistentVolumeis exported and returnsIResourceBuilder<KubernetesPersistentVolumeResource>, butKubernetesPersistentVolumeResourceis not annotated withAspireExport(contrast withKubernetesResourcewhich is[AspireExport(ExposeProperties = true)]). If polyglot hosts are expected to consume the returned resource/builder, the resource type typically needs an export annotation/projection; otherwise ATS bindings may be incomplete or inconsistent. Consider adding an appropriateAspireExportattribute (and exporting any required properties) forKubernetesPersistentVolumeResource.
[System.Diagnostics.CodeAnalysis.Experimental("ASPIRECOMPUTE002", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")]
public sealed partial class KubernetesPersistentVolumeResource : ApplicationModel.Resource, ApplicationModel.IResourceWithParent<KubernetesEnvironmentResource>, ApplicationModel.IResourceWithParent, ApplicationModel.IResource
{
public KubernetesPersistentVolumeResource(string name, KubernetesEnvironmentResource environment) : base(default!) { }
src/Aspire.Hosting.DevTunnels/api/Aspire.Hosting.DevTunnels.cs:100
- Enum member naming is inconsistent with common .NET acronym capitalization (e.g.,
UkSouth,EastUs,WestUs2). Since this is newly introduced API surface, consider usingUKSouth,EastUS,EastUS2,WestUS2,WestUS3, etc., to align with established naming conventions and avoid locking in inconsistent names.
public enum DevTunnelRegion : byte
{
WestEurope = 0,
UkSouth = 1,
NorthEurope = 2,
EastUs = 3,
EastUs2 = 4,
CentralIndia = 5,
WestUs3 = 6,
WestUs2 = 7,
SouthEastAsia = 8,
BrazilSouth = 9,
AustraliaCentral = 10,
AustraliaEast = 11,
JapanEast = 12
}
| public required ReferenceExpression CertificatePath { get { throw null; } init { } } | ||
|
|
||
| [AspireExport] | ||
| public required ReferenceExpression CertificateWithKeyPath { get { throw null; } init { } } | ||
|
|
||
| public required System.Collections.Generic.Dictionary<string, object> EnvironmentVariables { get { throw null; } init { } } |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated 2 comments.
Suppressed comments (2)
src/Aspire.Hosting.Go/api/Aspire.Hosting.Go.cs:21
- Using
string logOutput = \"\"makes the default value indistinguishable from an explicit empty value. For option-style parameters where "unset" is meaningful, defaulting tonull(i.e.,string? logOutput = null) is typically safer and avoids accidentally emitting an empty--log-outputvalue in downstream argument construction.
public static ApplicationModel.IResourceBuilder<T> WithDelveServer<T>(this ApplicationModel.IResourceBuilder<T> builder, int port = 2345, bool acceptMulticlient = true, bool? onlySameUser = null, bool continueOnStart = false, bool log = false, string logOutput = "")
src/Aspire.Hosting.Foundry/api/Aspire.Hosting.Foundry.cs:988
- It looks like
HostedAgentConfiguration.ContainerProtocolVersionswas removed and replaced withProtocolVersions. Since the old member was a public API (even ifAspireExportIgnore), removing it is a breaking change for .NET consumers. Consider keepingContainerProtocolVersionsas an[Obsolete]alias that forwards toProtocolVersionsto preserve binary/source compatibility.
[AspireExportIgnore(Reason = "Azure SDK-specific type not usable from polyglot hosts.")]
public System.Collections.Generic.IList<global::Azure.AI.Projects.Agents.ProtocolVersionRecord> ProtocolVersions { get { throw null; } init { } }
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated 1 comment.
Suppressed comments (4)
src/Aspire.Hosting/api/Aspire.Hosting.cs:1
- The
[Experimental(\"ASPIREINTERACTION001\")]annotation appears to have been removed from theIInteractionServicetype itself (and from several other interaction-related types in this file), leaving only specific members marked experimental (e.g.,PromptProgressAsync). Removing the attribute from the type changes the public API contract and warning behavior for consumers. If these APIs are still intended to be experimental, re-add the attribute at the type level (or apply it consistently across the interaction surface).
//------------------------------------------------------------------------------
src/Aspire.Hosting/api/Aspire.Hosting.cs:2846
- The newly added
Argumentsproperty usesinitbut is not markedrequired, while the rest of the context usesrequiredfor init-only properties. For consistency and to avoid consumers seeing a possibly-uninitializedArguments, consider markingArgumentsasrequired(and similarly for the other newly addedArgumentsproperties in result contexts, e.g.,HttpCommandResultContextandProcessCommandResultContext).
public sealed partial class HttpCommandRequestContext
{
public InteractionInputCollection Arguments { get { throw null; } init { } }
public required System.Threading.CancellationToken CancellationToken { get { throw null; } init { } }
public required EndpointReference Endpoint { get { throw null; } init { } }
src/Aspire.Hosting/api/Aspire.Hosting.cs:2004
ServiceProvideris now an obsolete alias forServices, but it is still part of the exported surface ofContainerFileSystemCallbackContext(noAspireExportIgnore). This can create duplicate/ambiguous API projections for polyglot hosts. Consider addingAspireExportIgnoretoServiceProvider(while keeping it for .NET source compatibility) and exporting onlyServices.
[AspireExport]
public required IResource Model { get { throw null; } init { } }
[System.Obsolete("Use Services instead.")]
public System.IServiceProvider ServiceProvider { get { throw null; } init { } }
[AspireExport]
public required System.IServiceProvider Services { get { throw null; } init { } }
src/Aspire.Hosting.Azure/api/Aspire.Hosting.Azure.cs:527
- The new constructor requires a non-null
subscription, but theSubscriptionproperty is declared nullable (object?). This weakens the contract and makes it unclear whenSubscriptioncan actually be null. Consider makingSubscriptionnon-nullable (object) or adjusting the constructor/property/nullability semantics to match (e.g., only nullable when tenant-scope is used).
public sealed partial class ExistingAzureResourceAnnotation : ApplicationModel.IResourceAnnotation
{
public ExistingAzureResourceAnnotation(object name, object? resourceGroup, object subscription) { }
public ExistingAzureResourceAnnotation(object name, object? resourceGroup = null) { }
public bool IsTenantScope { get { throw null; } }
public object Name { get { throw null; } }
public object? ResourceGroup { get { throw null; } }
public object? Subscription { get { throw null; } }
}
This comment has been minimized.
This comment has been minimized.
Tests selector (audit mode)The full test matrix and all jobs still run in audit mode. The tests and jobs below are what selective CI would run under enforcement. 48 / 100 test projects · 4 jobs, from 17 changed files. Selected test projects (48 / 100)
Selected jobs (4)
How these were chosen — grouped by what changed
🔧 show 27
🔧 🔧 🔧 🔧 🔧 🔧 📦 affected project 🔧 🔧 🔧 🔧 🔧 🔧 🔧 🔧 🔧 🔧 Job reasons
Selection computed for commit |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 17 changed files in this pull request and generated no new comments.
Suppressed comments (3)
src/Aspire.Hosting/api/Aspire.Hosting.cs:648
- cc
@JamesNK
IInteractionService is being promoted to a stable interface, but this new abstract member remains experimental. External implementations of the stable interface are therefore forced to implement an experimental contract, and that contract cannot later evolve without breaking those implementers. Keep the interface experimental, or move progress support to a separate experimental interface/default implementation.
System.Threading.Tasks.Task<InteractionResult<bool>> PromptProgressAsync(string message, string? title = null, ProgressInteractionOptions? options = null, System.Threading.CancellationToken cancellationToken = default);
src/Aspire.Hosting.Go/api/Aspire.Hosting.Go.cs:21
- cc
@air-hand
Replacing the existing overload with six scalar parameters leaves five optional settings on one API, making future additions difficult and producing a boolean-heavy call shape. Please preserve a small overload and move the Delve settings into an options type (or add a separate options overload) before this surface ships.
public static ApplicationModel.IResourceBuilder<T> WithDelveServer<T>(this ApplicationModel.IResourceBuilder<T> builder, int port = 2345, bool acceptMulticlient = true, bool? onlySameUser = null, bool continueOnStart = false, bool log = false, string logOutput = "")
src/Aspire.Hosting.DevTunnels/api/Aspire.Hosting.DevTunnels.cs:85
- cc
@kola-tm
This generated baseline no longer matches the source included in this PR: DevTunnelRegion now uses the default int underlying type and defines UKSouth/SoutheastAsia, while this file still records : byte, UkSouth, and SouthEastAsia. Since this PR is specifically updating the shipped API surface, regenerate the DevTunnels baseline after the source correction.
public enum DevTunnelRegion : byte
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated 2 comments.
Suppressed comments (3)
src/Aspire.Hosting.Kubernetes/api/Aspire.Hosting.Kubernetes.cs:425
AddPersistentVolume(...)and related methods are marked[AspireExport]and returnIResourceBuilder<KubernetesPersistentVolumeResource>, but the returned resource type itself isn’t annotated like other exported resource types in this file (e.g.,KubernetesResourceuses[AspireExport(ExposeProperties = true)]). If this resource is meant to be consumed by ATS/polyglot callers, consider adding[AspireExport(ExposeProperties = true)]toKubernetesPersistentVolumeResourceso the type is part of the exportable surface consistently.
public sealed partial class KubernetesPersistentVolumeResource : ApplicationModel.Resource, ApplicationModel.IResourceWithParent<KubernetesEnvironmentResource>, ApplicationModel.IResourceWithParent, ApplicationModel.IResource
{
public KubernetesPersistentVolumeResource(string name, KubernetesEnvironmentResource environment) : base(default!) { }
public KubernetesEnvironmentResource Parent { get { throw null; } }
}
src/Aspire.Hosting.DevTunnels/api/Aspire.Hosting.DevTunnels.cs:88
- Enum member
UkSouthis inconsistent with common .NET initialism casing (typicallyUKSouth). Consider renaming toUKSouthfor consistency with PascalCase + initialisms (or align with whatever casing convention is already used for other region enums in the repo).
public enum DevTunnelRegion : byte
{
WestEurope = 0,
UkSouth = 1,
src/Aspire.Hosting/api/Aspire.Hosting.cs:1088
- The exported name/method name (
withRequiredCommandValidation) doesn’t match the actual API nameWithRequiredCommand, which can be confusing for consumers and makes it harder to discover/align exports. If this is intended to represent a validation-specific overload, consider either (a) renaming the .NET method to reflect validation, or (b) exporting it under a name that stays consistent withWithRequiredCommand(and differentiating overloads via parameters/options).
[AspireExport("withRequiredCommandValidation", MethodName = "withRequiredCommandValidation")]
public static ApplicationModel.IResourceBuilder<T> WithRequiredCommand<T>(this ApplicationModel.IResourceBuilder<T> builder, string command, System.Func<ApplicationModel.RequiredCommandValidationContext, System.Threading.Tasks.Task<ApplicationModel.RequiredCommandValidationResult>> validationCallback, string? helpLink = null)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated 2 comments.
Suppressed comments (2)
src/Aspire.Hosting/api/Aspire.Hosting.cs:1
- This change removes the prior
AspireExportIgnoreonInputsDialogValidationContext.Services. Since the type is exported withExposeProperties = true, this will now exportIServiceProviderto the ATS/polyglot surface. IfIServiceProviderstill has no ATS representation (as the removed reason text indicates), this will likely break export/codegen or produce an unusable API. Either re-addAspireExportIgnoreforServices, or replace it with an ATS-compatible abstraction/handle that polyglot callers can actually consume.
//------------------------------------------------------------------------------
src/Aspire.Hosting.Azure.AppContainers/api/Aspire.Hosting.Azure.AppContainers.cs:67
- The
[Experimental(\"ASPIREACADOMAINS001\", ...)]annotation was removed fromConfigureCustomDomain. If this API is still considered experimental, dropping the attribute changes the API contract (and will remove the compile-time experimental warnings). Either restore theExperimentalattribute or (if the API is now stable) consider updating release notes/changelog accordingly so consumers aren’t surprised by the behavioral change in analyzers.
[AspireExport]
public static void ConfigureCustomDomain(this global::Azure.Provisioning.AppContainers.ContainerApp app, ApplicationModel.IResourceBuilder<ApplicationModel.ParameterResource> customDomain, ApplicationModel.IResourceBuilder<ApplicationModel.ParameterResource> certificateName) { }
| [AspireExportIgnore(Reason = "Azure SDK-specific type not usable from polyglot hosts.")] | ||
| public System.Collections.Generic.IList<global::Azure.AI.Projects.Agents.ProtocolVersionRecord> ProtocolVersions { get { throw null; } init { } } |
| [AspireValue("FoundryModels")] | ||
| public static readonly FoundryModel CohereCommandA; | ||
| [AspireValue("FoundryModels")] | ||
| public static readonly FoundryModel CohereCommandR082024; | ||
| [AspireValue("FoundryModels")] | ||
| public static readonly FoundryModel CohereCommandRPlus082024; | ||
| public static readonly FoundryModel CohereCommandAPlus052026; |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated 1 comment.
Suppressed comments (3)
src/Aspire.Hosting/api/Aspire.Hosting.cs:1088
- The exported name
withRequiredCommandValidationdoesn’t align with the method nameWithRequiredCommandand (based on the signature) appears to configure both the required command and its validation callback. If the intended polyglot surface is the same concept as the .NET extension, consider exporting it under a name that matches the behavioral unit (e.g.,withRequiredCommand) to avoid confusing/duplicative exports and improve discoverability.
[System.Diagnostics.CodeAnalysis.Experimental("ASPIRECOMMAND001", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")]
[AspireExport("withRequiredCommandValidation", MethodName = "withRequiredCommandValidation")]
public static ApplicationModel.IResourceBuilder<T> WithRequiredCommand<T>(this ApplicationModel.IResourceBuilder<T> builder, string command, System.Func<ApplicationModel.RequiredCommandValidationContext, System.Threading.Tasks.Task<ApplicationModel.RequiredCommandValidationResult>> validationCallback, string? helpLink = null)
src/Aspire.Hosting/api/Aspire.Hosting.cs:1920
- Setting
ExposeProperties = trueon a callback context can unintentionally export members whose types are not stable/serializable (e.g., logging abstractions), expanding the ATS contract more than necessary. Prefer exporting only the minimal required properties (either by omittingExposeProperties = trueand annotating specific properties with[AspireExport], or by explicitly[AspireExportIgnore]-ing any non-ATS-friendly properties) to keep the contract small and avoid export-generation failures.
[System.Diagnostics.CodeAnalysis.Experimental("ASPIREPIPELINES003", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")]
[AspireExport(ExposeProperties = true)]
public sealed partial class ContainerBuildOptionsCallbackContext
{
public ContainerBuildOptionsCallbackContext(IResource resource, System.IServiceProvider services, Microsoft.Extensions.Logging.ILogger logger, System.Threading.CancellationToken cancellationToken, DistributedApplicationExecutionContext executionContext) { }
src/Aspire.Hosting.DevTunnels/api/Aspire.Hosting.DevTunnels.cs:93
- Enum member naming appears inconsistent:
EastUs/WestUs3useUs, butUKSouthuses an all-caps acronym. For consistency with the surrounding members and .NET PascalCase conventions, consider renamingUKSouthtoUkSouth(since this enum member is newly introduced, it’s best to correct it before consumers take a dependency).
public enum DevTunnelRegion
{
WestEurope = 0,
UKSouth = 1,
NorthEurope = 2,
EastUs = 3,
EastUs2 = 4,
CentralIndia = 5,
WestUs3 = 6,
| [AspireExportIgnore(Reason = "Azure SDK-specific type not usable from polyglot hosts.")] | ||
| public System.Collections.Generic.IList<global::Azure.AI.Projects.Agents.ProtocolVersionRecord> ProtocolVersions { get { throw null; } init { } } |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
src/Aspire.Hosting/api/Aspire.Hosting.cs:3922
- These overrides are empty, which changes the behavior of
Collection<T>(mutations become no-ops). In API/reference-assembly-style stubs elsewhere in this file, members usethrow null;; these should follow the same pattern (or, if mutation is intentionally blocked at runtime, throwNotSupportedExceptionso callers get a clear failure instead of silent no-ops).
public sealed partial class ResourceAnnotationCollection : System.Collections.ObjectModel.Collection<IResourceAnnotation>
{
protected override void ClearItems() { }
protected override void InsertItem(int index, IResourceAnnotation item) { }
protected override void RemoveItem(int index) { }
protected override void SetItem(int index, IResourceAnnotation item) { }
| [AspireExport] | ||
| public static ApplicationModel.IResourceBuilder<T> WithDelveServer<T>(this ApplicationModel.IResourceBuilder<T> builder, Go.DelveServerOptions? options = null) | ||
| where T : Go.GoAppResource { throw null; } | ||
|
|
||
| [System.Obsolete("Use WithDelveServer() or WithDelveServer(DelveServerOptions) instead.")] | ||
| [AspireExportIgnore(Reason = "This obsolete compatibility overload is C#-only. Polyglot AppHosts use the DelveServerOptions overload.")] | ||
| public static ApplicationModel.IResourceBuilder<T> WithDelveServer<T>(this ApplicationModel.IResourceBuilder<T> builder, int port = 2345) | ||
| where T : Go.GoAppResource { throw null; } | ||
|
|
||
| [AspireExportIgnore(Reason = "This C# convenience overload uses default options. Polyglot AppHosts use the DelveServerOptions overload.")] | ||
| public static ApplicationModel.IResourceBuilder<T> WithDelveServer<T>(this ApplicationModel.IResourceBuilder<T> builder) | ||
| where T : Go.GoAppResource { throw null; } |
Auto-generated update to the API surface to compare current surface vs latest release. This should only be merged once this surface area ships in a new release.