Skip to content
Closed
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
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<!-- This repo version -->
<MajorVersion>13</MajorVersion>
<MinorVersion>3</MinorVersion>
<PatchVersion>4</PatchVersion>
<PatchVersion>5</PatchVersion>
<VersionPrefix>$(MajorVersion).$(MinorVersion).$(PatchVersion)</VersionPrefix>
<PreReleaseVersionLabel>preview.1</PreReleaseVersionLabel>
<DefaultTargetFramework>net8.0</DefaultTargetFramework>
Expand Down
6 changes: 5 additions & 1 deletion eng/pipelines/azure-pipelines-unofficial.yml
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,11 @@ extends:
enableMicrobuild: false
enablePublishUsingPipelines: false
enablePublishBuildAssets: false
enablePublishBuildArtifacts: true
# WinGet and Homebrew jobs only consume previously-built CLI archives;
# they don't run the repo build, so artifacts/log/$(_BuildConfig) is
# never created. Leaving this 'true' makes the 1ES Publish Logs output
# fail because its targetPath doesn't exist.
enablePublishBuildArtifacts: false
enableTelemetry: true
workspace:
clean: all
Expand Down
6 changes: 5 additions & 1 deletion eng/pipelines/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,11 @@ extends:
enableMicrobuild: false
enablePublishUsingPipelines: false
enablePublishBuildAssets: false
enablePublishBuildArtifacts: true
# WinGet and Homebrew jobs only consume previously-built CLI archives;
# they don't run the repo build, so artifacts/log/$(_BuildConfig) is
# never created. Leaving this 'true' makes the 1ES Publish Logs output
# fail because its targetPath doesn't exist.
enablePublishBuildArtifacts: false
enableTelemetry: true
workspace:
clean: all
Expand Down
19 changes: 1 addition & 18 deletions src/Aspire.Cli/DotNet/DotNetCliRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,6 @@ internal sealed class DotNetCliRunner(
private const int MaxSearchRetries = 3;
private static readonly TimeSpan[] s_searchRetryDelays = [TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2)];

private string GetMsBuildServerValue()
{
return configuration["DOTNET_CLI_USE_MSBUILD_SERVER"] ?? "true";
}

