From 293db20eebd2f451602c4dd6f69e75b7897c6467 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Wed, 29 Apr 2026 17:36:10 -0500 Subject: [PATCH 1/2] Ensure compute environment prepare waits for validation When Foundry is used with another compute environment, the compute environments get confused about who takes ownership of which compute. Make all compute-environment prepare pipeline steps depend on the shared validate-compute-environments step so before-start cannot race environment validation. Add diagnostics coverage for a mixed Foundry hosted-agent and Azure Container Apps app. Cover deployment target lookup returning null for a different compute environment. --- .../FoundryAgents.AppHost/AppHost.cs | 3 + .../FoundryAgents.AppHost.csproj | 1 + .../AzureContainerAppEnvironmentResource.cs | 2 +- .../AzureAppServiceEnvironmentResource.cs | 2 +- .../AzureKubernetesEnvironmentResource.cs | 1 + .../DockerComposeEnvironmentResource.cs | 4 +- .../HostedAgent/AzureHostedAgentResource.cs | 2 +- .../HostedAgentBuilderExtension.cs | 10 +- .../Project/ProjectResource.cs | 2 +- .../KubernetesEnvironmentResource.cs | 1 + .../ApplicationModel/ResourceExtensions.cs | 13 +- .../DistributedApplicationPipeline.cs | 2 +- .../Pipelines/WellKnownPipelineSteps.cs | 6 + .../AzureDeployerTests.cs | 30 + ..._DoesNotHang_step=diagnostics.verified.txt | 18 +- ...ps_CreatesCorrectDependencies.verified.txt | 696 ++++++++++++++++++ ...nments_Works_step=diagnostics.verified.txt | 30 +- ...ts_CreatesCorrectDependencies.verified.txt | 18 +- ...on_CreatesCorrectDependencies.verified.txt | 18 +- .../ResourceExtensionsTests.cs | 19 + 20 files changed, 826 insertions(+), 52 deletions(-) create mode 100644 tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithFoundryAndAzureContainerApps_CreatesCorrectDependencies.verified.txt diff --git a/playground/FoundryAgents/FoundryAgents.AppHost/AppHost.cs b/playground/FoundryAgents/FoundryAgents.AppHost/AppHost.cs index d0e727e7223..04302915a42 100644 --- a/playground/FoundryAgents/FoundryAgents.AppHost/AppHost.cs +++ b/playground/FoundryAgents/FoundryAgents.AppHost/AppHost.cs @@ -8,6 +8,8 @@ var builder = DistributedApplication.CreateBuilder(args); +var aca = builder.AddAzureContainerAppEnvironment("env"); + var foundry = builder.AddFoundry("aif-myfoundry"); var project = foundry.AddProject("proj-myproject") // workaround for https://github.com/microsoft/aspire/issues/15971 @@ -71,6 +73,7 @@ create funny charts or calculations about the topic. builder.AddProject("chat-app") .WithExternalHttpEndpoints() + .WithComputeEnvironment(aca) .WithReference(jokerAgent).WaitFor(jokerAgent) .WithReference(researchAgent).WaitFor(researchAgent); diff --git a/playground/FoundryAgents/FoundryAgents.AppHost/FoundryAgents.AppHost.csproj b/playground/FoundryAgents/FoundryAgents.AppHost/FoundryAgents.AppHost.csproj index 9620d21ef48..8cffc7feadd 100644 --- a/playground/FoundryAgents/FoundryAgents.AppHost/FoundryAgents.AppHost.csproj +++ b/playground/FoundryAgents/FoundryAgents.AppHost/FoundryAgents.AppHost.csproj @@ -11,6 +11,7 @@ + diff --git a/src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppEnvironmentResource.cs b/src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppEnvironmentResource.cs index 53fd954ee10..fece4869a97 100644 --- a/src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppEnvironmentResource.cs +++ b/src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppEnvironmentResource.cs @@ -50,7 +50,7 @@ public AzureContainerAppEnvironmentResource(string name, Action PrepareDeploymentTargetsAsync(ctx), - DependsOnSteps = [AzureEnvironmentResource.PrepareResourcesStepName], + DependsOnSteps = [AzureEnvironmentResource.PrepareResourcesStepName, WellKnownPipelineSteps.ValidateComputeEnvironments], RequiredBySteps = [WellKnownPipelineSteps.BeforeStart] }; diff --git a/src/Aspire.Hosting.Azure.AppService/AzureAppServiceEnvironmentResource.cs b/src/Aspire.Hosting.Azure.AppService/AzureAppServiceEnvironmentResource.cs index 0024accb6f3..2e9e39a29a4 100644 --- a/src/Aspire.Hosting.Azure.AppService/AzureAppServiceEnvironmentResource.cs +++ b/src/Aspire.Hosting.Azure.AppService/AzureAppServiceEnvironmentResource.cs @@ -51,7 +51,7 @@ public AzureAppServiceEnvironmentResource(string name, Action PrepareDeploymentTargetsAsync(ctx), - DependsOnSteps = [AzureEnvironmentResource.PrepareResourcesStepName], + DependsOnSteps = [AzureEnvironmentResource.PrepareResourcesStepName, WellKnownPipelineSteps.ValidateComputeEnvironments], RequiredBySteps = [WellKnownPipelineSteps.BeforeStart] }; diff --git a/src/Aspire.Hosting.Azure.Kubernetes/AzureKubernetesEnvironmentResource.cs b/src/Aspire.Hosting.Azure.Kubernetes/AzureKubernetesEnvironmentResource.cs index e36747ea9b0..2cce7bdb839 100644 --- a/src/Aspire.Hosting.Azure.Kubernetes/AzureKubernetesEnvironmentResource.cs +++ b/src/Aspire.Hosting.Azure.Kubernetes/AzureKubernetesEnvironmentResource.cs @@ -46,6 +46,7 @@ public AzureKubernetesEnvironmentResource( Name = $"prepare-aks-{Name}", Description = $"Prepares Azure Kubernetes Service environment {Name}.", Action = ctx => PrepareAksEnvironmentAsync(ctx), + DependsOnSteps = [WellKnownPipelineSteps.ValidateComputeEnvironments], RequiredBySteps = [ WellKnownPipelineSteps.BeforeStart, diff --git a/src/Aspire.Hosting.Docker/DockerComposeEnvironmentResource.cs b/src/Aspire.Hosting.Docker/DockerComposeEnvironmentResource.cs index d562ebf49ae..d0054a28dc9 100644 --- a/src/Aspire.Hosting.Docker/DockerComposeEnvironmentResource.cs +++ b/src/Aspire.Hosting.Docker/DockerComposeEnvironmentResource.cs @@ -70,6 +70,7 @@ public DockerComposeEnvironmentResource(string name) : base(name) Name = $"prepare-deployment-targets-{Name}", Description = $"Prepares Docker Compose deployment targets for {Name}.", Action = ctx => PrepareDeploymentTargetsAsync(ctx), + DependsOnSteps = [WellKnownPipelineSteps.ValidateComputeEnvironments], RequiredBySteps = [WellKnownPipelineSteps.BeforeStart] }; steps.Add(prepareDeploymentTargetsStep); @@ -118,7 +119,8 @@ public DockerComposeEnvironmentResource(string name) : base(name) { Name = $"prepare-{Name}", Description = $"Prepares the Docker Compose environment {Name} for deployment.", - Action = ctx => PrepareAsync(ctx) + Action = ctx => PrepareAsync(ctx), + DependsOnSteps = [WellKnownPipelineSteps.ValidateComputeEnvironments] }; prepareStep.DependsOn(WellKnownPipelineSteps.Publish); prepareStep.DependsOn(WellKnownPipelineSteps.Build); diff --git a/src/Aspire.Hosting.Foundry/HostedAgent/AzureHostedAgentResource.cs b/src/Aspire.Hosting.Foundry/HostedAgent/AzureHostedAgentResource.cs index d520765783d..fc0c69476df 100644 --- a/src/Aspire.Hosting.Foundry/HostedAgent/AzureHostedAgentResource.cs +++ b/src/Aspire.Hosting.Foundry/HostedAgent/AzureHostedAgentResource.cs @@ -15,7 +15,7 @@ namespace Aspire.Hosting.Foundry; /// /// A Microsoft Foundry hosted agent resource. /// -public class AzureHostedAgentResource : Resource, IComputeResource, IResourceWithEnvironment +public class AzureHostedAgentResource : Resource, IResourceWithEnvironment { /// /// Creates a new instance of the class. diff --git a/src/Aspire.Hosting.Foundry/HostedAgent/HostedAgentBuilderExtension.cs b/src/Aspire.Hosting.Foundry/HostedAgent/HostedAgentBuilderExtension.cs index 2299b2fa498..8d9f7b1308f 100644 --- a/src/Aspire.Hosting.Foundry/HostedAgent/HostedAgentBuilderExtension.cs +++ b/src/Aspire.Hosting.Foundry/HostedAgent/HostedAgentBuilderExtension.cs @@ -261,6 +261,9 @@ await interactionService.PromptMessageBoxAsync( project = builder.ApplicationBuilder.CreateResourceBuilder(projResource); } } + + builder.WithComputeEnvironment(project); + // Hosted Agent resource name var agentName = $"{resource.Name}-ha"; if (builder.ApplicationBuilder.TryCreateResourceBuilder(agentName, out var rb)) @@ -304,9 +307,12 @@ await interactionService.PromptMessageBoxAsync( { throw new InvalidOperationException($"Unable to create hosted agent for resource '{resource.Name}' because it is not a container, executable, or project resource."); } - - target = resource; + else + { + target = resource; + } } + // Create a separate agent resource to host the deployment var agent = new AzureHostedAgentResource(agentName, target, configure); diff --git a/src/Aspire.Hosting.Foundry/Project/ProjectResource.cs b/src/Aspire.Hosting.Foundry/Project/ProjectResource.cs index 8ed2448b8f5..697b7cafbd8 100644 --- a/src/Aspire.Hosting.Foundry/Project/ProjectResource.cs +++ b/src/Aspire.Hosting.Foundry/Project/ProjectResource.cs @@ -59,7 +59,7 @@ public AzureCognitiveServicesProjectResource([ResourceName] string name, Action< return Task.CompletedTask; }, Resource = this, - DependsOnSteps = [AzureEnvironmentResource.PrepareResourcesStepName], + DependsOnSteps = [AzureEnvironmentResource.PrepareResourcesStepName, WellKnownPipelineSteps.ValidateComputeEnvironments], RequiredBySteps = [WellKnownPipelineSteps.BeforeStart] }; steps.Add(removeDefaultContainerRegistryStep); diff --git a/src/Aspire.Hosting.Kubernetes/KubernetesEnvironmentResource.cs b/src/Aspire.Hosting.Kubernetes/KubernetesEnvironmentResource.cs index a17d583828f..8aa7e3fabc5 100644 --- a/src/Aspire.Hosting.Kubernetes/KubernetesEnvironmentResource.cs +++ b/src/Aspire.Hosting.Kubernetes/KubernetesEnvironmentResource.cs @@ -200,6 +200,7 @@ public KubernetesEnvironmentResource(string name) : base(name) Name = $"prepare-deployment-targets-{Name}", Description = $"Prepares Kubernetes deployment targets for {Name}.", Action = ctx => PrepareDeploymentTargetsAsync(ctx), + DependsOnSteps = [WellKnownPipelineSteps.ValidateComputeEnvironments], RequiredBySteps = [WellKnownPipelineSteps.BeforeStart] }; diff --git a/src/Aspire.Hosting/ApplicationModel/ResourceExtensions.cs b/src/Aspire.Hosting/ApplicationModel/ResourceExtensions.cs index dab51d4862f..ba1ee31ee5f 100644 --- a/src/Aspire.Hosting/ApplicationModel/ResourceExtensions.cs +++ b/src/Aspire.Hosting/ApplicationModel/ResourceExtensions.cs @@ -999,7 +999,7 @@ internal static bool IsBuildOnlyContainer(this IResource resource) if (resource.TryGetLastAnnotation(out var computeEnvironmentAnnotation)) { // If you have a ComputeEnvironmentAnnotation, it means the resource is bound to a specific compute environment. - // Skip the annotation if it doesn't match the specified computeEnvironmentResource. + // Skip the annotation if it doesn't match the specified targetComputeEnvironment. if (targetComputeEnvironment is not null && targetComputeEnvironment != computeEnvironmentAnnotation.ComputeEnvironment) { return null; @@ -1024,7 +1024,16 @@ internal static bool IsBuildOnlyContainer(this IResource resource) throw new InvalidOperationException($"Resource '{resource.Name}' has multiple compute environments - '{computeEnvironmentNames}'. Please specify a single compute environment using 'WithComputeEnvironment'."); } - return annotations[0]; + var deploymentTargetAnnotation = annotations[0]; + + // If you have a DeploymentTargetAnnotation, it means the resource is bound to a specific compute environment. + // Skip the annotation if it doesn't match the specified targetComputeEnvironment. + if (targetComputeEnvironment is not null && targetComputeEnvironment != deploymentTargetAnnotation.ComputeEnvironment) + { + return null; + } + + return deploymentTargetAnnotation; } return null; } diff --git a/src/Aspire.Hosting/Pipelines/DistributedApplicationPipeline.cs b/src/Aspire.Hosting/Pipelines/DistributedApplicationPipeline.cs index 1e2bdad15da..41ea625621a 100644 --- a/src/Aspire.Hosting/Pipelines/DistributedApplicationPipeline.cs +++ b/src/Aspire.Hosting/Pipelines/DistributedApplicationPipeline.cs @@ -336,7 +336,7 @@ public DistributedApplicationPipeline() _steps.Add(new PipelineStep { - Name = "validate-compute-environments", + Name = WellKnownPipelineSteps.ValidateComputeEnvironments, Description = "Validates compute resource bindings before startup.", Action = static context => { diff --git a/src/Aspire.Hosting/Pipelines/WellKnownPipelineSteps.cs b/src/Aspire.Hosting/Pipelines/WellKnownPipelineSteps.cs index 0df1c31fe9b..dca3b069fcb 100644 --- a/src/Aspire.Hosting/Pipelines/WellKnownPipelineSteps.cs +++ b/src/Aspire.Hosting/Pipelines/WellKnownPipelineSteps.cs @@ -74,6 +74,12 @@ public static class WellKnownPipelineSteps [AspireValue("WellKnownPipelineSteps")] public const string Diagnostics = "diagnostics"; + /// + /// The step that validates compute resources are assigned to unambiguous compute environments. + /// + [AspireValue("WellKnownPipelineSteps")] + public const string ValidateComputeEnvironments = "validate-compute-environments"; + /// /// The step that runs before the application starts. /// diff --git a/tests/Aspire.Hosting.Azure.Tests/AzureDeployerTests.cs b/tests/Aspire.Hosting.Azure.Tests/AzureDeployerTests.cs index cb59c6a75c7..98833afb486 100644 --- a/tests/Aspire.Hosting.Azure.Tests/AzureDeployerTests.cs +++ b/tests/Aspire.Hosting.Azure.Tests/AzureDeployerTests.cs @@ -1271,6 +1271,36 @@ public async Task DeployAsync_WithRedisAccessKeyAuthentication_CreatesCorrectDep await Verify(logs); } + [Fact] + public async Task DeployAsync_WithFoundryAndAzureContainerApps_CreatesCorrectDependencies() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, step: "diagnostics"); + var mockActivityReporter = new TestPipelineActivityReporter(testOutputHelper); + ConfigureTestServices(builder, activityReporter: mockActivityReporter); + + var foundryProject = builder.AddFoundry("foundry") + .AddProject("foundry-project"); + var acaEnv = builder.AddAzureContainerAppEnvironment("aca-env"); + + builder.AddProject("agent", launchProfileName: null) + .PublishAsHostedAgent(foundryProject); + + builder.AddProject("api", launchProfileName: null) + .WithExternalHttpEndpoints() + .WithComputeEnvironment(acaEnv); + + using var app = builder.Build(); + await app.StartAsync(); + await app.WaitForShutdownAsync(); + + var logs = mockActivityReporter.LoggedMessages + .Where(s => s.StepTitle == "diagnostics") + .Select(s => s.Message) + .ToList(); + + await Verify(logs); + } + [Fact] public async Task DeployAsync_WithPrivateEndpoints_CreatesCorrectDependencies() { diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithAzureResourceDependencies_DoesNotHang_step=diagnostics.verified.txt b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithAzureResourceDependencies_DoesNotHang_step=diagnostics.verified.txt index 53773bb6d4b..a21d8c91380 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithAzureResourceDependencies_DoesNotHang_step=diagnostics.verified.txt +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithAzureResourceDependencies_DoesNotHang_step=diagnostics.verified.txt @@ -1,4 +1,4 @@ -[ +[ PIPELINE DEPENDENCY GRAPH DIAGNOSTICS ===================================== @@ -15,9 +15,9 @@ This shows the order in which steps would execute, respecting all dependencies. Steps with no dependencies run first, followed by steps that depend on them. 1. azure-prepare-resources - 2. prepare-azure-app-service-env - 3. validate-azure-app-service - 4. validate-compute-environments + 2. validate-compute-environments + 3. prepare-azure-app-service-env + 4. validate-azure-app-service 5. before-start 6. process-parameters 7. build-prereq @@ -127,7 +127,7 @@ Step: login-to-acr-env-acr Step: prepare-azure-app-service-env Description: Prepares Azure App Service deployment targets for env. - Dependencies: ✓ azure-prepare-resources + Dependencies: ✓ azure-prepare-resources, ✓ validate-compute-environments Resource: env (AzureAppServiceEnvironmentResource) Step: print-api-summary @@ -378,10 +378,10 @@ If targeting 'login-to-acr-env-acr': [5] login-to-acr-env-acr If targeting 'prepare-azure-app-service-env': - Direct dependencies: azure-prepare-resources - Total steps: 2 + Direct dependencies: azure-prepare-resources, validate-compute-environments + Total steps: 3 Execution order: - [0] azure-prepare-resources + [0] azure-prepare-resources | validate-compute-environments (parallel) [1] prepare-azure-app-service-env If targeting 'print-api-summary': @@ -600,4 +600,4 @@ If targeting 'validate-compute-environments': [0] validate-compute-environments -] +] \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithFoundryAndAzureContainerApps_CreatesCorrectDependencies.verified.txt b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithFoundryAndAzureContainerApps_CreatesCorrectDependencies.verified.txt new file mode 100644 index 00000000000..9964a2d210c --- /dev/null +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithFoundryAndAzureContainerApps_CreatesCorrectDependencies.verified.txt @@ -0,0 +1,696 @@ +[ +PIPELINE DEPENDENCY GRAPH DIAGNOSTICS +===================================== + +This diagnostic output shows the complete pipeline dependency graph structure. +Use this to understand step relationships and troubleshoot execution issues. + +Total steps defined: 42 + +Analysis for full pipeline execution (showing all steps and their relationships) + +EXECUTION ORDER +=============== +This shows the order in which steps would execute, respecting all dependencies. +Steps with no dependencies run first, followed by steps that depend on them. + + 1. azure-prepare-resources + 2. validate-compute-environments + 3. prepare-azure-container-apps-aca-env + 4. prepare-foundry-project-foundry-project + 5. validate-azure-container-apps + 6. before-start + 7. process-parameters + 8. build-prereq + 9. check-container-runtime + 10. deploy-prereq + 11. build-agent + 12. build-api + 13. build + 14. validate-azure-login + 15. create-provisioning-context + 16. provision-aca-env-acr + 17. provision-aca-env + 18. login-to-acr-aca-env-acr + 19. provision-foundry-project-acr + 20. login-to-acr-foundry-project-acr + 21. push-prereq + 22. push-api + 23. provision-api-containerapp + 24. provision-foundry + 25. provision-foundry-project + 26. provision-azure-bicep-resources + 27. compute-endpoints-foundry-project + 28. push-agent + 29. deploy-agent-ha + 30. print-api-summary + 31. print-dashboard-url-aca-env + 32. deploy + 33. deploy-api + 34. destroy-prereq + 35. destroy-azure-azure634f9 + 36. destroy + 37. diagnostics + 38. publish-prereq + 39. publish-azure634f9 + 40. publish + 41. publish-manifest + 42. push + +DETAILED STEP ANALYSIS +====================== +Shows each step's dependencies, associated resources, tags, and descriptions. +✓ = dependency exists, ? = dependency missing + +Step: azure-prepare-resources + Description: Prepares the Azure resources. + Dependencies: none + Resource: azure634f9 (AzureEnvironmentResource) + +Step: before-start + Description: Aggregation step for operations that run before the application starts. + Dependencies: ✓ azure-prepare-resources, ✓ prepare-azure-container-apps-aca-env, ✓ prepare-foundry-project-foundry-project, ✓ validate-azure-container-apps, ✓ validate-compute-environments + +Step: build + Description: Aggregation step for all build operations. All build steps should be required by this step. + Dependencies: ✓ build-agent, ✓ build-api + +Step: build-agent + Description: Builds the container image for the agent project. + Dependencies: ✓ build-prereq, ✓ check-container-runtime, ✓ deploy-prereq + Resource: agent (ProjectResource) + Tags: build-compute + +Step: build-api + Description: Builds the container image for the api project. + Dependencies: ✓ build-prereq, ✓ check-container-runtime, ✓ deploy-prereq + Resource: api (ProjectResource) + Tags: build-compute + +Step: build-prereq + Description: Prerequisite step that runs before any build operations. + Dependencies: ✓ process-parameters + +Step: check-container-runtime + Description: Checks whether the container runtime (Docker/Podman) is running. + Dependencies: none + +Step: compute-endpoints-foundry-project + Dependencies: ✓ provision-azure-bicep-resources + Resource: foundry-project (AzureCognitiveServicesProjectResource) + +Step: create-provisioning-context + Description: Creates the Azure provisioning context for infrastructure deployment. + Dependencies: ✓ deploy-prereq, ✓ validate-azure-login + Resource: azure634f9 (AzureEnvironmentResource) + +Step: deploy + Description: Aggregation step for all deploy operations. All deploy steps should be required by this step. + Dependencies: ✓ build-agent, ✓ build-api, ✓ compute-endpoints-foundry-project, ✓ create-provisioning-context, ✓ deploy-agent-ha, ✓ print-api-summary, ✓ print-dashboard-url-aca-env, ✓ provision-azure-bicep-resources, ✓ validate-azure-login + +Step: deploy-agent-ha + Dependencies: ✓ deploy-prereq, ✓ provision-azure-bicep-resources, ✓ push-agent + Resource: agent-ha (AzureHostedAgentResource) + Tags: deploy-compute + +Step: deploy-api + Description: Aggregation step for deploying api to Azure Container Apps. + Dependencies: ✓ print-api-summary + Resource: api-containerapp (AzureContainerAppResource) + Tags: deploy-compute + +Step: deploy-prereq + Description: Prerequisite step that runs before any deploy operations. Initializes deployment environment and manages deployment state. + Dependencies: ✓ process-parameters + +Step: destroy + Description: Aggregation step for all destroy operations. All destroy steps should be required by this step. + Dependencies: ✓ destroy-azure-azure634f9 + +Step: destroy-azure-azure634f9 + Description: Destroys the Azure resource group and all resources for azure634f9. + Dependencies: ✓ destroy-prereq + Resource: azure634f9 (AzureEnvironmentResource) + +Step: destroy-prereq + Description: Prerequisite step that runs before any destroy operations. + Dependencies: none + +Step: diagnostics + Description: Dumps dependency graph information for troubleshooting pipeline execution. + Dependencies: none + +Step: login-to-acr-aca-env-acr + Dependencies: ✓ provision-aca-env-acr + Resource: aca-env-acr (AzureContainerRegistryResource) + Tags: acr-login + +Step: login-to-acr-foundry-project-acr + Dependencies: ✓ provision-foundry-project-acr + Resource: foundry-project-acr (AzureContainerRegistryResource) + Tags: acr-login + +Step: prepare-azure-container-apps-aca-env + Description: Prepares Azure Container Apps deployment targets for aca-env. + Dependencies: ✓ azure-prepare-resources, ✓ validate-compute-environments + Resource: aca-env (AzureContainerAppEnvironmentResource) + +Step: prepare-foundry-project-foundry-project + Description: Prepares Microsoft Foundry project foundry-project for deployment. + Dependencies: ✓ azure-prepare-resources, ✓ validate-compute-environments + Resource: foundry-project (AzureCognitiveServicesProjectResource) + +Step: print-api-summary + Description: Prints the deployment summary and URL for api. + Dependencies: ✓ provision-api-containerapp + Resource: api-containerapp (AzureContainerAppResource) + Tags: print-summary + +Step: print-dashboard-url-aca-env + Description: Prints the deployment summary and dashboard URL for aca-env. + Dependencies: ✓ provision-aca-env, ✓ provision-azure-bicep-resources + Resource: aca-env (AzureContainerAppEnvironmentResource) + Tags: print-summary + +Step: process-parameters + Description: Prompts for parameter values before build, publish, or deployment operations. + Dependencies: none + +Step: provision-aca-env + Description: Provisions the Azure Bicep resource aca-env using Azure infrastructure. + Dependencies: ✓ create-provisioning-context, ✓ provision-aca-env-acr + Resource: aca-env (AzureContainerAppEnvironmentResource) + Tags: provision-infra + +Step: provision-aca-env-acr + Description: Provisions the Azure Bicep resource aca-env-acr using Azure infrastructure. + Dependencies: ✓ create-provisioning-context + Resource: aca-env-acr (AzureContainerRegistryResource) + Tags: provision-infra + +Step: provision-api-containerapp + Description: Provisions the Azure Bicep resource api-containerapp using Azure infrastructure. + Dependencies: ✓ create-provisioning-context, ✓ provision-aca-env, ✓ push-api + Resource: api-containerapp (AzureContainerAppResource) + Tags: provision-infra + +Step: provision-azure-bicep-resources + Description: Aggregation step for all Azure infrastructure provisioning operations. + Dependencies: ✓ create-provisioning-context, ✓ deploy-prereq, ✓ provision-aca-env, ✓ provision-aca-env-acr, ✓ provision-api-containerapp, ✓ provision-foundry, ✓ provision-foundry-project, ✓ provision-foundry-project-acr + Resource: azure634f9 (AzureEnvironmentResource) + Tags: provision-infra + +Step: provision-foundry + Description: Provisions the Azure Bicep resource foundry using Azure infrastructure. + Dependencies: ✓ create-provisioning-context + Resource: foundry (FoundryResource) + Tags: provision-infra + +Step: provision-foundry-project + Description: Provisions the Azure Bicep resource foundry-project using Azure infrastructure. + Dependencies: ✓ create-provisioning-context, ✓ provision-foundry, ✓ provision-foundry-project-acr + Resource: foundry-project (AzureCognitiveServicesProjectResource) + Tags: provision-infra + +Step: provision-foundry-project-acr + Description: Provisions the Azure Bicep resource foundry-project-acr using Azure infrastructure. + Dependencies: ✓ create-provisioning-context + Resource: foundry-project-acr (AzureContainerRegistryResource) + Tags: provision-infra + +Step: publish + Description: Aggregation step for all publish operations. All publish steps should be required by this step. + Dependencies: ✓ publish-azure634f9 + +Step: publish-azure634f9 + Description: Publishes the Azure environment configuration for azure634f9. + Dependencies: ✓ publish-prereq + Resource: azure634f9 (AzureEnvironmentResource) + +Step: publish-manifest + Description: Publishes the Aspire application model as a JSON manifest file. + Dependencies: none + +Step: publish-prereq + Description: Prerequisite step that runs before any publish operations. + Dependencies: ✓ process-parameters + +Step: push + Description: Aggregation step for all push operations. All push steps should be required by this step. + Dependencies: ✓ push-agent, ✓ push-api, ✓ push-prereq + +Step: push-agent + Dependencies: ✓ build-agent, ✓ push-prereq + Resource: agent (ProjectResource) + Tags: push-container-image + +Step: push-api + Dependencies: ✓ build-api, ✓ push-prereq + Resource: api (ProjectResource) + Tags: push-container-image + +Step: push-prereq + Description: Prerequisite step that runs before any push operations. + Dependencies: ✓ login-to-acr-aca-env-acr, ✓ login-to-acr-foundry-project-acr + +Step: validate-azure-container-apps + Dependencies: none + +Step: validate-azure-login + Description: Validates Azure CLI authentication before deployment. + Dependencies: ✓ deploy-prereq + Resource: azure634f9 (AzureEnvironmentResource) + +Step: validate-compute-environments + Description: Validates compute resource bindings before startup. + Dependencies: none + +POTENTIAL ISSUES: +Identifies problems in the pipeline configuration that could prevent execution. +───────────────── +INFO: Orphaned steps (no dependencies, not required by others): + - diagnostics + - publish-manifest + +EXECUTION SIMULATION ("What If" Analysis): +Shows what steps would run for each possible target step and in what order. +Steps at the same level can run concurrently. +───────────────────────────────────────────────────────────────────────────── +If targeting 'azure-prepare-resources': + Direct dependencies: none + Total steps: 1 + Execution order: + [0] azure-prepare-resources + +If targeting 'before-start': + Direct dependencies: azure-prepare-resources, prepare-azure-container-apps-aca-env, prepare-foundry-project-foundry-project, validate-azure-container-apps, validate-compute-environments + Total steps: 6 + Execution order: + [0] azure-prepare-resources | validate-azure-container-apps | validate-compute-environments (parallel) + [1] prepare-azure-container-apps-aca-env | prepare-foundry-project-foundry-project (parallel) + [2] before-start + +If targeting 'build': + Direct dependencies: build-agent, build-api + Total steps: 7 + Execution order: + [0] check-container-runtime | process-parameters (parallel) + [1] build-prereq | deploy-prereq (parallel) + [2] build-agent | build-api (parallel) + [3] build + +If targeting 'build-agent': + Direct dependencies: build-prereq, check-container-runtime, deploy-prereq + Total steps: 5 + Execution order: + [0] check-container-runtime | process-parameters (parallel) + [1] build-prereq | deploy-prereq (parallel) + [2] build-agent + +If targeting 'build-api': + Direct dependencies: build-prereq, check-container-runtime, deploy-prereq + Total steps: 5 + Execution order: + [0] check-container-runtime | process-parameters (parallel) + [1] build-prereq | deploy-prereq (parallel) + [2] build-api + +If targeting 'build-prereq': + Direct dependencies: process-parameters + Total steps: 2 + Execution order: + [0] process-parameters + [1] build-prereq + +If targeting 'check-container-runtime': + Direct dependencies: none + Total steps: 1 + Execution order: + [0] check-container-runtime + +If targeting 'compute-endpoints-foundry-project': + Direct dependencies: provision-azure-bicep-resources + Total steps: 19 + Execution order: + [0] check-container-runtime | process-parameters (parallel) + [1] build-prereq | deploy-prereq (parallel) + [2] build-api | validate-azure-login (parallel) + [3] create-provisioning-context + [4] provision-aca-env-acr | provision-foundry | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env | provision-foundry-project (parallel) + [6] push-prereq + [7] push-api + [8] provision-api-containerapp + [9] provision-azure-bicep-resources + [10] compute-endpoints-foundry-project + +If targeting 'create-provisioning-context': + Direct dependencies: deploy-prereq, validate-azure-login + Total steps: 4 + Execution order: + [0] process-parameters + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + +If targeting 'deploy': + Direct dependencies: build-agent, build-api, compute-endpoints-foundry-project, create-provisioning-context, deploy-agent-ha, print-api-summary, print-dashboard-url-aca-env, provision-azure-bicep-resources, validate-azure-login + Total steps: 25 + Execution order: + [0] check-container-runtime | process-parameters (parallel) + [1] build-prereq | deploy-prereq (parallel) + [2] build-agent | build-api | validate-azure-login (parallel) + [3] create-provisioning-context + [4] provision-aca-env-acr | provision-foundry | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env | provision-foundry-project (parallel) + [6] push-prereq + [7] push-agent | push-api (parallel) + [8] provision-api-containerapp + [9] print-api-summary | provision-azure-bicep-resources (parallel) + [10] compute-endpoints-foundry-project | deploy-agent-ha | print-dashboard-url-aca-env (parallel) + [11] deploy + +If targeting 'deploy-agent-ha': + Direct dependencies: deploy-prereq, provision-azure-bicep-resources, push-agent + Total steps: 21 + Execution order: + [0] check-container-runtime | process-parameters (parallel) + [1] build-prereq | deploy-prereq (parallel) + [2] build-agent | build-api | validate-azure-login (parallel) + [3] create-provisioning-context + [4] provision-aca-env-acr | provision-foundry | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env | provision-foundry-project (parallel) + [6] push-prereq + [7] push-agent | push-api (parallel) + [8] provision-api-containerapp + [9] provision-azure-bicep-resources + [10] deploy-agent-ha + +If targeting 'deploy-api': + Direct dependencies: print-api-summary + Total steps: 17 + Execution order: + [0] check-container-runtime | process-parameters (parallel) + [1] build-prereq | deploy-prereq (parallel) + [2] build-api | validate-azure-login (parallel) + [3] create-provisioning-context + [4] provision-aca-env-acr | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env (parallel) + [6] push-prereq + [7] push-api + [8] provision-api-containerapp + [9] print-api-summary + [10] deploy-api + +If targeting 'deploy-prereq': + Direct dependencies: process-parameters + Total steps: 2 + Execution order: + [0] process-parameters + [1] deploy-prereq + +If targeting 'destroy': + Direct dependencies: destroy-azure-azure634f9 + Total steps: 3 + Execution order: + [0] destroy-prereq + [1] destroy-azure-azure634f9 + [2] destroy + +If targeting 'destroy-azure-azure634f9': + Direct dependencies: destroy-prereq + Total steps: 2 + Execution order: + [0] destroy-prereq + [1] destroy-azure-azure634f9 + +If targeting 'destroy-prereq': + Direct dependencies: none + Total steps: 1 + Execution order: + [0] destroy-prereq + +If targeting 'diagnostics': + Direct dependencies: none + Total steps: 1 + Execution order: + [0] diagnostics + +If targeting 'login-to-acr-aca-env-acr': + Direct dependencies: provision-aca-env-acr + Total steps: 6 + Execution order: + [0] process-parameters + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-aca-env-acr + [5] login-to-acr-aca-env-acr + +If targeting 'login-to-acr-foundry-project-acr': + Direct dependencies: provision-foundry-project-acr + Total steps: 6 + Execution order: + [0] process-parameters + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-foundry-project-acr + [5] login-to-acr-foundry-project-acr + +If targeting 'prepare-azure-container-apps-aca-env': + Direct dependencies: azure-prepare-resources, validate-compute-environments + Total steps: 3 + Execution order: + [0] azure-prepare-resources | validate-compute-environments (parallel) + [1] prepare-azure-container-apps-aca-env + +If targeting 'prepare-foundry-project-foundry-project': + Direct dependencies: azure-prepare-resources, validate-compute-environments + Total steps: 3 + Execution order: + [0] azure-prepare-resources | validate-compute-environments (parallel) + [1] prepare-foundry-project-foundry-project + +If targeting 'print-api-summary': + Direct dependencies: provision-api-containerapp + Total steps: 16 + Execution order: + [0] check-container-runtime | process-parameters (parallel) + [1] build-prereq | deploy-prereq (parallel) + [2] build-api | validate-azure-login (parallel) + [3] create-provisioning-context + [4] provision-aca-env-acr | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env (parallel) + [6] push-prereq + [7] push-api + [8] provision-api-containerapp + [9] print-api-summary + +If targeting 'print-dashboard-url-aca-env': + Direct dependencies: provision-aca-env, provision-azure-bicep-resources + Total steps: 19 + Execution order: + [0] check-container-runtime | process-parameters (parallel) + [1] build-prereq | deploy-prereq (parallel) + [2] build-api | validate-azure-login (parallel) + [3] create-provisioning-context + [4] provision-aca-env-acr | provision-foundry | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env | provision-foundry-project (parallel) + [6] push-prereq + [7] push-api + [8] provision-api-containerapp + [9] provision-azure-bicep-resources + [10] print-dashboard-url-aca-env + +If targeting 'process-parameters': + Direct dependencies: none + Total steps: 1 + Execution order: + [0] process-parameters + +If targeting 'provision-aca-env': + Direct dependencies: create-provisioning-context, provision-aca-env-acr + Total steps: 6 + Execution order: + [0] process-parameters + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-aca-env-acr + [5] provision-aca-env + +If targeting 'provision-aca-env-acr': + Direct dependencies: create-provisioning-context + Total steps: 5 + Execution order: + [0] process-parameters + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-aca-env-acr + +If targeting 'provision-api-containerapp': + Direct dependencies: create-provisioning-context, provision-aca-env, push-api + Total steps: 15 + Execution order: + [0] check-container-runtime | process-parameters (parallel) + [1] build-prereq | deploy-prereq (parallel) + [2] build-api | validate-azure-login (parallel) + [3] create-provisioning-context + [4] provision-aca-env-acr | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env (parallel) + [6] push-prereq + [7] push-api + [8] provision-api-containerapp + +If targeting 'provision-azure-bicep-resources': + Direct dependencies: create-provisioning-context, deploy-prereq, provision-aca-env, provision-aca-env-acr, provision-api-containerapp, provision-foundry, provision-foundry-project, provision-foundry-project-acr + Total steps: 18 + Execution order: + [0] check-container-runtime | process-parameters (parallel) + [1] build-prereq | deploy-prereq (parallel) + [2] build-api | validate-azure-login (parallel) + [3] create-provisioning-context + [4] provision-aca-env-acr | provision-foundry | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env | provision-foundry-project (parallel) + [6] push-prereq + [7] push-api + [8] provision-api-containerapp + [9] provision-azure-bicep-resources + +If targeting 'provision-foundry': + Direct dependencies: create-provisioning-context + Total steps: 5 + Execution order: + [0] process-parameters + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-foundry + +If targeting 'provision-foundry-project': + Direct dependencies: create-provisioning-context, provision-foundry, provision-foundry-project-acr + Total steps: 7 + Execution order: + [0] process-parameters + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-foundry | provision-foundry-project-acr (parallel) + [5] provision-foundry-project + +If targeting 'provision-foundry-project-acr': + Direct dependencies: create-provisioning-context + Total steps: 5 + Execution order: + [0] process-parameters + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-foundry-project-acr + +If targeting 'publish': + Direct dependencies: publish-azure634f9 + Total steps: 4 + Execution order: + [0] process-parameters + [1] publish-prereq + [2] publish-azure634f9 + [3] publish + +If targeting 'publish-azure634f9': + Direct dependencies: publish-prereq + Total steps: 3 + Execution order: + [0] process-parameters + [1] publish-prereq + [2] publish-azure634f9 + +If targeting 'publish-manifest': + Direct dependencies: none + Total steps: 1 + Execution order: + [0] publish-manifest + +If targeting 'publish-prereq': + Direct dependencies: process-parameters + Total steps: 2 + Execution order: + [0] process-parameters + [1] publish-prereq + +If targeting 'push': + Direct dependencies: push-agent, push-api, push-prereq + Total steps: 16 + Execution order: + [0] check-container-runtime | process-parameters (parallel) + [1] build-prereq | deploy-prereq (parallel) + [2] build-agent | build-api | validate-azure-login (parallel) + [3] create-provisioning-context + [4] provision-aca-env-acr | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr (parallel) + [6] push-prereq + [7] push-agent | push-api (parallel) + [8] push + +If targeting 'push-agent': + Direct dependencies: build-agent, push-prereq + Total steps: 13 + Execution order: + [0] check-container-runtime | process-parameters (parallel) + [1] build-prereq | deploy-prereq (parallel) + [2] build-agent | validate-azure-login (parallel) + [3] create-provisioning-context + [4] provision-aca-env-acr | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr (parallel) + [6] push-prereq + [7] push-agent + +If targeting 'push-api': + Direct dependencies: build-api, push-prereq + Total steps: 13 + Execution order: + [0] check-container-runtime | process-parameters (parallel) + [1] build-prereq | deploy-prereq (parallel) + [2] build-api | validate-azure-login (parallel) + [3] create-provisioning-context + [4] provision-aca-env-acr | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr (parallel) + [6] push-prereq + [7] push-api + +If targeting 'push-prereq': + Direct dependencies: login-to-acr-aca-env-acr, login-to-acr-foundry-project-acr + Total steps: 9 + Execution order: + [0] process-parameters + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-aca-env-acr | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr (parallel) + [6] push-prereq + +If targeting 'validate-azure-container-apps': + Direct dependencies: none + Total steps: 1 + Execution order: + [0] validate-azure-container-apps + +If targeting 'validate-azure-login': + Direct dependencies: deploy-prereq + Total steps: 3 + Execution order: + [0] process-parameters + [1] deploy-prereq + [2] validate-azure-login + +If targeting 'validate-compute-environments': + Direct dependencies: none + Total steps: 1 + Execution order: + [0] validate-compute-environments + + +] \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithMultipleComputeEnvironments_Works_step=diagnostics.verified.txt b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithMultipleComputeEnvironments_Works_step=diagnostics.verified.txt index c4d840f8c50..531661150c9 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithMultipleComputeEnvironments_Works_step=diagnostics.verified.txt +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithMultipleComputeEnvironments_Works_step=diagnostics.verified.txt @@ -1,4 +1,4 @@ -[ +[ PIPELINE DEPENDENCY GRAPH DIAGNOSTICS ===================================== @@ -15,11 +15,11 @@ This shows the order in which steps would execute, respecting all dependencies. Steps with no dependencies run first, followed by steps that depend on them. 1. azure-prepare-resources - 2. prepare-azure-app-service-aas-env - 3. prepare-azure-container-apps-aca-env - 4. validate-azure-app-service - 5. validate-azure-container-apps - 6. validate-compute-environments + 2. validate-compute-environments + 3. prepare-azure-app-service-aas-env + 4. prepare-azure-container-apps-aca-env + 5. validate-azure-app-service + 6. validate-azure-container-apps 7. before-start 8. process-parameters 9. build-prereq @@ -161,12 +161,12 @@ Step: login-to-acr-aca-env-acr Step: prepare-azure-app-service-aas-env Description: Prepares Azure App Service deployment targets for aas-env. - Dependencies: ✓ azure-prepare-resources + Dependencies: ✓ azure-prepare-resources, ✓ validate-compute-environments Resource: aas-env (AzureAppServiceEnvironmentResource) Step: prepare-azure-container-apps-aca-env Description: Prepares Azure Container Apps deployment targets for aca-env. - Dependencies: ✓ azure-prepare-resources + Dependencies: ✓ azure-prepare-resources, ✓ validate-compute-environments Resource: aca-env (AzureContainerAppEnvironmentResource) Step: print-api-service-summary @@ -504,17 +504,17 @@ If targeting 'login-to-acr-aca-env-acr': [5] login-to-acr-aca-env-acr If targeting 'prepare-azure-app-service-aas-env': - Direct dependencies: azure-prepare-resources - Total steps: 2 + Direct dependencies: azure-prepare-resources, validate-compute-environments + Total steps: 3 Execution order: - [0] azure-prepare-resources + [0] azure-prepare-resources | validate-compute-environments (parallel) [1] prepare-azure-app-service-aas-env If targeting 'prepare-azure-container-apps-aca-env': - Direct dependencies: azure-prepare-resources - Total steps: 2 + Direct dependencies: azure-prepare-resources, validate-compute-environments + Total steps: 3 Execution order: - [0] azure-prepare-resources + [0] azure-prepare-resources | validate-compute-environments (parallel) [1] prepare-azure-container-apps-aca-env If targeting 'print-api-service-summary': @@ -822,4 +822,4 @@ If targeting 'validate-compute-environments': [0] validate-compute-environments -] +] \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithPrivateEndpoints_CreatesCorrectDependencies.verified.txt b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithPrivateEndpoints_CreatesCorrectDependencies.verified.txt index 1350cc2aaf6..2423ce98bca 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithPrivateEndpoints_CreatesCorrectDependencies.verified.txt +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithPrivateEndpoints_CreatesCorrectDependencies.verified.txt @@ -1,4 +1,4 @@ -[ +[ PIPELINE DEPENDENCY GRAPH DIAGNOSTICS ===================================== @@ -15,9 +15,9 @@ This shows the order in which steps would execute, respecting all dependencies. Steps with no dependencies run first, followed by steps that depend on them. 1. azure-prepare-resources - 2. prepare-azure-container-apps-env - 3. validate-azure-container-apps - 4. validate-compute-environments + 2. validate-compute-environments + 3. prepare-azure-container-apps-env + 4. validate-azure-container-apps 5. before-start 6. process-parameters 7. build-prereq @@ -139,7 +139,7 @@ Step: login-to-acr-env-acr Step: prepare-azure-container-apps-env Description: Prepares Azure Container Apps deployment targets for env. - Dependencies: ✓ azure-prepare-resources + Dependencies: ✓ azure-prepare-resources, ✓ validate-compute-environments Resource: env (AzureContainerAppEnvironmentResource) Step: print-api-summary @@ -465,10 +465,10 @@ If targeting 'login-to-acr-env-acr': [5] login-to-acr-env-acr If targeting 'prepare-azure-container-apps-env': - Direct dependencies: azure-prepare-resources - Total steps: 2 + Direct dependencies: azure-prepare-resources, validate-compute-environments + Total steps: 3 Execution order: - [0] azure-prepare-resources + [0] azure-prepare-resources | validate-compute-environments (parallel) [1] prepare-azure-container-apps-env If targeting 'print-api-summary': @@ -836,4 +836,4 @@ If targeting 'validate-compute-environments': [0] validate-compute-environments -] +] \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithRedisAccessKeyAuthentication_CreatesCorrectDependencies.verified.txt b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithRedisAccessKeyAuthentication_CreatesCorrectDependencies.verified.txt index 9a3c1a42fa4..c0bcc1c442b 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithRedisAccessKeyAuthentication_CreatesCorrectDependencies.verified.txt +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithRedisAccessKeyAuthentication_CreatesCorrectDependencies.verified.txt @@ -1,4 +1,4 @@ -[ +[ PIPELINE DEPENDENCY GRAPH DIAGNOSTICS ===================================== @@ -15,9 +15,9 @@ This shows the order in which steps would execute, respecting all dependencies. Steps with no dependencies run first, followed by steps that depend on them. 1. azure-prepare-resources - 2. prepare-azure-app-service-env - 3. validate-azure-app-service - 4. validate-compute-environments + 2. validate-compute-environments + 3. prepare-azure-app-service-env + 4. validate-azure-app-service 5. before-start 6. process-parameters 7. build-prereq @@ -134,7 +134,7 @@ Step: login-to-acr-env-acr Step: prepare-azure-app-service-env Description: Prepares Azure App Service deployment targets for env. - Dependencies: ✓ azure-prepare-resources + Dependencies: ✓ azure-prepare-resources, ✓ validate-compute-environments Resource: env (AzureAppServiceEnvironmentResource) Step: print-api-summary @@ -427,10 +427,10 @@ If targeting 'login-to-acr-env-acr': [5] login-to-acr-env-acr If targeting 'prepare-azure-app-service-env': - Direct dependencies: azure-prepare-resources - Total steps: 2 + Direct dependencies: azure-prepare-resources, validate-compute-environments + Total steps: 3 Execution order: - [0] azure-prepare-resources + [0] azure-prepare-resources | validate-compute-environments (parallel) [1] prepare-azure-app-service-env If targeting 'print-api-summary': @@ -724,4 +724,4 @@ If targeting 'validate-compute-environments': [0] validate-compute-environments -] +] \ No newline at end of file diff --git a/tests/Aspire.Hosting.Tests/ResourceExtensionsTests.cs b/tests/Aspire.Hosting.Tests/ResourceExtensionsTests.cs index e30ae623550..87b4793d550 100644 --- a/tests/Aspire.Hosting.Tests/ResourceExtensionsTests.cs +++ b/tests/Aspire.Hosting.Tests/ResourceExtensionsTests.cs @@ -144,6 +144,25 @@ public void TryGetAnnotationsIncludingAncestorsOfTypeCombinesAnnotationsFromPare Assert.Equal(3, annotations.Count()); } + [Fact] + public void GetDeploymentTargetAnnotation_ReturnsNullForDifferentTargetComputeEnvironment() + { + using var builder = TestDistributedApplicationBuilder.Create(); + var requestedEnvironment = builder.AddResource(new ComputeEnvironmentResource("env1")); + var annotationEnvironment = builder.AddResource(new ComputeEnvironmentResource("env2")); + var deploymentTarget = builder.AddResource(new ParentResource("target")); + + var resource = builder.AddResource(new ParentResource("resource")) + .WithAnnotation(new DeploymentTargetAnnotation(deploymentTarget.Resource) + { + ComputeEnvironment = annotationEnvironment.Resource + }); + + var annotation = resource.Resource.GetDeploymentTargetAnnotation(requestedEnvironment.Resource); + + Assert.Null(annotation); + } + [Fact] public void TryGetContainerImageNameReturnsCorrectFormatWhenShaSupplied() { From d400f662b6f7340dcc0d16e3640d7a81c7047a5b Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Wed, 29 Apr 2026 18:06:56 -0500 Subject: [PATCH 2/2] Fix tests --- .../Snapshots/TwoPassScanningGeneratedAspire.verified.go | 2 ++ .../Snapshots/TwoPassScanningGeneratedAspire.verified.java | 3 +++ .../Snapshots/TwoPassScanningGeneratedAspire.verified.py | 2 ++ .../Snapshots/TwoPassScanningGeneratedAspire.verified.rs | 5 +++++ .../Snapshots/TwoPassScanningGeneratedAspire.verified.ts | 3 +++ 5 files changed, 15 insertions(+) diff --git a/tests/Aspire.Hosting.CodeGeneration.Go.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.go b/tests/Aspire.Hosting.CodeGeneration.Go.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.go index df102d0f896..96d373bcc0f 100644 --- a/tests/Aspire.Hosting.CodeGeneration.Go.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.go +++ b/tests/Aspire.Hosting.CodeGeneration.Go.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.go @@ -574,6 +574,7 @@ var WellKnownPipelineSteps = struct { PublishPrereq string Push string PushPrereq string + ValidateComputeEnvironments string }{ Build: "build", BuildPrereq: "build-prereq", @@ -587,6 +588,7 @@ var WellKnownPipelineSteps = struct { PublishPrereq: "publish-prereq", Push: "push", PushPrereq: "push-prereq", + ValidateComputeEnvironments: "validate-compute-environments", } var WellKnownPipelineTags = struct { diff --git a/tests/Aspire.Hosting.CodeGeneration.Java.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.java b/tests/Aspire.Hosting.CodeGeneration.Java.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.java index 3efb0f95a8f..b27d5752d92 100644 --- a/tests/Aspire.Hosting.CodeGeneration.Java.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.java +++ b/tests/Aspire.Hosting.CodeGeneration.Java.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.java @@ -22438,6 +22438,9 @@ private WellKnownPipelineSteps() { } /** The prerequisite step that runs before any push operations. */ public static final String PushPrereq = "push-prereq"; + /** The step that validates compute resources are assigned to unambiguous compute environments. */ + public static final String ValidateComputeEnvironments = "validate-compute-environments"; + } // ===== WellKnownPipelineTags.java ===== diff --git a/tests/Aspire.Hosting.CodeGeneration.Python.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.py b/tests/Aspire.Hosting.CodeGeneration.Python.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.py index 989c53c47da..e0f5c405739 100644 --- a/tests/Aspire.Hosting.CodeGeneration.Python.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.py +++ b/tests/Aspire.Hosting.CodeGeneration.Python.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.py @@ -1864,6 +1864,8 @@ class TestNestedDto(typing.TypedDict, total=False): WellKnownPipelineSteps.Push = "push" # The prerequisite step that runs before any push operations. WellKnownPipelineSteps.PushPrereq = "push-prereq" +# The step that validates compute resources are assigned to unambiguous compute environments. +WellKnownPipelineSteps.ValidateComputeEnvironments = "validate-compute-environments" WellKnownPipelineTags = types.SimpleNamespace() # Tag for steps that build compute resources. diff --git a/tests/Aspire.Hosting.CodeGeneration.Rust.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.rs b/tests/Aspire.Hosting.CodeGeneration.Rust.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.rs index 579ab8666d6..e1f5035b52f 100644 --- a/tests/Aspire.Hosting.CodeGeneration.Rust.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.rs +++ b/tests/Aspire.Hosting.CodeGeneration.Rust.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.rs @@ -1020,6 +1020,11 @@ pub mod well_known_pipeline_steps { serde_json::from_value::(serde_json::json!("push-prereq")) .expect("generated exported value should deserialize") } + /// The step that validates compute resources are assigned to unambiguous compute environments. + pub fn validate_compute_environments() -> String { + serde_json::from_value::(serde_json::json!("validate-compute-environments")) + .expect("generated exported value should deserialize") + } } pub mod well_known_pipeline_tags { diff --git a/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts b/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts index 3b02b64a29a..fbfb93d7f97 100644 --- a/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts +++ b/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts @@ -647,6 +647,9 @@ export namespace WellKnownPipelineSteps { /** The prerequisite step that runs before any push operations. */ export const PushPrereq = "push-prereq"; + /** The step that validates compute resources are assigned to unambiguous compute environments. */ + export const ValidateComputeEnvironments = "validate-compute-environments"; + } export namespace WellKnownPipelineTags {