Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/Aspire.Hosting.Azure/AzureResourcePreparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,10 @@ private async Task<HashSet<IAzureResource>> GetAzureReferences(IResource resourc

if (resource.TryGetAnnotationsOfType<CommandLineArgsCallbackAnnotation>(out var commandLineArgsCallbackAnnotations))
{
var context = new CommandLineArgsCallbackContext([], resource, cancellationToken: cancellationToken);
var context = new CommandLineArgsCallbackContext([], resource, cancellationToken: cancellationToken)
{
ExecutionContext = executionContext
};

foreach (var c in commandLineArgsCallbackAnnotations)
{
Expand Down
7 changes: 1 addition & 6 deletions src/Aspire.Hosting/ResourceBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2310,15 +2310,10 @@ public static IResourceBuilder<T> WithVSCodeDebugSupport<T>(this IResourceBuilde
ArgumentException.ThrowIfNullOrWhiteSpace(projectPath);
ArgumentException.ThrowIfNullOrWhiteSpace(debugAdapterId);

if (builder is IResourceBuilder<IResourceWithArgs> resourceWithArgs)
if (builder.ApplicationBuilder.ExecutionContext.IsRunMode && builder is IResourceBuilder<IResourceWithArgs> resourceWithArgs)
{
resourceWithArgs.WithArgs(ctx =>
{
if (!ctx.ExecutionContext.IsRunMode)
{
return;
}

var config = ctx.ExecutionContext.ServiceProvider.GetRequiredService<IConfiguration>();
if (ExtensionUtils.IsExtensionHost(config) && argsCallback is not null)
{
Expand Down
32 changes: 32 additions & 0 deletions tests/Aspire.Hosting.Azure.Tests/AzureResourcePreparerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,38 @@ public async Task NullCommandLineArgIsIgnored()
Assert.True(true);
}

[Fact]
public async Task CommandLineArgsCallbackContextHasCorrectExecutionContextDuringPublish()
{
using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish);
builder.AddAzureContainerAppEnvironment("env");

// Create a project with a WithArgs callback that checks IsRunMode before accessing ServiceProvider
// This simulates what WithVSCodeDebugSupport does
var api = builder.AddProject<Project>("api", launchProfileName: null)
.WithArgs(context =>
{
// This simulates WithVSCodeDebugSupport behavior - checking IsRunMode before accessing ServiceProvider
if (!context.ExecutionContext.IsRunMode)
{
return;
}

// This should not be reached during publish mode, but if the ExecutionContext is not set correctly,
// it will default to Run mode and then try to access ServiceProvider which will throw
_ = context.ExecutionContext.ServiceProvider;
Copy link
Member

Choose a reason for hiding this comment

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

  1. we don't need the IsRunMode check. That can be removed.
  2. You can set the IServiceProvider to a variable outside of the callback on line 243, and then Assert that it is not null at the end of the test on line 267.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in d421906. Removed the IsRunMode check and updated the test to capture the ExecutionContext and assert it's not null and in Publish mode.

});

using var app = builder.Build();

// This should not throw because ExecutionContext should be set to Publish mode
// and the IsRunMode check should prevent accessing ServiceProvider
await ExecuteBeforeStartHooksAsync(app, default);

// Test passes if we reach this point without exceptions
Assert.True(true);
}

private sealed class Project : IProjectMetadata
{
public string ProjectPath => "project";
Expand Down