diff --git a/src/Aspire.Hosting.Azure/AzureResourcePreparer.cs b/src/Aspire.Hosting.Azure/AzureResourcePreparer.cs index f2423151be8..4030996136b 100644 --- a/src/Aspire.Hosting.Azure/AzureResourcePreparer.cs +++ b/src/Aspire.Hosting.Azure/AzureResourcePreparer.cs @@ -380,7 +380,10 @@ private async Task> GetAzureReferences(IResource resourc if (resource.TryGetAnnotationsOfType(out var commandLineArgsCallbackAnnotations)) { - var context = new CommandLineArgsCallbackContext([], resource, cancellationToken: cancellationToken); + var context = new CommandLineArgsCallbackContext([], resource, cancellationToken: cancellationToken) + { + ExecutionContext = executionContext + }; foreach (var c in commandLineArgsCallbackAnnotations) { diff --git a/src/Aspire.Hosting/ResourceBuilderExtensions.cs b/src/Aspire.Hosting/ResourceBuilderExtensions.cs index 129c5e0e5f4..911f09ee8e5 100644 --- a/src/Aspire.Hosting/ResourceBuilderExtensions.cs +++ b/src/Aspire.Hosting/ResourceBuilderExtensions.cs @@ -2310,15 +2310,15 @@ public static IResourceBuilder WithVSCodeDebugSupport(this IResourceBuilde ArgumentException.ThrowIfNullOrWhiteSpace(projectPath); ArgumentException.ThrowIfNullOrWhiteSpace(debugAdapterId); + if (!builder.ApplicationBuilder.ExecutionContext.IsRunMode) + { + return builder; + } + if (builder is IResourceBuilder resourceWithArgs) { resourceWithArgs.WithArgs(ctx => { - if (!ctx.ExecutionContext.IsRunMode) - { - return; - } - var config = ctx.ExecutionContext.ServiceProvider.GetRequiredService(); if (ExtensionUtils.IsExtensionHost(config) && argsCallback is not null) { diff --git a/tests/Aspire.Hosting.Azure.Tests/AzureResourcePreparerTests.cs b/tests/Aspire.Hosting.Azure.Tests/AzureResourcePreparerTests.cs index af04b88e227..96af844a4c7 100644 --- a/tests/Aspire.Hosting.Azure.Tests/AzureResourcePreparerTests.cs +++ b/tests/Aspire.Hosting.Azure.Tests/AzureResourcePreparerTests.cs @@ -235,6 +235,33 @@ public async Task NullCommandLineArgIsIgnored() Assert.True(true); } + [Fact] + public async Task CommandLineArgsCallbackContextHasCorrectExecutionContextDuringPublish() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + builder.AddAzureContainerAppEnvironment("env"); + + DistributedApplicationExecutionContext? capturedExecutionContext = null; + + // Create a project with a WithArgs callback that captures the ExecutionContext + var api = builder.AddProject("api", launchProfileName: null) + .WithArgs(context => + { + // Capture the ExecutionContext to verify it's set correctly + capturedExecutionContext = context.ExecutionContext; + }); + + using var app = builder.Build(); + + // This should not throw - the ExecutionContext should be set correctly + await ExecuteBeforeStartHooksAsync(app, default); + + // Verify the ExecutionContext was captured and is in Publish mode + Assert.NotNull(capturedExecutionContext); + Assert.True(capturedExecutionContext.IsPublishMode); + Assert.False(capturedExecutionContext.IsRunMode); + } + private sealed class Project : IProjectMetadata { public string ProjectPath => "project"; diff --git a/tests/Aspire.Hosting.Tests/ExecutableResourceBuilderExtensionTests.cs b/tests/Aspire.Hosting.Tests/ExecutableResourceBuilderExtensionTests.cs index 2d8818f1277..db6a2f60bb6 100644 --- a/tests/Aspire.Hosting.Tests/ExecutableResourceBuilderExtensionTests.cs +++ b/tests/Aspire.Hosting.Tests/ExecutableResourceBuilderExtensionTests.cs @@ -1,5 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. + +#pragma warning disable ASPIREEXTENSION001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. +#pragma warning disable IDE0005 // Using directive is unnecessary. + +using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Utils; namespace Aspire.Hosting.Tests; @@ -65,4 +70,29 @@ public void WithWorkingDirectoryAllowsEmptyString() var annotation = executable.Resource.Annotations.OfType().Single(); Assert.Equal(builder.AppHostDirectory, annotation.WorkingDirectory); } + + [Fact] + public void WithVSCodeDebugSupportAddsAnnotationInRunMode() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Run); + var executable = builder.AddExecutable("myexe", "command", "workingdirectory") + .WithVSCodeDebugSupport("project.py", "python", "ms-python.python"); + + var annotation = executable.Resource.Annotations.OfType().SingleOrDefault(); + Assert.NotNull(annotation); + Assert.Equal("project.py", annotation.ProjectPath); + Assert.Equal("python", annotation.DebugAdapterId); + Assert.Equal("ms-python.python", annotation.RequiredExtensionId); + } + + [Fact] + public void WithVSCodeDebugSupportDoesNotAddAnnotationInPublishMode() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + var executable = builder.AddExecutable("myexe", "command", "workingdirectory") + .WithVSCodeDebugSupport("project.py", "python", "ms-python.python"); + + var annotation = executable.Resource.Annotations.OfType().SingleOrDefault(); + Assert.Null(annotation); + } } \ No newline at end of file