Skip to content

Commit

Permalink
Notify users of latest release version (#121)
Browse files Browse the repository at this point in the history
* Show warning message if version is outdated

* fix variable name

* fix spacing

* catch ratelimitexceeded error if no token is provided

* make loadgithubclient public

* revert githubclient to be protected

* fix tests

* handle command null error
  • Loading branch information
ryfu-msft authored Aug 5, 2021
1 parent de32cc8 commit 4e7f4cd
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 138 deletions.
98 changes: 49 additions & 49 deletions src/WingetCreateCLI/Commands/BaseCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,62 @@ public abstract class BaseCommand
/// <summary>
/// Gets the GitHubClient instance to use for interacting with GitHub from the CLI.
/// </summary>
protected GitHub GitHubClient { get; private set; }
internal GitHub GitHubClient { get; private set; }

/// <summary>
/// Abstract method executing the command.
/// </summary>
/// <returns>Boolean representing success or fail of the command.</returns>
public abstract Task<bool> Execute();

/// <summary>
/// Creates a new GitHub client using the provided or cached token if present.
/// If the requireToken bool is set to TRUE, OAuth flow can be launched to acquire a new token for the client.
/// The OAuth flow will only be launched if no token is provided in the command line and no token is present in the token cache.
/// </summary>
/// <param name="requireToken">Boolean value indicating whether a token is required for the client and whether to initiate an OAuth flow.</param>
/// <returns>A boolean value indicating whether a new GitHub client was created and accessed successfully.</returns>
public async Task<bool> LoadGitHubClient(bool requireToken = false)
{
bool isCacheToken = false;

if (string.IsNullOrEmpty(this.GitHubToken))
{
Logger.Trace("No token parameter, reading cached token");
this.GitHubToken = GitHubOAuth.ReadTokenCache();

if (string.IsNullOrEmpty(this.GitHubToken))
{
if (requireToken)
{
Logger.Trace("No token found in cache, launching OAuth flow");
if (!await this.GetTokenFromOAuth())
{
return false;
}
}
}
else
{
isCacheToken = true;
}
}

if (await this.CheckGitHubTokenAndSetClient())
{
return true;
}
else
{
if (isCacheToken)
{
GitHubOAuth.DeleteTokenCache();
}

return false;
}
}

/// <summary>
/// Creates a formatted directory of manifest files from the manifest object models and saves the directory to a local path.
/// </summary>
Expand Down Expand Up @@ -312,54 +360,6 @@ protected static void DisplayManifestPreview(Manifests manifests)
Console.WriteLine(manifests.DefaultLocaleManifest.ToYaml());
}

/// <summary>
/// Creates a new GitHub client using the provided or cached token if present.
/// If the requireToken bool is set to TRUE, OAuth flow can be launched to acquire a new token for the client.
/// The OAuth flow will only be launched if no token is provided in the command line and no token is present in the token cache.
/// </summary>
/// <param name="requireToken">Boolean value indicating whether a token is required for the client and whether to initiate an OAuth flow.</param>
/// <returns>A boolean value indicating whether a new GitHub client was created and accessed successfully.</returns>
protected async Task<bool> LoadGitHubClient(bool requireToken = false)
{
bool isCacheToken = false;

if (string.IsNullOrEmpty(this.GitHubToken))
{
Logger.Trace("No token parameter, reading cached token");
this.GitHubToken = GitHubOAuth.ReadTokenCache();

if (string.IsNullOrEmpty(this.GitHubToken))
{
if (requireToken)
{
Logger.Trace("No token found in cache, launching OAuth flow");
if (!await this.GetTokenFromOAuth())
{
return false;
}
}
}
else
{
isCacheToken = true;
}
}

if (await this.CheckGitHubTokenAndSetClient())
{
return true;
}
else
{
if (isCacheToken)
{
GitHubOAuth.DeleteTokenCache();
}

return false;
}
}

/// <summary>
/// Launches the GitHub OAuth flow and obtains a GitHub token.
/// </summary>
Expand Down
13 changes: 3 additions & 10 deletions src/WingetCreateCLI/Commands/NewCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,17 +141,10 @@ public override async Task<bool> Execute()
if (this.WingetRepoOwner == DefaultWingetRepoOwner &&
this.WingetRepo == DefaultWingetRepo)
{
if (await this.LoadGitHubClient())
{
if (!await this.PromptPackageIdentifierAndCheckDuplicates(manifests))
{
Console.WriteLine();
Logger.ErrorLocalized(nameof(Resources.PackageIdAlreadyExists_Error));
return false;
}
}
else
if (!await this.PromptPackageIdentifierAndCheckDuplicates(manifests))
{
Console.WriteLine();
Logger.ErrorLocalized(nameof(Resources.PackageIdAlreadyExists_Error));
return false;
}
}
Expand Down
5 changes: 0 additions & 5 deletions src/WingetCreateCLI/Commands/UpdateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,6 @@ public override async Task<bool> Execute()
return false;
}

if (!await this.LoadGitHubClient())
{
return false;
}

Logger.DebugLocalized(nameof(Resources.RetrievingManifest_Message), this.Id);

string exactId;
Expand Down
160 changes: 91 additions & 69 deletions src/WingetCreateCLI/Program.cs
Original file line number Diff line number Diff line change
@@ -1,88 +1,110 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.

namespace Microsoft.WingetCreateCLI
{
using System;
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.

namespace Microsoft.WingetCreateCLI
{
using System;
using System.Linq;
using System.Threading.Tasks;
using CommandLine;
using System.Threading.Tasks;
using CommandLine;
using CommandLine.Text;
using Microsoft.WingetCreateCLI.Commands;
using Microsoft.WingetCreateCLI.Logging;
using Microsoft.WingetCreateCLI.Properties;
using Microsoft.WingetCreateCLI.Telemetry;
using Microsoft.WingetCreateCLI.Telemetry.Events;
using Microsoft.WingetCreateCLI.Commands;
using Microsoft.WingetCreateCLI.Logging;
using Microsoft.WingetCreateCLI.Properties;
using Microsoft.WingetCreateCLI.Telemetry;
using Microsoft.WingetCreateCLI.Telemetry.Events;
using Microsoft.WingetCreateCore.Common;

/// <summary>
/// Main entry class for the CLI.
/// </summary>
internal class Program

/// <summary>
/// Main entry class for the CLI.
/// </summary>
internal class Program
{
private static async Task<int> Main(string[] args)
private static async Task<int> Main(string[] args)
{
Logger.Initialize();
UserSettings.FirstRunTelemetryConsent();
TelemetryEventListener.EventListener.IsTelemetryEnabled();

string arguments = string.Join(' ', Environment.GetCommandLineArgs());
Logger.Trace($"Command line args: {arguments}");

Parser myParser = new Parser(config => config.HelpWriter = null);

string arguments = string.Join(' ', Environment.GetCommandLineArgs());
Logger.Trace($"Command line args: {arguments}");

Parser myParser = new Parser(config => config.HelpWriter = null);

var types = new Type[] { typeof(NewCommand), typeof(UpdateCommand), typeof(SubmitCommand), typeof(SettingsCommand), typeof(TokenCommand), typeof(CacheCommand) };
var parserResult = myParser.ParseArguments(args, types);

BaseCommand command = parserResult.MapResult(c => c as BaseCommand, err => null);

if (command == null)
if (command == null)
{
DisplayHelp(parserResult as NotParsed<object>);
DisplayParsingErrors(parserResult as NotParsed<object>);
return args.Any() ? 1 : 0;
}

try
{
WingetCreateCore.Serialization.ProducedBy = string.Join(" ", Constants.ProgramName, Utils.GetEntryAssemblyVersion());
return await command.Execute() ? 0 : 1;
}
catch (Exception ex)
{
TelemetryManager.Log.WriteEvent(new GlobalExceptionEvent
{
ExceptionType = ex.GetType().ToString(),
ErrorMessage = ex.Message,
StackTrace = ex.StackTrace,
});

Logger.Error(ex.ToString());
return 1;
}
DisplayParsingErrors(parserResult as NotParsed<object>);
return args.Any() ? 1 : 0;
}

if (!await command.LoadGitHubClient())
{
return 1;
}

try
{
string latestVersion = await command.GitHubClient.GetLatestRelease();
string trimmedVersion = latestVersion.TrimStart('v').Split('-').First();
if (trimmedVersion != Utils.GetEntryAssemblyVersion())
{
Logger.WarnLocalized(nameof(Resources.OutdatedVersionNotice_Message));
Logger.WarnLocalized(nameof(Resources.GetLatestVersion_Message), latestVersion, "https://github.com/microsoft/winget-create/releases");
Logger.WarnLocalized(nameof(Resources.UpgradeUsingWinget_Message));
Console.WriteLine();
}
}
catch (Exception ex) when (ex is Octokit.ApiException || ex is Octokit.RateLimitExceededException)
{
// Since this is only notifying the user if an update is available, don't block if the token is invalid or a rate limit error is encountered.
}

try
{
WingetCreateCore.Serialization.ProducedBy = string.Join(" ", Constants.ProgramName, Utils.GetEntryAssemblyVersion());
return await command.Execute() ? 0 : 1;
}
catch (Exception ex)
{
TelemetryManager.Log.WriteEvent(new GlobalExceptionEvent
{
ExceptionType = ex.GetType().ToString(),
ErrorMessage = ex.Message,
StackTrace = ex.StackTrace,
});

Logger.Error(ex.ToString());
return 1;
}
}

private static void DisplayHelp(NotParsed<object> result)
{
var helpText = HelpText.AutoBuild(
result,
h =>
{
h.AddDashesToOption = true;
h.AdditionalNewLineAfterOption = false;
h.Heading = string.Format(Resources.Heading, Utils.GetEntryAssemblyVersion()) + Environment.NewLine;
h.Copyright = Constants.MicrosoftCopyright;
h.AddNewLineBetweenHelpSections = true;
h.AddPreOptionsLine(Resources.AppDescription_HelpText);
h.AddPostOptionsLines(new string[] { Resources.MoreHelp_HelpText, Resources.PrivacyStatement_HelpText });
h.MaximumDisplayWidth = 100;
h.AutoHelp = false;
h.AutoVersion = false;
return h;
},
e => e,
verbsIndex: true);
Console.WriteLine(helpText);

private static void DisplayHelp(NotParsed<object> result)
{
var helpText = HelpText.AutoBuild(
result,
h =>
{
h.AddDashesToOption = true;
h.AdditionalNewLineAfterOption = false;
h.Heading = string.Format(Resources.Heading, Utils.GetEntryAssemblyVersion()) + Environment.NewLine;
h.Copyright = Constants.MicrosoftCopyright;
h.AddNewLineBetweenHelpSections = true;
h.AddPreOptionsLine(Resources.AppDescription_HelpText);
h.AddPostOptionsLines(new string[] { Resources.MoreHelp_HelpText, Resources.PrivacyStatement_HelpText });
h.MaximumDisplayWidth = 100;
h.AutoHelp = false;
h.AutoVersion = false;
return h;
},
e => e,
verbsIndex: true);
Console.WriteLine(helpText);
Console.WriteLine();
}

Expand All @@ -97,4 +119,4 @@ private static void DisplayParsingErrors<T>(ParserResult<T> result)
}
}
}
}
}
29 changes: 28 additions & 1 deletion src/WingetCreateCLI/Properties/Resources.Designer.cs

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

Loading

0 comments on commit 4e7f4cd

Please sign in to comment.