internal static string GetBackchannelSocketPath()
{
return CliPathHelper.CreateUnixDomainSocketPath("cli.sock");
Expand Down Expand Up @@ -520,12 +515,6 @@ public async Task<int> RunAsync(FileInfo projectFile, bool watch, bool noBuild,
// We copy the dictionary here because we don't want to mutate the input.
var finalEnv = env?.ToDictionary() ?? new Dictionary<string, string>();

// Inject DOTNET_CLI_USE_MSBUILD_SERVER when noBuild == false
if (!noBuild)
{
finalEnv["DOTNET_CLI_USE_MSBUILD_SERVER"] = GetMsBuildServerValue();
}

// Check if update notifications are disabled and set version check environment variable
if (!features.IsFeatureEnabled(KnownFeatures.UpdateNotificationsEnabled, defaultValue: true))
{
Expand Down Expand Up @@ -808,15 +797,9 @@ public async Task<int> BuildAsync(FileInfo projectFilePath, bool noRestore, Proc
string[] cliArgs = ["build", noRestoreSwitch, projectFilePath.FullName];
cliArgs = [.. cliArgs.Where(arg => !string.IsNullOrWhiteSpace(arg))];

// Always inject DOTNET_CLI_USE_MSBUILD_SERVER for apphost builds
var env = new Dictionary<string, string>
{
["DOTNET_CLI_USE_MSBUILD_SERVER"] = GetMsBuildServerValue()
};

return await ExecuteAsync(
args: cliArgs,
env: env,
env: null,
projectFile: projectFilePath,
workingDirectory: projectFilePath.Directory!,
backchannelCompletionSource: null,
Expand Down
28 changes: 10 additions & 18 deletions src/Aspire.Dashboard/Model/Interaction/InputViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,9 @@ public InputViewModel(InteractionInput input)

public void SetInput(InteractionInput input)
{
string value;
if (Input == null)
{
value = input.Value;
}
else
{
// Only overwrite the local value if the input was loading and is no longer loading (update could have come from server)
// This avoids changes in local values being overwritten by a dynamic server update.
if (Input.Loading && !input.Loading)
{
value = input.Value;
}
else
{
value = Input.Value;
}
}
var value = Input is null || ShouldUseIncomingValue(Input, input)
? input.Value
: Input.Value;
input.Value = value;

Input = input;
Expand Down Expand Up @@ -137,4 +122,11 @@ private static bool OptionsEqual(List<SelectViewModel<string>> existing, List<Se

return true;
}

private static bool ShouldUseIncomingValue(InteractionInput current, InteractionInput incoming)
{
// Preserve local edits during ordinary updates, but accept server-provided values when
// dynamic loading completes or when the input is disabled and therefore server-owned.
return (current.Loading && !incoming.Loading) || incoming.Disabled;
}
}
21 changes: 8 additions & 13 deletions tests/Aspire.Cli.Tests/DotNet/DotNetCliRunnerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public async Task DotNetCliCorrectlyAppliesNoLaunchProfileArgumentWhenSpecifiedI
}

[Fact]
public async Task BuildAsyncAlwaysInjectsDotnetCliUseMsBuildServerEnvironmentVariable()
public async Task BuildAsyncDoesNotInjectDotnetCliUseMsBuildServerEnvironmentVariable()
{
using var workspace = TemporaryWorkspace.Create(outputHelper);
var projectFile = new FileInfo(Path.Combine(workspace.WorkspaceRoot.FullName, "AppHost.csproj"));
Expand All @@ -84,8 +84,7 @@ public async Task BuildAsyncAlwaysInjectsDotnetCliUseMsBuildServerEnvironmentVar
(args, env, _, _) =>
{
Assert.NotNull(env);
Assert.True(env.ContainsKey("DOTNET_CLI_USE_MSBUILD_SERVER"));
Assert.Equal("true", env["DOTNET_CLI_USE_MSBUILD_SERVER"]);
Assert.False(env.ContainsKey("DOTNET_CLI_USE_MSBUILD_SERVER"));
},
0);

Expand Down Expand Up @@ -123,14 +122,13 @@ public async Task RestoreAsyncRunsDotnetRestoreCommand()
}

[Fact]
public async Task BuildAsyncUsesConfigurationValueForDotnetCliUseMsBuildServer()
public async Task BuildAsyncDoesNotInjectConfiguredDotnetCliUseMsBuildServer()
{
using var workspace = TemporaryWorkspace.Create(outputHelper);
var projectFile = new FileInfo(Path.Combine(workspace.WorkspaceRoot.FullName, "AppHost.csproj"));
await File.WriteAllTextAsync(projectFile.FullName, "Not a real project file.");

var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper);
// Add a configuration value that overrides the default
services.AddSingleton<IConfiguration>(sp =>
{
var configBuilder = new ConfigurationBuilder();
Expand All @@ -151,8 +149,7 @@ public async Task BuildAsyncUsesConfigurationValueForDotnetCliUseMsBuildServer()
(args, env, _, _) =>
{
Assert.NotNull(env);
Assert.True(env.ContainsKey("DOTNET_CLI_USE_MSBUILD_SERVER"));
Assert.Equal("false", env["DOTNET_CLI_USE_MSBUILD_SERVER"]);
Assert.False(env.ContainsKey("DOTNET_CLI_USE_MSBUILD_SERVER"));
},
0);

Expand Down Expand Up @@ -220,7 +217,7 @@ public async Task BuildAsyncDoesNotIncludeNoRestoreFlagWhenNoRestoreIsFalse()
}

[Fact]
public async Task RunAsyncInjectsDotnetCliUseMsBuildServerWhenNoBuildIsFalse()
public async Task RunAsyncDoesNotInjectDotnetCliUseMsBuildServerWhenNoBuildIsFalse()
{
using var workspace = TemporaryWorkspace.Create(outputHelper);
var projectFile = new FileInfo(Path.Combine(workspace.WorkspaceRoot.FullName, "AppHost.csproj"));
Expand All @@ -238,15 +235,14 @@ public async Task RunAsyncInjectsDotnetCliUseMsBuildServerWhenNoBuildIsFalse()
(args, env, _, _) =>
{
Assert.NotNull(env);
Assert.True(env.ContainsKey("DOTNET_CLI_USE_MSBUILD_SERVER"));
Assert.Equal("true", env["DOTNET_CLI_USE_MSBUILD_SERVER"]);
Assert.False(env.ContainsKey("DOTNET_CLI_USE_MSBUILD_SERVER"));
},
0);

var exitCode = await runner.RunAsync(
projectFile: projectFile,
watch: false,
noBuild: false, // This should inject the environment variable
noBuild: false,
noRestore: false,
args: ["--operation", "inspect"],
env: new Dictionary<string, string>(),
Expand Down Expand Up @@ -317,8 +313,7 @@ public async Task RunAsyncPreservesExistingEnvironmentVariables()
(args, env, _, _) =>
{
Assert.NotNull(env);
Assert.True(env.ContainsKey("DOTNET_CLI_USE_MSBUILD_SERVER"));
Assert.Equal("true", env["DOTNET_CLI_USE_MSBUILD_SERVER"]);
Assert.False(env.ContainsKey("DOTNET_CLI_USE_MSBUILD_SERVER"));
// Verify existing environment variable is preserved
Assert.True(env.ContainsKey("EXISTING_VAR"));
Assert.Equal("existing_value", env["EXISTING_VAR"]);
Expand Down
50 changes: 50 additions & 0 deletions tests/Aspire.Dashboard.Tests/Model/InputViewModelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,4 +259,54 @@ public void ChoiceVersion_NotIncrementedWhenOptionsUnchanged()

Assert.Equal(initialVersion, viewModel.ChoiceVersion);
}

[Fact]
public void SetInput_DisabledInputUsesIncomingValue()
{
var input = new InteractionInput
{
Label = "Location",
InputType = InputType.Choice,
Placeholder = "Select a location",
Disabled = true
};
var viewModel = new InputViewModel(input);

var updatedInput = new InteractionInput
{
Label = "Location",
InputType = InputType.Choice,
Placeholder = "Select a location",
Disabled = true,
Value = "westus"
};
updatedInput.Options.Add("westus", "West US");

viewModel.SetInput(updatedInput);

Assert.Equal("westus", viewModel.Value);
}

[Fact]
public void SetInput_EnabledInputPreservesLocalValue()
{
var input = new InteractionInput
{
Label = "Name",
InputType = InputType.Text,
Value = "local"
};
var viewModel = new InputViewModel(input);

var updatedInput = new InteractionInput
{
Label = "Name",
InputType = InputType.Text,
Value = "server"
};

viewModel.SetInput(updatedInput);

Assert.Equal("local", viewModel.Value);
}
}
4 changes: 2 additions & 2 deletions tests/Shared/RepoTesting/Aspire.RepoTesting.targets
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
`AspireProjectOrPackageReference` - maps to projects in `src/` or `src/Components/`
-->

<Import Project="Sdk.props" Sdk="Aspire.AppHost.Sdk" Version="13.3.4" Condition="'$(IsAspireHost)' == 'true' and '$(RepoRoot)' == '' and '$(TestsRunningOutsideOfRepo)' == 'true'" />
<Import Project="Sdk.props" Sdk="Aspire.AppHost.Sdk" Version="13.3.5" Condition="'$(IsAspireHost)' == 'true' and '$(RepoRoot)' == '' and '$(TestsRunningOutsideOfRepo)' == 'true'" />

<PropertyGroup>
<!-- copy by default only when archiving tests, and for test projects that support running out of repo -->
Expand Down Expand Up @@ -165,6 +165,6 @@
<AspireHostingSDKVersion>$(MajorVersion).$(MinorVersion).$(PatchVersion)</AspireHostingSDKVersion>
</PropertyGroup>

<Import Project="Sdk.targets" Sdk="Aspire.AppHost.Sdk" Version="13.3.4" Condition="'$(IsAspireHost)' == 'true' and '$(RepoRoot)' == '' and '$(TestsRunningOutsideOfRepo)' == 'true'" />
<Import Project="Sdk.targets" Sdk="Aspire.AppHost.Sdk" Version="13.3.5" Condition="'$(IsAspireHost)' == 'true' and '$(RepoRoot)' == '' and '$(TestsRunningOutsideOfRepo)' == 'true'" />

</Project>
Loading
Loading