Skip to content

Conversation

captainsafia
Copy link
Member

Contributes to #10448.

20250828_130408

@Copilot Copilot AI review requested due to automatic review settings August 28, 2025 20:05
@captainsafia captainsafia requested a review from eerhardt as a code owner August 28, 2025 20:05
@github-actions github-actions bot added the area-app-model Issues pertaining to the APIs in Aspire.Hosting, e.g. DistributedApplication label Aug 28, 2025
Copy link
Contributor

@Copilot 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 adds support for prompting users for unresolved parameter values during Azure deployment, addressing the need to collect missing parameter values interactively rather than failing the deployment.

  • Adds parameter resolution step before Azure Bicep provisioning that prompts for unresolved parameters
  • Exposes the WaitForValueTcs property on ParameterResource for testing purposes
  • Updates Azure deployment context to include interaction service for parameter prompting

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/Aspire.Hosting.Azure.Tests/AzureDeployerTests.cs Adds tests for parameter prompting functionality during deployment
src/Aspire.Hosting/ApplicationModel/ParameterResource.cs Changes WaitForValueTcs visibility from internal to public
src/Aspire.Hosting.Azure/AzureEnvironmentResource.cs Injects interaction service into Azure deploying context
src/Aspire.Hosting.Azure/AzureDeployingContext.cs Implements parameter resolution logic with user prompting
playground/deployers/Deployers.AppHost/AppHost.cs Adds example parameters for testing deployment scenarios

@@ -75,7 +75,7 @@ internal string ConfigurationKey
/// <summary>
/// A task completion source that can be used to wait for the value of the parameter to be set.
/// </summary>
internal TaskCompletionSource<string>? WaitForValueTcs { get; set; }
public TaskCompletionSource<string>? WaitForValueTcs { get; set; }
Copy link
Member

Choose a reason for hiding this comment

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

We shouldn't be exposing the TaskCompletionSource publicly. That would mean anyone would be able to complete the Task. Instead, you just want the Task to be exposed, right?

Copy link
Member

Choose a reason for hiding this comment

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

Maybe we should flip this instead. ParameterResource has the ability for callers to give it a Task<string> that it can use to pull the value from?

Copy link
Member Author

Choose a reason for hiding this comment

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

We shouldn't be exposing the TaskCompletionSource publicly. That would mean anyone would be able to complete the Task.

In this case, we do want to complete the TCS from outside the core API

Maybe we should flip this instead. ParameterResource has the ability for callers to give it a Task that it can use to pull the value from?

Is this similar to SetValue from #11160 (comment). Something like public void SetValue(Task<string> valueProvider) then we'd resolve the valueProvider that is passed in GetValueAsync.

Another option is to do something similar to what we did with ProvisioningContextProvider and have a common ParameterProcessor implementation that both run-mode and publish-mode scenarios use.

Copy link
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 a TCS should be exposed publically. Instead I would expected there to be a Task property on the type and, if publically required, a method to complete it, e.g.

public Task ValueAvailableTask { get; }
public void SetValue(string s); // completes the task

Copy link
Member

@davidfowl davidfowl Aug 29, 2025

Choose a reason for hiding this comment

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

Unless you want to cancel or set an exception (now we're recreating a TCS with a new name).

Copy link
Member Author

Choose a reason for hiding this comment

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

I changed the implementation in 5d805e1 so that ParameterProcessor is public. This let's the Azure deployer and any other deployers that are implemented add support for parameter resolution.

Some notes on this:

  • Users now get prompted about saving values to user secrets, which isn't something we want to support for deployment. We may need to opt this out, I can see it being valuable for super local deployment scenarios but not necessarily deployments from CI.
  • We need to add a WaitForParameterResolutionAsync method to the processor so that we can support the dashboard's fire and forget model and the

@davidfowl
Copy link
Member

Does every deployment system need to implement their own parameter processing and prompting? Why wouldn't this be as generic as what we have at runtime with the ParameterProcessor?

@captainsafia
Copy link
Member Author

Does every deployment system need to implement their own parameter processing and prompting? Why wouldn't this be as generic as what we have at runtime with the ParameterProcessor?

Yep, this is a scenario where this proposal:

Another option is to do something similar to what we did with ProvisioningContextProvider and have a common ParameterProcessor implementation that both run-mode and publish-mode scenarios use.

would come in handy. If we centralize parameter resolution as a core public API, then it wouldn't need to be rewritten in multiple places.

Copy link
Contributor

github-actions bot commented Sep 2, 2025

🚀 Dogfood this PR with:

curl -fsSL https://github.com/raw/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 11160

Or

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

ResourceNotificationService notificationService,
ResourceLoggerService loggerService,
IInteractionService interactionService,
ILogger<ParameterProcessor> logger,
DistributedApplicationOptions options)
{
private readonly List<ParameterResource> _unresolvedParameters = [];

public async Task InitializeParametersAsync(IEnumerable<ParameterResource> parameterResources)
private Task? _parameterResolutionTask;
Copy link
Member

Choose a reason for hiding this comment

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

Delete this task.

@@ -76,14 +77,16 @@ private Task DeployAsync(DeployingContext context)
var activityPublisher = context.Services.GetRequiredService<IPublishingActivityReporter>();
var containerImageBuilder = context.Services.GetRequiredService<IResourceContainerImageBuilder>();
var processRunner = context.Services.GetRequiredService<IProcessRunner>();
var parameterProcessor = context.Services.GetRequiredService<ParameterProcessor>();
Copy link
Member

Choose a reason for hiding this comment

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

Do we want this concrete type as the DI service? Or do we want an interface?

Copy link
Member

Choose a reason for hiding this comment

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

Interface when we figure out what to expose. This API is sketchy as is.

/// Initializes parameter resources and handles unresolved parameters if interaction service is available.
/// </summary>
/// <param name="parameterResources">The parameter resources to initialize.</param>
/// <param name="waitForResolution">Whether to wait for all parameters to be resolved before returning.</param>
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// <param name="waitForResolution">Whether to wait for all parameters to be resolved before returning.</param>
/// <param name="waitForResolution">Whether to wait for all parameters to be resolved before completing the returned Task.</param>

@@ -14,16 +15,24 @@ namespace Aspire.Hosting.Orchestrator;
/// <summary>
/// Handles processing of parameter resources during application orchestration.
/// </summary>
internal sealed class ParameterProcessor(
[Experimental("ASPIREINTERACTION001", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")]
public sealed class ParameterProcessor(
Copy link
Member

Choose a reason for hiding this comment

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

I think this is the first public type in the Aspire.Hosting.Orchestrator namespace. I'm wondering if we should make an interface in a separate namespace that is already exposed.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good callout -- I think we should move this to the Aspire.Hosting namespace to match what we do for InteractionService.

@captainsafia captainsafia merged commit b024fa4 into main Sep 3, 2025
305 checks passed
@captainsafia captainsafia deleted the safia/deploy-params branch September 3, 2025 21:37
@dotnet-policy-service dotnet-policy-service bot added this to the 9.5 milestone Sep 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-app-model Issues pertaining to the APIs in Aspire.Hosting, e.g. DistributedApplication
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants