diff --git a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj
index e181af68ac..64b113fba9 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj
+++ b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj
@@ -15,6 +15,7 @@
+
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 707550e11b..2a12004cab 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
@@ -1,12 +1,12 @@
-using System;
-using System.Diagnostics;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using NuGet.Versioning;
+using System;
using System.IO;
+using System.Linq;
using System.Reflection;
-using System.Runtime.InteropServices;
-using Microsoft.Extensions.DependencyInjection;
using System.Threading.Tasks;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.Commands;
using Volo.Abp.Cli.NuGet;
@@ -18,7 +18,6 @@ namespace Volo.Abp.Cli
public class CliService : ITransientDependency
{
public ILogger Logger { get; set; }
-
protected ICommandLineArgumentParser CommandLineArgumentParser { get; }
protected ICommandSelector CommandSelector { get; }
protected IHybridServiceScopeFactory ServiceScopeFactory { get; }
@@ -40,11 +39,9 @@ namespace Volo.Abp.Cli
public async Task RunAsync(string[] args)
{
- Logger.LogInformation($"ABP CLI, version {GetCliVersion()}.");
- Logger.LogInformation("https://abp.io");
-
- await CheckForNewVersion();
+ Logger.LogInformation("ABP CLI (https://abp.io)");
+ await CheckCliVersionAsync();
CheckDependencies();
var commandLineArgs = CommandLineArgumentParser.Parse(args);
@@ -72,7 +69,7 @@ namespace Volo.Abp.Cli
private void CheckDependencies()
{
var installedNpmPackages = CmdHelper.RunCmdAndGetOutput("npm list -g --depth 0");
-
+
if (!installedNpmPackages.Contains(" yarn@"))
{
InstallYarn();
@@ -95,47 +92,107 @@ namespace Volo.Abp.Cli
CmdHelper.RunCmd("npm install gulp -g");
}
- private async Task CheckForNewVersion()
+ private async Task CheckCliVersionAsync()
{
+ var assembly = typeof(CliService).Assembly;
+
+ var toolPath = assembly.Location.Contains(".store") ? assembly.Location.Substring(0, assembly.Location.IndexOf(".store")) : null;
+ SemanticVersion currentCliVersion = default;
+
+ if (!string.IsNullOrEmpty(toolPath))
+ {
+ var strReader = new StringReader(CmdHelper.RunCmdAndGetOutput($"dotnet tool list --tool-path {toolPath}"));
+ string output;
+ while ((output = await strReader.ReadLineAsync()) != null)
+ {
+ if (output.StartsWith("Volo.Abp.Cli", StringComparison.InvariantCultureIgnoreCase) &&
+ SemanticVersion.TryParse(output.Split(new char[0], StringSplitOptions.RemoveEmptyEntries)[1], out var detectedVersion))
+ {
+ currentCliVersion = detectedVersion;
+ }
+ }
+ }
+
+ if (currentCliVersion == null)
+ {
+ // If not a tool executable, fallback to assembly version and treat as dev without updates
+ // Assembly revisions are not supported by SemVer scheme required for NuGet, trim to {major}.{minor}.{patch}
+ var assemblyVersion = string.Join(".", assembly.GetFileVersion().Split('.').Take(3));
+ currentCliVersion = SemanticVersion.Parse(assemblyVersion + "-dev");
+ }
+
+ var updateChannel =
+ currentCliVersion.IsPrerelease ?
+ currentCliVersion.Release.Contains("preview") ?
+ UpdateChannel.Nightly
+ : currentCliVersion.Release.Contains("dev") ?
+ UpdateChannel.Development
+ : UpdateChannel.Prerelease
+ : UpdateChannel.Stable;
+
+ Logger.LogInformation($"Version {currentCliVersion} ({updateChannel} channel)");
+
try
{
- var currentVersion = GetCliVersion();
- var latestVersion = await NuGetService.GetLatestVersionOrNullAsync("Volo.Abp.Cli");
+ SemanticVersion latestVersion = default;
- if (!latestVersion.IsNullOrEmpty() && currentVersion != latestVersion)
+ switch (updateChannel)
{
- Logger.LogInformation("");
- Logger.LogWarning("ABP CLI has a newer version (" + latestVersion + "). Please update to get the latest features and fixes.");
+ case UpdateChannel.Stable:
+ latestVersion = await NuGetService.GetLatestVersionOrNullAsync("Volo.Abp.Cli");
+ break;
+
+ case UpdateChannel.Prerelease:
+ latestVersion = await NuGetService.GetLatestVersionOrNullAsync("Volo.Abp.Cli", includePreviews: true);
+ break;
+
+ case UpdateChannel.Nightly:
+ latestVersion = await NuGetService.GetLatestVersionOrNullAsync("Volo.Abp.Cli", includeNightly: true);
+ break;
+ }
+
+ if (latestVersion != null & latestVersion > currentCliVersion)
+ {
+ Logger.LogWarning($"ABP CLI has a newer {updateChannel.ToString().ToLowerInvariant()} version {latestVersion}, please update to get the latest features and fixes.");
Logger.LogWarning("");
Logger.LogWarning("Update Command: ");
- Logger.LogWarning(" dotnet tool update -g Volo.Abp.Cli");
+
+ // Update command doesn't support prerelease versions https://github.com/dotnet/sdk/issues/2551 workaround is to uninstall & install
+ switch (updateChannel)
+ {
+ case UpdateChannel.Stable:
+ Logger.LogWarning($" dotnet tool update --tool-path {toolPath} Volo.Abp.Cli");
+ break;
+
+ case UpdateChannel.Prerelease:
+ Logger.LogWarning($" dotnet tool uninstall --tool-path {toolPath} Volo.Abp.Cli");
+ Logger.LogWarning($" dotnet tool install --tool-path {toolPath} --version {latestVersion} Volo.Abp.Cli");
+ break;
+
+ case UpdateChannel.Nightly:
+ Logger.LogWarning($" dotnet tool uninstall --tool-path {toolPath} Volo.Abp.Cli");
+ Logger.LogWarning($" dotnet tool install --tool-path {toolPath} --add-source https://www.myget.org/F/abp-nightly/api/v3/index.json --version {latestVersion} Volo.Abp.Cli");
+ break;
+ }
+
Logger.LogWarning("");
}
+
+ return;
}
catch (Exception e)
{
- Logger.LogWarning("Could not get the latest version infom from NuGet.org:");
+ Logger.LogWarning("Unable to retrieve the latest version");
Logger.LogWarning(e.Message);
}
}
- private static string GetCliVersion()
+ protected enum UpdateChannel
{
- var version = typeof(CliService)
- .Assembly
- .GetFileVersion();
-
- /* Assembly versions are like "2.4.0.0", but NuGet removes the last "0" here,
- * like "2.4.0".
- * So, we need to remove it from the assembly version to match to the NuGet version.
- */
-
- if (version.Split('.').Length == 4)
- {
- version = version.RemovePostFix(".0");
- }
-
- return version;
+ Development,
+ Stable,
+ Prerelease,
+ Nightly
}
}
-}
\ 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/NuGet/NuGetService.cs
index 115ce41d74..be0a444d0d 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs
@@ -1,4 +1,5 @@
using Newtonsoft.Json;
+using NuGet.Versioning;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -23,16 +24,17 @@ namespace Volo.Abp.Cli.NuGet
CancellationTokenProvider = cancellationTokenProvider;
}
- public async Task GetLatestVersionOrNullAsync(string packageId, bool includePreviews = false)
+ public async Task GetLatestVersionOrNullAsync(string packageId, bool includePreviews = false, bool includeNightly = false)
{
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromSeconds(30);
- var responseMessage = await client.GetAsync(
- $"https://api.nuget.org/v3-flatcontainer/{packageId.ToLowerInvariant()}/index.json",
- CancellationTokenProvider.Token
- );
+ var url = includeNightly ?
+ $"https://www.myget.org/F/abp-nightly/api/v3/flatcontainer/{packageId.ToLowerInvariant()}/index.json" :
+ $"https://api.nuget.org/v3-flatcontainer/{packageId.ToLowerInvariant()}/index.json";
+
+ var responseMessage = await client.GetAsync(url, CancellationTokenProvider.Token);
if (!responseMessage.IsSuccessStatusCode)
{
@@ -41,16 +43,14 @@ namespace Volo.Abp.Cli.NuGet
var result = await responseMessage.Content.ReadAsStringAsync();
- var versions = JsonSerializer.Deserialize(result).Versions;
+ var versions = JsonSerializer.Deserialize(result).Versions.Select(x => SemanticVersion.Parse(x));
- if (!includePreviews)
+ if (!includePreviews && !includeNightly)
{
- versions = versions
- .Where(x => !x.Contains("beta") && !x.Contains("preview") && !x.Contains("alpha") && !x.Contains("rc"))
- .ToList();
+ versions = versions.Where(x => !x.IsPrerelease);
}
- return versions.Count > 0 ? versions.Last() : null;
+ return versions.Any() ? versions.Max() : null;
}
}
@@ -60,4 +60,4 @@ namespace Volo.Abp.Cli.NuGet
public List Versions { get; set; }
}
}
-}
\ No newline at end of file
+}