Skip to content
Closed
40 changes: 38 additions & 2 deletions src/Aspire.Cli/Commands/UpdateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ internal sealed class UpdateCommand : BaseCommand
private readonly IProjectUpdater _projectUpdater;
private readonly ILogger<UpdateCommand> _logger;
private readonly ICliDownloader? _cliDownloader;
private readonly ICliUpdateNotifier _updateNotifier;

public UpdateCommand(
IProjectLocator projectLocator,
Expand All @@ -41,12 +42,14 @@ public UpdateCommand(
ArgumentNullException.ThrowIfNull(packagingService);
ArgumentNullException.ThrowIfNull(projectUpdater);
ArgumentNullException.ThrowIfNull(logger);
ArgumentNullException.ThrowIfNull(updateNotifier);

_projectLocator = projectLocator;
_packagingService = packagingService;
_projectUpdater = projectUpdater;
_logger = logger;
_cliDownloader = cliDownloader;
_updateNotifier = updateNotifier;

var projectOption = new Option<FileInfo?>("--project");
projectOption.Description = UpdateCommandStrings.ProjectArgumentDescription;
Expand Down Expand Up @@ -116,6 +119,21 @@ protected override async Task<int> ExecuteAsync(ParseResult parseResult, Cancell
cancellationToken);

await _projectUpdater.UpdateProjectAsync(projectFile!, channel, cancellationToken);

// After successful project update, check if CLI update is available and prompt
if (_cliDownloader is not null && _updateNotifier.IsUpdateAvailable())
{
var shouldUpdateCli = await InteractionService.ConfirmAsync(
UpdateCommandStrings.UpdateCliAfterProjectUpdatePrompt,
defaultValue: true,
cancellationToken);

if (shouldUpdateCli)
{
// Use the same channel that was selected for the project update
return await ExecuteSelfUpdateAsync(parseResult, cancellationToken, channel.Name);
}
}
}
catch (ProjectUpdaterException ex)
{
Expand All @@ -125,15 +143,33 @@ protected override async Task<int> ExecuteAsync(ParseResult parseResult, Cancell
}
catch (ProjectLocatorException ex)
{
// Check if this is a "no project found" error and prompt for self-update
if (string.Equals(ex.Message, ErrorStrings.NoProjectFileFound, StringComparisons.CliInputOrOutput))
{
// Only prompt for self-update if not running as dotnet tool and downloader is available
if (_cliDownloader is not null)
{
var shouldUpdateCli = await InteractionService.ConfirmAsync(
UpdateCommandStrings.NoAppHostFoundUpdateCliPrompt,
defaultValue: true,
cancellationToken);

if (shouldUpdateCli)
{
return await ExecuteSelfUpdateAsync(parseResult, cancellationToken);
}
}
}

return HandleProjectLocatorException(ex, InteractionService);
}

return 0;
}

private async Task<int> ExecuteSelfUpdateAsync(ParseResult parseResult, CancellationToken cancellationToken)
private async Task<int> ExecuteSelfUpdateAsync(ParseResult parseResult, CancellationToken cancellationToken, string? selectedQuality = null)
{
var quality = parseResult.GetValue<string?>("--quality");
var quality = selectedQuality ?? parseResult.GetValue<string?>("--quality");

// If quality is not specified, prompt the user
if (string.IsNullOrEmpty(quality))
Expand Down
8 changes: 7 additions & 1 deletion src/Aspire.Cli/Interaction/ConsoleInteractionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,16 @@ public void DisplayEmptyLine()

private const string UpdateUrl = "https://aka.ms/aspire/update";

public void DisplayVersionUpdateNotification(string newerVersion)
public void DisplayVersionUpdateNotification(string newerVersion, string? updateCommand = null)
{
_ansiConsole.WriteLine();
_ansiConsole.MarkupLine(string.Format(CultureInfo.CurrentCulture, InteractionServiceStrings.NewCliVersionAvailable, newerVersion));

if (!string.IsNullOrEmpty(updateCommand))
{
_ansiConsole.MarkupLine(string.Format(CultureInfo.CurrentCulture, InteractionServiceStrings.ToUpdateRunCommand, updateCommand));
}

_ansiConsole.MarkupLine(string.Format(CultureInfo.CurrentCulture, InteractionServiceStrings.MoreInfoNewCliVersion, UpdateUrl));
}
}
4 changes: 2 additions & 2 deletions src/Aspire.Cli/Interaction/ExtensionInteractionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,9 @@ public void DisplayMarkdown(string markdown)
_consoleInteractionService.DisplayMarkdown(markdown);
}

public void DisplayVersionUpdateNotification(string newerVersion)
public void DisplayVersionUpdateNotification(string newerVersion, string? updateCommand = null)
{
_consoleInteractionService.DisplayVersionUpdateNotification(newerVersion);
_consoleInteractionService.DisplayVersionUpdateNotification(newerVersion, updateCommand);
}

public void LogMessage(LogLevel logLevel, string message)
Expand Down
2 changes: 1 addition & 1 deletion src/Aspire.Cli/Interaction/IInteractionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ internal interface IInteractionService
void DisplayCancellationMessage();
void DisplayEmptyLine();

void DisplayVersionUpdateNotification(string newerVersion);
void DisplayVersionUpdateNotification(string newerVersion, string? updateCommand = null);
void WriteConsoleLog(string message, int? lineNumber = null, string? type = null, bool isErrorMessage = false);
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions src/Aspire.Cli/Resources/InteractionServiceStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@
<value>[dim]For more information, see: [link]{0}[/][/]</value>
<comment>Do not translate [dim] and [link]. Also leave [/] as-is. {0} is a URL</comment>
</data>
<data name="ToUpdateRunCommand" xml:space="preserve">
<value>[dim]To update, run: {0}[/]</value>
<comment>Do not translate [dim]. Also leave [/] as-is. {0} is the command to run</comment>
</data>
<data name="UnbuildableAppHostsDetected" xml:space="preserve">
<value>No app hosts were found (there may be app hosts project files with syntax errors/invalid SDK versions).</value>
</data>
Expand Down
2 changes: 2 additions & 0 deletions src/Aspire.Cli/Resources/UpdateCommandStrings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src/Aspire.Cli/Resources/UpdateCommandStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,10 @@
<data name="FallbackParsingWarning" xml:space="preserve">
<value>Note: Update plan generated using fallback parsing due to unresolvable AppHost SDK. Dependency analysis may have reduced accuracy.</value>
</data>
<data name="NoAppHostFoundUpdateCliPrompt" xml:space="preserve">
<value>No Aspire AppHost project found. Would you like to update the Aspire CLI instead?</value>
</data>
<data name="UpdateCliAfterProjectUpdatePrompt" xml:space="preserve">
<value>An update is available for the Aspire CLI. Would you like to update it now?</value>
</data>
</root>
5 changes: 5 additions & 0 deletions src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.ru.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.tr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Aspire.Cli/Resources/xlf/UpdateCommandStrings.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading