diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs index bf2bd71fc0..53d23cb508 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs @@ -29,6 +29,11 @@ public class AbpCliCoreModule : AbpModule context.Services.AddHttpClient(CliConsts.HttpClientName) .ConfigurePrimaryHttpMessageHandler(() => new CliHttpClientHandler()); + context.Services.AddHttpClient(CliConsts.GithubHttpClientName, client => + { + client.DefaultRequestHeaders.UserAgent.ParseAdd("MyAgent/1.0"); + }); + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); Configure(options => diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs index 1c0cd3ace4..93cd5f3f98 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs @@ -10,6 +10,8 @@ public static class CliConsts public const string HttpClientName = "AbpHttpClient"; + public const string GithubHttpClientName = "GithubHttpClient"; + public const string LogoutUrl = CliUrls.WwwAbpIo + "api/license/logout"; public const string LicenseCodePlaceHolder = @""; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs index 0b302520aa..3ab75da1c0 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs @@ -13,7 +13,7 @@ using System.Threading.Tasks; using Volo.Abp.Cli.Args; using Volo.Abp.Cli.Commands; using Volo.Abp.Cli.Memory; -using Volo.Abp.Cli.NuGet; +using Volo.Abp.Cli.Version; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; using Volo.Abp.IO; @@ -27,14 +27,14 @@ public class CliService : ITransientDependency protected ICommandLineArgumentParser CommandLineArgumentParser { get; } protected ICommandSelector CommandSelector { get; } protected IServiceScopeFactory ServiceScopeFactory { get; } - protected NuGetService NuGetService { get; } + protected PackageVersionCheckerService PackageVersionCheckerService { get; } public ICmdHelper CmdHelper { get; } public CliService( ICommandLineArgumentParser commandLineArgumentParser, ICommandSelector commandSelector, IServiceScopeFactory serviceScopeFactory, - NuGetService nugetService, + PackageVersionCheckerService nugetService, ICmdHelper cmdHelper, MemoryService memoryService) { @@ -42,7 +42,7 @@ public class CliService : ITransientDependency CommandLineArgumentParser = commandLineArgumentParser; CommandSelector = commandSelector; ServiceScopeFactory = serviceScopeFactory; - NuGetService = nugetService; + PackageVersionCheckerService = nugetService; CmdHelper = cmdHelper; Logger = NullLogger.Instance; @@ -61,6 +61,7 @@ public class CliService : ITransientDependency await CheckCliVersionAsync(currentCliVersion); } #endif + try { if (commandLineArgs.IsCommand("prompt")) @@ -175,24 +176,22 @@ public class CliService : ITransientDependency { return; } - - var assembly = typeof(CliService).Assembly; - var toolPath = GetToolPath(assembly); - var updateChannel = GetUpdateChannel(currentCliVersion); try { - var latestVersion = await GetLatestVersion(updateChannel); + var assembly = typeof(CliService).Assembly; + var toolPath = GetToolPath(assembly); + var updateChannel = GetUpdateChannel(currentCliVersion); - if (latestVersion != null && latestVersion > currentCliVersion) + var latestVersionInfo = await GetLatestVersion(updateChannel); + if (latestVersionInfo != null && latestVersionInfo.Version > currentCliVersion) { - LogNewVersionInfo(updateChannel, latestVersion, toolPath); + LogNewVersionInfo(updateChannel, latestVersionInfo.Version, toolPath, latestVersionInfo.Message); } } catch (Exception e) { - Logger.LogWarning("Unable to retrieve the latest version"); - Logger.LogWarning(e.Message); + Logger.LogWarning("Unable to retrieve the latest version: " + e.Message); } } @@ -200,13 +199,17 @@ public class CliService : ITransientDependency { try { - var latestTime = await _memoryService.GetAsync(CliConsts.MemoryKeys.LatestCliVersionCheckDate); - - if (latestTime != null && DateTime.Now - DateTime.Parse(latestTime, CultureInfo.InvariantCulture) < TimeSpan.FromDays(1)) + var latestTimeAsString = await _memoryService.GetAsync(CliConsts.MemoryKeys.LatestCliVersionCheckDate); + if (DateTime.TryParse(latestTimeAsString, + System.Globalization.CultureInfo.InvariantCulture, + System.Globalization.DateTimeStyles.None, out var latestTimeParsed)) { - return false; + if (DateTime.Now.Subtract(latestTimeParsed).TotalDays < 1) + { + return false; + } } - + await _memoryService.SetAsync(CliConsts.MemoryKeys.LatestCliVersionCheckDate, DateTime.Now.ToString(CultureInfo.InvariantCulture)); return true; @@ -282,18 +285,18 @@ public class CliService : ITransientDependency return UpdateChannel.Prerelease; } - private async Task GetLatestVersion(UpdateChannel updateChannel) + private async Task GetLatestVersion(UpdateChannel updateChannel) { switch (updateChannel) { case UpdateChannel.Stable: - return await NuGetService.GetLatestVersionOrNullAsync("Volo.Abp.Cli"); + return await PackageVersionCheckerService.GetLatestVersionOrNullAsync("Volo.Abp.Cli"); case UpdateChannel.Prerelease: - return await NuGetService.GetLatestVersionOrNullAsync("Volo.Abp.Cli", includeReleaseCandidates: true); + return await PackageVersionCheckerService.GetLatestVersionOrNullAsync("Volo.Abp.Cli", includeReleaseCandidates: true); case UpdateChannel.Nightly: - return await NuGetService.GetLatestVersionOrNullAsync("Volo.Abp.Cli", includeNightly: true); + return await PackageVersionCheckerService.GetLatestVersionOrNullAsync("Volo.Abp.Cli", includeNightly: true); default: return default; @@ -306,11 +309,17 @@ public class CliService : ITransientDependency return globalPaths.Select(Environment.ExpandEnvironmentVariables).Contains(toolPath); } - private void LogNewVersionInfo(UpdateChannel updateChannel, SemanticVersion latestVersion, string toolPath) + private void LogNewVersionInfo(UpdateChannel updateChannel, SemanticVersion latestVersion, string toolPath, string message = null) { var toolPathArg = IsGlobalTool(toolPath) ? "-g" : $"--tool-path {toolPath}"; Logger.LogWarning($"ABP CLI has a newer {updateChannel.ToString().ToLowerInvariant()} version {latestVersion}, please update to get the latest features and fixes."); + + if (!string.IsNullOrWhiteSpace(message)) + { + Logger.LogWarning(message); + } + Logger.LogWarning(string.Empty); Logger.LogWarning("Update Command: "); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs index 4c1351ffba..83ae5a9f73 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs @@ -8,6 +8,8 @@ public static class CliUrls public const string WwwAbpIo = WwwAbpIoProduction; public const string AccountAbpIo = AccountAbpIoProduction; public const string NuGetRootPath = NuGetRootPathProduction; + public const string LatestVersionCheckFullPath = + "https://raw.githubusercontent.com/abpframework/abp/dev/latest-versions.json"; public const string WwwAbpIoProduction = "https://abp.io/"; public const string AccountAbpIoProduction = "https://account.abp.io/"; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CliCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CliCommand.cs index 7a6926ecdd..108d664f3a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CliCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CliCommand.cs @@ -5,7 +5,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Cli.Args; using Volo.Abp.Cli.Commands.Services; -using Volo.Abp.Cli.NuGet; +using Volo.Abp.Cli.Version; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; @@ -18,14 +18,14 @@ public class CliCommand : IConsoleCommand, ITransientDependency private const string CliPackageName = "Volo.Abp.Cli"; private readonly ICmdHelper _cmdHelper; - private readonly NuGetService _nuGetService; + private readonly PackageVersionCheckerService _packageVersionCheckerService; private readonly AbpNuGetIndexUrlService _nuGetIndexUrlService; public ILogger Logger { get; set; } - public CliCommand(ICmdHelper cmdHelper, NuGetService nuGetService, AbpNuGetIndexUrlService nuGetIndexUrlService) + public CliCommand(ICmdHelper cmdHelper, PackageVersionCheckerService packageVersionCheckerService, AbpNuGetIndexUrlService nuGetIndexUrlService) { _cmdHelper = cmdHelper; - _nuGetService = nuGetService; + _packageVersionCheckerService = packageVersionCheckerService; _nuGetIndexUrlService = nuGetIndexUrlService; Logger = NullLogger.Instance; @@ -104,13 +104,13 @@ public class CliCommand : IConsoleCommand, ITransientDependency private async Task GetLatestPreviewVersion() { - var latestPreviewVersion = await _nuGetService + var latestPreviewVersionInfo = await _packageVersionCheckerService .GetLatestVersionOrNullAsync( packageId: CliPackageName, includeReleaseCandidates: true ); - return latestPreviewVersion.IsPrerelease ? latestPreviewVersion.ToString() : null; + return latestPreviewVersionInfo.Version.IsPrerelease ? latestPreviewVersionInfo.Version.ToString() : null; } private void ShowCliManualUpdateCommand() diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs index 73198c93bc..83c21d4773 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs @@ -17,7 +17,7 @@ using Volo.Abp.Cli.Args; using Volo.Abp.Cli.Auth; using Volo.Abp.Cli.Commands.Services; using Volo.Abp.Cli.Http; -using Volo.Abp.Cli.NuGet; +using Volo.Abp.Cli.Version; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; using Volo.Abp.Http; @@ -32,7 +32,7 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency public ICmdHelper CmdHelper { get; } private readonly AbpNuGetIndexUrlService _nuGetIndexUrlService; - private readonly NuGetService _nuGetService; + private readonly PackageVersionCheckerService _packageVersionCheckerService; private readonly AuthService _authService; private readonly CliHttpClientFactory _cliHttpClientFactory; private const string SuitePackageName = "Volo.Abp.Suite"; @@ -42,14 +42,14 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency public SuiteCommand( AbpNuGetIndexUrlService nuGetIndexUrlService, - NuGetService nuGetService, + PackageVersionCheckerService packageVersionCheckerService, ICmdHelper cmdHelper, AuthService authService, CliHttpClientFactory cliHttpClientFactory) { CmdHelper = cmdHelper; _nuGetIndexUrlService = nuGetIndexUrlService; - _nuGetService = nuGetService; + _packageVersionCheckerService = packageVersionCheckerService; _authService = authService; _cliHttpClientFactory = cliHttpClientFactory; Logger = NullLogger.Instance; @@ -393,13 +393,13 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency private async Task GetLatestPreviewVersion() { - var latestPreviewVersion = await _nuGetService + var latestPreviewVersionInfo = await _packageVersionCheckerService .GetLatestVersionOrNullAsync( packageId: SuitePackageName, includeReleaseCandidates: true ); - return latestPreviewVersion.IsPrerelease ? latestPreviewVersion.ToString() : null; + return latestPreviewVersionInfo.Version.IsPrerelease ? latestPreviewVersionInfo.Version.ToString() : null; } private void ShowSuiteManualUpdateCommand() diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClientFactory.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClientFactory.cs index 1d21dd7be5..546a2f020c 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClientFactory.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClientFactory.cs @@ -20,9 +20,9 @@ public class CliHttpClientFactory : ISingletonDependency _cancellationTokenProvider = cancellationTokenProvider; } - public HttpClient CreateClient(bool needsAuthentication = true, TimeSpan? timeout = null) + public HttpClient CreateClient(bool needsAuthentication = true, TimeSpan? timeout = null, string clientName = null) { - var httpClient = _clientFactory.CreateClient(CliConsts.HttpClientName); + var httpClient = _clientFactory.CreateClient(clientName ?? CliConsts.HttpClientName); httpClient.Timeout = timeout ?? DefaultTimeout; if (needsAuthentication) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs index 336594b130..5818959ec7 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs @@ -5,7 +5,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using System.Xml; -using Volo.Abp.Cli.NuGet; +using Volo.Abp.Cli.Version; using Volo.Abp.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -15,14 +15,14 @@ namespace Volo.Abp.Cli.ProjectModification; public class VoloNugetPackagesVersionUpdater : ITransientDependency { - private readonly NuGetService _nuGetService; + private readonly PackageVersionCheckerService _packageVersionCheckerService; private readonly MyGetPackageListFinder _myGetPackageListFinder; public ILogger Logger { get; set; } public static Encoding DefaultEncoding = Encoding.UTF8; - public VoloNugetPackagesVersionUpdater(NuGetService nuGetService, MyGetPackageListFinder myGetPackageListFinder) + public VoloNugetPackagesVersionUpdater(PackageVersionCheckerService packageVersionCheckerService, MyGetPackageListFinder myGetPackageListFinder) { - _nuGetService = nuGetService; + _packageVersionCheckerService = packageVersionCheckerService; _myGetPackageListFinder = myGetPackageListFinder; Logger = NullLogger.Instance; } @@ -37,8 +37,8 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency } else { - var latestVersionFromNuget = await _nuGetService.GetLatestVersionOrNullAsync("Volo.Abp.Core", includeReleaseCandidates: includeReleaseCandidates); - var latestReleaseCandidateVersionFromNuget = await _nuGetService.GetLatestVersionOrNullAsync("Volo.Abp.Core", includeReleaseCandidates: true); + var latestVersionInfo = await _packageVersionCheckerService.GetLatestVersionOrNullAsync("Volo.Abp.Core", includeReleaseCandidates: includeReleaseCandidates); + var latestReleaseCandidateVersionInfo = await _packageVersionCheckerService.GetLatestVersionOrNullAsync("Volo.Abp.Core", includeReleaseCandidates: true); var latestVersionFromMyGet = await GetLatestVersionFromMyGet("Volo.Abp.Core"); async Task UpdateAsync(string filePath) @@ -53,8 +53,8 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency includePreviews, includeReleaseCandidates, switchToStable, - latestVersionFromNuget, - latestReleaseCandidateVersionFromNuget, + latestVersionInfo.Version, + latestReleaseCandidateVersionInfo.Version, latestVersionFromMyGet, version); @@ -81,8 +81,8 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency } else { - var latestVersionFromNuget = await _nuGetService.GetLatestVersionOrNullAsync("Volo.Abp.Core"); - var latestReleaseCandidateVersionFromNuget = await _nuGetService.GetLatestVersionOrNullAsync("Volo.Abp.Core", includeReleaseCandidates: true); + var latestVersionInfo = await _packageVersionCheckerService.GetLatestVersionOrNullAsync("Volo.Abp.Core"); + var latestReleaseCandidateVersionInfo = await _packageVersionCheckerService.GetLatestVersionOrNullAsync("Volo.Abp.Core", includeReleaseCandidates: true); var latestVersionFromMyGet = await GetLatestVersionFromMyGet("Volo.Abp.Core"); using (var fs = File.Open(projectPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) @@ -95,8 +95,8 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency includeNightlyPreviews, includeReleaseCandidates, switchToStable, - latestVersionFromNuget, - latestReleaseCandidateVersionFromNuget, + latestVersionInfo.Version, + latestReleaseCandidateVersionInfo.Version, latestVersionFromMyGet, version); @@ -137,11 +137,11 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency protected virtual async Task SpecifiedVersionExists(string version, string packageId) { - var versionList = await _nuGetService.GetPackageVersionListAsync(packageId); + var versionList = await _packageVersionCheckerService.GetPackageVersionListAsync(packageId); if (versionList.All(v => !v.Equals(version, StringComparison.OrdinalIgnoreCase))) { - versionList = await _nuGetService.GetPackageVersionListAsync(packageId, true); + versionList = await _packageVersionCheckerService.GetPackageVersionListAsync(packageId, true); } return versionList.Any(v => v.Equals(version, StringComparison.OrdinalIgnoreCase)); @@ -240,13 +240,15 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency SemanticVersion latestVersion; if (currentSemanticVersion.IsPrerelease && !switchToStable) { - latestVersion = latestNugetReleaseCandidateVersion == null || isLeptonXPackage ? - await _nuGetService.GetLatestVersionOrNullAsync(packageId, includeReleaseCandidates: true) : latestNugetReleaseCandidateVersion; + latestVersion = latestNugetReleaseCandidateVersion == null || isLeptonXPackage + ? (await _packageVersionCheckerService.GetLatestVersionOrNullAsync(packageId, includeReleaseCandidates: true))?.Version + : latestNugetReleaseCandidateVersion; } else { - latestVersion = latestNugetVersion == null || isLeptonXPackage ? - await _nuGetService.GetLatestVersionOrNullAsync(packageId, includeReleaseCandidates: includeReleaseCandidates) : latestNugetVersion; + latestVersion = latestNugetVersion == null || isLeptonXPackage + ? (await _packageVersionCheckerService.GetLatestVersionOrNullAsync(packageId, includeReleaseCandidates: includeReleaseCandidates))?.Version + : latestNugetVersion; } if (latestVersion != null && (currentSemanticVersion < latestVersion || (currentSemanticVersion.IsPrerelease && switchToStable))) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/CommercialPackages.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Version/CommercialPackages.cs similarity index 95% rename from framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/CommercialPackages.cs rename to framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Version/CommercialPackages.cs index 096fe9f314..e99eddb499 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/CommercialPackages.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Version/CommercialPackages.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace Volo.Abp.Cli.NuGet; +namespace Volo.Abp.Cli.Version; internal static class CommercialPackages { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Version/LatestVersionInfo.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Version/LatestVersionInfo.cs new file mode 100644 index 0000000000..e586e0df11 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Version/LatestVersionInfo.cs @@ -0,0 +1,16 @@ +using NuGet.Versioning; + +namespace Volo.Abp.Cli.Version; + +public class LatestVersionInfo +{ + public SemanticVersion Version { get; } + + public string Message { get; } + + public LatestVersionInfo(SemanticVersion version, string message = null) + { + Version = version; + Message = message; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Version/PackageVersionCheckerService.cs similarity index 69% rename from framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs rename to framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Version/PackageVersionCheckerService.cs index 8800d0f05a..c005ff7b2a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Version/PackageVersionCheckerService.cs @@ -3,6 +3,7 @@ using Newtonsoft.Json; using NuGet.Versioning; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -14,9 +15,9 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Json; using Volo.Abp.Threading; -namespace Volo.Abp.Cli.NuGet; +namespace Volo.Abp.Cli.Version; -public class NuGetService : ITransientDependency +public class PackageVersionCheckerService : ITransientDependency { public ILogger Logger { get; set; } protected IJsonSerializer JsonSerializer { get; } @@ -26,7 +27,7 @@ public class NuGetService : ITransientDependency private readonly CliHttpClientFactory _cliHttpClientFactory; private DeveloperApiKeyResult _apiKeyResult; - public NuGetService( + public PackageVersionCheckerService( IJsonSerializer jsonSerializer, IRemoteServiceExceptionHandler remoteServiceExceptionHandler, ICancellationTokenProvider cancellationTokenProvider, @@ -58,26 +59,30 @@ public class NuGetService : ITransientDependency return versionList.Contains(version); } - public async Task GetLatestVersionOrNullAsync(string packageId, bool includeNightly = false, bool includeReleaseCandidates = false) + public async Task GetLatestVersionOrNullAsync(string packageId, bool includeNightly = false, bool includeReleaseCandidates = false) { - var versionList = await GetPackageVersionListAsync(packageId, includeNightly); + if (!includeNightly && !includeReleaseCandidates) + { + var latestStableVersionResult = await GetLatestStableVersionOrNullAsync(); + if (latestStableVersionResult == null) + { + return null; + } + return SemanticVersion.TryParse(latestStableVersionResult.Version, out var semanticVersion) + ? new LatestVersionInfo(semanticVersion, latestStableVersionResult.Message) + : null; + } + + var versionList = await GetPackageVersionListAsync(packageId, includeNightly); if (versionList == null) { return null; } List versions; - - if (!includeNightly && !includeReleaseCandidates) - { - versions = versionList - .Select(SemanticVersion.Parse) - .OrderByDescending(v => v, new VersionComparer()).ToList(); - - versions = versions.Where(x => !x.IsPrerelease).ToList(); - } - else if (!includeNightly && includeReleaseCandidates) + + if (!includeNightly && includeReleaseCandidates) { versions = versionList .Where(v => !v.Contains("-preview")) @@ -91,7 +96,9 @@ public class NuGetService : ITransientDependency .OrderByDescending(v => v, new VersionComparer()).ToList(); } - return versions.Any() ? versions.Max() : null; + return versions.Any() + ? new LatestVersionInfo(versions.Max()) + : null; } @@ -148,15 +155,13 @@ public class NuGetService : ITransientDependency logger: Logger )) { - if (responseMessage.StatusCode == System.Net.HttpStatusCode.NotFound) + if (responseMessage.StatusCode == HttpStatusCode.NotFound) { //the package doesn't exist... return null; } - else - { - await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage); - } + + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage); var responseContent = await responseMessage.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize(responseContent).Versions; @@ -183,9 +188,46 @@ public class NuGetService : ITransientDependency return CliUrls.GetNuGetPackageInfoUrl(_apiKeyResult.ApiKey, packageId); } + private async Task GetLatestStableVersionOrNullAsync() + { + try + { + var client = _cliHttpClientFactory.CreateClient(clientName: CliConsts.GithubHttpClientName, needsAuthentication: false); + + using (var responseMessage = await client.GetHttpResponseMessageWithRetryAsync( + CliUrls.LatestVersionCheckFullPath, + cancellationToken: CancellationTokenProvider.Token, + logger: Logger + )) + { + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage); + + var content = await responseMessage.Content.ReadAsStringAsync(); + var result = JsonSerializer.Deserialize>(content); + + return result.FirstOrDefault(x => x.Type.ToLowerInvariant() == "stable"); + } + } + catch + { + return null; + } + } + public class NuGetVersionResultDto { [JsonProperty("versions")] public List Versions { get; set; } } + + public class LatestStableVersionResult + { + public string Version { get; set; } + + public DateTime? ReleaseDate { get; set; } + + public string Type { get; set; } + + public string Message { get; set; } + } } diff --git a/latest-versions.json b/latest-versions.json new file mode 100644 index 0000000000..afd4f0f8a4 --- /dev/null +++ b/latest-versions.json @@ -0,0 +1,8 @@ +[ + { + "version": "7.0.2", + "releaseDate": "", + "type": "stable", + "message": "" + } +] \ No newline at end of file