Skip to content

Commit 3983f38

Browse files
Copilotmitchdenny
andcommitted
Add feature flag for SDK installation (dotnetSdkInstallationEnabled)
- Add KnownFeatures.DotNetSdkInstallationEnabled constant - Update SdkInstallHelper to check feature flag before offering installation - Default feature flag to true (enabled by default) - Add IFeatures parameter to EnsureSdkInstalledAsync method - Store _features field in AddCommand and ExecCommand - Update all command calls to pass _features parameter Addresses feedback from @mitchdenny to add feature flag control. Co-authored-by: mitchdenny <[email protected]>
1 parent b3ea029 commit 3983f38

File tree

8 files changed

+23
-9
lines changed

8 files changed

+23
-9
lines changed

src/Aspire.Cli/Commands/AddCommand.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ internal sealed class AddCommand : BaseCommand
2525
private readonly AspireCliTelemetry _telemetry;
2626
private readonly IDotNetSdkInstaller _sdkInstaller;
2727
private readonly ICliHostEnvironment _hostEnvironment;
28+
private readonly IFeatures _features;
2829

2930
public AddCommand(IDotNetCliRunner runner, IPackagingService packagingService, IInteractionService interactionService, IProjectLocator projectLocator, IAddCommandPrompter prompter, AspireCliTelemetry telemetry, IDotNetSdkInstaller sdkInstaller, IFeatures features, ICliUpdateNotifier updateNotifier, CliExecutionContext executionContext, ICliHostEnvironment hostEnvironment)
3031
: base("add", AddCommandStrings.Description, features, updateNotifier, executionContext, interactionService)
@@ -37,6 +38,7 @@ public AddCommand(IDotNetCliRunner runner, IPackagingService packagingService, I
3738
ArgumentNullException.ThrowIfNull(telemetry);
3839
ArgumentNullException.ThrowIfNull(sdkInstaller);
3940
ArgumentNullException.ThrowIfNull(hostEnvironment);
41+
ArgumentNullException.ThrowIfNull(features);
4042

4143
_runner = runner;
4244
_packagingService = packagingService;
@@ -45,6 +47,7 @@ public AddCommand(IDotNetCliRunner runner, IPackagingService packagingService, I
4547
_telemetry = telemetry;
4648
_sdkInstaller = sdkInstaller;
4749
_hostEnvironment = hostEnvironment;
50+
_features = features;
4851

4952
var integrationArgument = new Argument<string>("integration");
5053
integrationArgument.Description = AddCommandStrings.IntegrationArgumentDescription;
@@ -67,7 +70,7 @@ public AddCommand(IDotNetCliRunner runner, IPackagingService packagingService, I
6770
protected override async Task<int> ExecuteAsync(ParseResult parseResult, CancellationToken cancellationToken)
6871
{
6972
// Check if the .NET SDK is available
70-
if (!await SdkInstallHelper.EnsureSdkInstalledAsync(_sdkInstaller, InteractionService, _hostEnvironment, cancellationToken))
73+
if (!await SdkInstallHelper.EnsureSdkInstalledAsync(_sdkInstaller, InteractionService, _features, _hostEnvironment, cancellationToken))
7174
{
7275
return ExitCodeConstants.SdkNotInstalled;
7376
}

src/Aspire.Cli/Commands/ExecCommand.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ internal class ExecCommand : BaseCommand
2626
private readonly AspireCliTelemetry _telemetry;
2727
private readonly IDotNetSdkInstaller _sdkInstaller;
2828
private readonly ICliHostEnvironment _hostEnvironment;
29+
private readonly IFeatures _features;
2930

3031
public ExecCommand(
3132
IDotNetCliRunner runner,
@@ -48,6 +49,7 @@ public ExecCommand(
4849
ArgumentNullException.ThrowIfNull(telemetry);
4950
ArgumentNullException.ThrowIfNull(sdkInstaller);
5051
ArgumentNullException.ThrowIfNull(hostEnvironment);
52+
ArgumentNullException.ThrowIfNull(features);
5153

5254
_runner = runner;
5355
_certificateService = certificateService;
@@ -56,6 +58,7 @@ public ExecCommand(
5658
_telemetry = telemetry;
5759
_sdkInstaller = sdkInstaller;
5860
_hostEnvironment = hostEnvironment;
61+
_features = features;
5962

6063
var projectOption = new Option<FileInfo?>("--project");
6164
projectOption.Description = ExecCommandStrings.ProjectArgumentDescription;
@@ -84,7 +87,7 @@ public ExecCommand(
8487
protected override async Task<int> ExecuteAsync(ParseResult parseResult, CancellationToken cancellationToken)
8588
{
8689
// Check if the .NET SDK is available
87-
if (!await SdkInstallHelper.EnsureSdkInstalledAsync(_sdkInstaller, InteractionService, _hostEnvironment, cancellationToken))
90+
if (!await SdkInstallHelper.EnsureSdkInstalledAsync(_sdkInstaller, InteractionService, _features, _hostEnvironment, cancellationToken))
8891
{
8992
return ExitCodeConstants.SdkNotInstalled;
9093
}

src/Aspire.Cli/Commands/InitCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public InitCommand(
9797
protected override async Task<int> ExecuteAsync(ParseResult parseResult, CancellationToken cancellationToken)
9898
{
9999
// Check if the .NET SDK is available
100-
if (!await SdkInstallHelper.EnsureSdkInstalledAsync(_sdkInstaller, InteractionService, _hostEnvironment, cancellationToken))
100+
if (!await SdkInstallHelper.EnsureSdkInstalledAsync(_sdkInstaller, InteractionService, _features, _hostEnvironment, cancellationToken))
101101
{
102102
return ExitCodeConstants.SdkNotInstalled;
103103
}

src/Aspire.Cli/Commands/NewCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ private async Task<ITemplate> GetProjectTemplateAsync(ParseResult parseResult, C
124124
protected override async Task<int> ExecuteAsync(ParseResult parseResult, CancellationToken cancellationToken)
125125
{
126126
// Check if the .NET SDK is available
127-
if (!await SdkInstallHelper.EnsureSdkInstalledAsync(_sdkInstaller, InteractionService, _hostEnvironment, cancellationToken))
127+
if (!await SdkInstallHelper.EnsureSdkInstalledAsync(_sdkInstaller, InteractionService, _features, _hostEnvironment, cancellationToken))
128128
{
129129
return ExitCodeConstants.SdkNotInstalled;
130130
}

src/Aspire.Cli/Commands/PublishCommandBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ protected override async Task<int> ExecuteAsync(ParseResult parseResult, Cancell
8888
StartTerminalProgressBar();
8989

9090
// Check if the .NET SDK is available
91-
if (!await SdkInstallHelper.EnsureSdkInstalledAsync(_sdkInstaller, InteractionService, _hostEnvironment, cancellationToken))
91+
if (!await SdkInstallHelper.EnsureSdkInstalledAsync(_sdkInstaller, InteractionService, _features, _hostEnvironment, cancellationToken))
9292
{
9393
// Send terminal progress bar stop sequence
9494
StopTerminalProgressBar();

src/Aspire.Cli/Commands/RunCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ protected override async Task<int> ExecuteAsync(ParseResult parseResult, Cancell
103103
}
104104

105105
// Check if the .NET SDK is available
106-
if (!await SdkInstallHelper.EnsureSdkInstalledAsync(_sdkInstaller, InteractionService, _hostEnvironment, cancellationToken))
106+
if (!await SdkInstallHelper.EnsureSdkInstalledAsync(_sdkInstaller, InteractionService, _features, _hostEnvironment, cancellationToken))
107107
{
108108
return ExitCodeConstants.SdkNotInstalled;
109109
}

src/Aspire.Cli/KnownFeatures.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ internal static class KnownFeatures
1717
public static string StagingChannelEnabled => "stagingChannelEnabled";
1818
public static string DefaultWatchEnabled => "defaultWatchEnabled";
1919
public static string ShowAllTemplates => "showAllTemplates";
20+
public static string DotNetSdkInstallationEnabled => "dotnetSdkInstallationEnabled";
2021
}

src/Aspire.Cli/Utils/SdkInstallHelper.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Globalization;
5+
using Aspire.Cli.Configuration;
56
using Aspire.Cli.DotNet;
67
using Aspire.Cli.Interaction;
78
using Aspire.Cli.Resources;
@@ -15,21 +16,24 @@ internal static class SdkInstallHelper
1516
{
1617
/// <summary>
1718
/// Ensures that the .NET SDK is installed and available, displaying an error message if it's not.
18-
/// If the SDK is missing, prompts the user to install it automatically (if in interactive mode).
19+
/// If the SDK is missing, prompts the user to install it automatically (if in interactive mode and feature is enabled).
1920
/// </summary>
2021
/// <param name="sdkInstaller">The SDK installer service.</param>
2122
/// <param name="interactionService">The interaction service for user communication.</param>
23+
/// <param name="features">The features service for checking if SDK installation is enabled.</param>
2224
/// <param name="hostEnvironment">The CLI host environment for detecting interactive capabilities.</param>
2325
/// <param name="cancellationToken">Cancellation token.</param>
2426
/// <returns>True if the SDK is available, false if it's missing.</returns>
2527
public static async Task<bool> EnsureSdkInstalledAsync(
2628
IDotNetSdkInstaller sdkInstaller,
2729
IInteractionService interactionService,
30+
IFeatures features,
2831
ICliHostEnvironment? hostEnvironment = null,
2932
CancellationToken cancellationToken = default)
3033
{
3134
ArgumentNullException.ThrowIfNull(sdkInstaller);
3235
ArgumentNullException.ThrowIfNull(interactionService);
36+
ArgumentNullException.ThrowIfNull(features);
3337

3438
var (success, highestVersion, minimumRequiredVersion) = await sdkInstaller.CheckAsync(cancellationToken);
3539

@@ -43,8 +47,11 @@ public static async Task<bool> EnsureSdkInstalledAsync(
4347
detectedVersion);
4448
interactionService.DisplayError(sdkErrorMessage);
4549

46-
// Only offer to install if we support interactive input
47-
if (hostEnvironment?.SupportsInteractiveInput == true)
50+
// Only offer to install if:
51+
// 1. The feature is enabled (default: true)
52+
// 2. We support interactive input
53+
if (features.IsFeatureEnabled(KnownFeatures.DotNetSdkInstallationEnabled, defaultValue: true) &&
54+
hostEnvironment?.SupportsInteractiveInput == true)
4855
{
4956
// Offer to install the SDK automatically
5057
var shouldInstall = await interactionService.ConfirmAsync(

0 commit comments

Comments
 (0)