Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
8 changes: 6 additions & 2 deletions src/Aspire.Cli/Projects/DotNetAppHostProject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ public async Task<int> RunAsync(AppHostProjectContext context, CancellationToken

try
{
if (!watch && !context.NoBuild)
if (!context.NoBuild)
{
// Build in CLI if either not running under extension host, or the extension reports 'build-dotnet-using-cli' capability.
Comment thread
Bertolossi marked this conversation as resolved.
var extensionHasBuildCapability = extensionBackchannel is not null && await extensionBackchannel.HasCapabilityAsync(KnownCapabilities.BuildDotnetUsingCli, cancellationToken);
Expand Down Expand Up @@ -338,7 +338,11 @@ public async Task<int> RunAsync(AppHostProjectContext context, CancellationToken
// Start the apphost - the runner will signal the backchannel when ready
try
{
// noBuild: true if either watch mode is off (we already built above) or --no-build was passed
// The app host may already have been built above (in the CLI, or by the extension).
// For non-watch runs we pass noBuild=true so dotnet run doesn't rebuild. For watch runs
// we leave builds enabled unless the user explicitly requested --no-build, so dotnet watch
// can perform its own build/incremental build and hot reload even if an up-front build
// already happened earlier in this method.
// noRestore: only relevant when noBuild is false (since --no-build implies --no-restore)
var noBuild = !watch || context.NoBuild;
return await _runner.RunAsync(
Expand Down
53 changes: 53 additions & 0 deletions tests/Aspire.Cli.Tests/Commands/RunCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,59 @@ public async Task RunCommand_WhenDefaultWatchEnabledFeatureFlagIsTrue_UsesWatchM
Assert.True(watchModeUsed, "Expected watch mode to be enabled when defaultWatchEnabled feature flag is true");
}

[Fact]
public async Task RunCommand_WhenDefaultWatchEnabledFeatureFlagIsTrueAndBuildFails_ReturnsBuildFailure()
{
var runCalled = false;

var runnerFactory = (IServiceProvider sp) =>
{
var runner = new TestDotNetCliRunner();
runner.BuildAsyncCallback = (projectFile, noRestore, options, ct) =>
{
options.StandardErrorCallback?.Invoke("error CS0103: The name 'MissingSymbol' does not exist in the current context");
return 1;
Comment thread
Bertolossi marked this conversation as resolved.
};

runner.GetAppHostInformationAsyncCallback = (projectFile, options, ct) => (0, true, VersionHelper.GetDefaultTemplateVersion());

runner.RunAsyncCallback = (projectFile, watch, noBuild, noRestore, args, env, backchannelCompletionSource, options, ct) =>
{
runCalled = true;
return Task.FromResult(0);
};

return runner;
};

var backchannelFactory = (IServiceProvider sp) =>
{
var backchannel = new TestAppHostBackchannel();
backchannel.GetAppHostLogEntriesAsyncCallback = ReturnLogEntriesUntilCancelledAsync;
return backchannel;
};

var projectLocatorFactory = (IServiceProvider sp) => new TestProjectLocator();

using var workspace = TemporaryWorkspace.Create(outputHelper);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, options =>
{
options.ProjectLocatorFactory = projectLocatorFactory;
options.AppHostBackchannelFactory = backchannelFactory;
options.DotNetCliRunnerFactory = runnerFactory;
options.EnabledFeatures = [KnownFeatures.DefaultWatchEnabled];
});

using var provider = services.BuildServiceProvider();
var command = provider.GetRequiredService<RootCommand>();
var result = command.Parse("run");

var exitCode = await result.InvokeAsync().DefaultTimeout();

Assert.Equal(ExitCodeConstants.FailedToBuildArtifacts, exitCode);
Assert.False(runCalled, "The AppHost should not be started when the initial build fails in watch mode.");
}

[Fact]
public async Task RunCommand_WhenDefaultWatchEnabledFeatureFlagIsFalse_DoesNotUseWatchMode()
{
Expand Down
Loading