File: Utils\AppHostHelper.cs
Web Access
Project: src\src\Aspire.Cli\Aspire.Cli.csproj (aspire)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Aspire.Cli.Interaction;
using Semver;
using System.Diagnostics;
 
namespace Aspire.Cli.Utils;
 
internal static class AppHostHelper
{
    private static readonly ActivitySource s_activitySource = new ActivitySource(nameof(AppHostHelper));
 
    internal static async Task<(bool IsCompatibleAppHost, bool SupportsBackchannel, string? AspireHostingSdkVersion)> CheckAppHostCompatibilityAsync(IDotNetCliRunner runner, IInteractionService interactionService, FileInfo projectFile, CancellationToken cancellationToken)
    {
            var appHostInformation = await GetAppHostInformationAsync(runner, interactionService, projectFile, cancellationToken);
 
            if (appHostInformation.ExitCode != 0)
            {
                interactionService.DisplayError("The project could not be analyzed due to a build error. For more information run with --debug switch.");
                return (false, false, null);
            }
 
            if (!appHostInformation.IsAspireHost)
            {
                interactionService.DisplayError($"The project is not an Aspire app host project.");
                return (false, false, null);
            }
 
            if (!SemVersion.TryParse(appHostInformation.AspireHostingSdkVersion, out var aspireSdkVersion))
            {
                interactionService.DisplayError($"Could not parse Aspire SDK version.");
                return (false, false, null);
            }
 
            var compatibleRanges = SemVersionRange.Parse("^9.2.0-dev", SemVersionRangeOptions.IncludeAllPrerelease);
            if (!aspireSdkVersion.Satisfies(compatibleRanges))
            {
                interactionService.DisplayError($"The Aspire SDK version '{appHostInformation.AspireHostingSdkVersion}' is not supported. Please update to the latest version.");
                return (false, false, appHostInformation.AspireHostingSdkVersion);
            }
            else
            {
                // NOTE: When we go to support < 9.2.0 app hosts this is where we'll make
                //       a determination as to whether the apphsot supports backchannel or not.
                return (true, true, appHostInformation.AspireHostingSdkVersion);
            }
    }
 
    internal static async Task<(int ExitCode, bool IsAspireHost, string? AspireHostingSdkVersion)> GetAppHostInformationAsync(IDotNetCliRunner runner, IInteractionService interactionService, FileInfo projectFile, CancellationToken cancellationToken)
    {
        using var activity = s_activitySource.StartActivity(nameof(GetAppHostInformationAsync), ActivityKind.Client);
 
        var appHostInformationResult = await interactionService.ShowStatusAsync(
            ":microscope: Checking project type...",
            () => runner.GetAppHostInformationAsync(projectFile, cancellationToken)
        );
 
        return appHostInformationResult;
    }
    
    internal static async Task<int> BuildAppHostAsync(IDotNetCliRunner runner, IInteractionService interactionService, FileInfo projectFile, CancellationToken cancellationToken)
    {
        return await interactionService.ShowStatusAsync(
            ":hammer_and_wrench:  Building app host...",
            () => runner.BuildAsync(projectFile, cancellationToken));
    }
}