From 73be82dd975d9211c25c07f008181bd0a642bc5b Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Sun, 28 Jul 2019 20:59:00 +0200 Subject: [PATCH] Added Azure Pipelines logging and better command line parsing support. --- .../AzurePipelinesMessageLogger.cs | 24 ++++ CompatibilityChecker/ConsoleMessageLogger.cs | 2 +- .../CompatibilityCheckerCLI.csproj | 3 + CompatibilityCheckerCLI/Program.cs | 105 +++++++++++------ .../CompatibilityCheckerCoreCLI.csproj | 1 + CompatibilityCheckerCoreCLI/Program.cs | 109 ++++++++++++------ .../PublishProfiles/FolderProfile.pubxml | 16 +++ .../Properties/launchSettings.json | 2 +- 8 files changed, 189 insertions(+), 73 deletions(-) create mode 100644 CompatibilityChecker/AzurePipelinesMessageLogger.cs create mode 100644 CompatibilityCheckerCoreCLI/Properties/PublishProfiles/FolderProfile.pubxml diff --git a/CompatibilityChecker/AzurePipelinesMessageLogger.cs b/CompatibilityChecker/AzurePipelinesMessageLogger.cs new file mode 100644 index 0000000..24f825f --- /dev/null +++ b/CompatibilityChecker/AzurePipelinesMessageLogger.cs @@ -0,0 +1,24 @@ +namespace CompatibilityChecker +{ + using System; + + public class AzurePipelinesMessageLogger : IMessageLogger + { + public virtual void Report(Message message) + { + switch (message.Severity) + { + case Severity.Error: + Console.Error.WriteLine("##vso[task.logissue type=error]{0}", message); + break; + case Severity.Warning: + Console.Error.WriteLine("##vso[task.logissue type=warning]{0}", message); + break; + default: + Console.WriteLine("##vso[task.logdetail]{0}",message); + break; + } + + } + } +} diff --git a/CompatibilityChecker/ConsoleMessageLogger.cs b/CompatibilityChecker/ConsoleMessageLogger.cs index 14dfa21..113c8bf 100644 --- a/CompatibilityChecker/ConsoleMessageLogger.cs +++ b/CompatibilityChecker/ConsoleMessageLogger.cs @@ -2,7 +2,7 @@ { using System; - internal class ConsoleMessageLogger : IMessageLogger + public class ConsoleMessageLogger : IMessageLogger { public virtual void Report(Message message) { diff --git a/CompatibilityCheckerCLI/CompatibilityCheckerCLI.csproj b/CompatibilityCheckerCLI/CompatibilityCheckerCLI.csproj index 3b42324..7400715 100644 --- a/CompatibilityCheckerCLI/CompatibilityCheckerCLI.csproj +++ b/CompatibilityCheckerCLI/CompatibilityCheckerCLI.csproj @@ -52,6 +52,9 @@ + + 2.5.0 + 1.6.0 diff --git a/CompatibilityCheckerCLI/Program.cs b/CompatibilityCheckerCLI/Program.cs index 410e03d..26e46ef 100644 --- a/CompatibilityCheckerCLI/Program.cs +++ b/CompatibilityCheckerCLI/Program.cs @@ -2,6 +2,9 @@ using System.Reflection; using System.Reflection.PortableExecutable; using CompatibilityChecker; +using CommandLine; +using System.Collections.Generic; +using CommandLine.Text; namespace CompatibilityCheckerCoreCLI { @@ -10,58 +13,92 @@ namespace CompatibilityCheckerCoreCLI internal class Program { + public class Options + { + [Value(0, MetaName = "reference assembly", Required = true, HelpText = "The reference assembly.")] + public string ReferenceAssembly { get; set; } + + [Value(1, MetaName = "new assembly", Required = true, HelpText = "The new assembly.")] + public string NewAssembly { get; set; } + + [Option('a', "azure-pipelines", Required = false, Default = false, HelpText = "Include the logging prefixes for Azure Pipelines.")] + public bool AzurePipelines { get; set; } + + [Usage(ApplicationAlias = "cccc")] + public static IEnumerable Examples { + get { + yield return new Example("Compare versions", new Options { ReferenceAssembly = "Assembly-1.0.0.dll", NewAssembly = "Assembly-1.0.1.dll" }); + yield return new Example("Compare versions in Azure Pipelines as CI", new Options { ReferenceAssembly = "Assembly-1.0.0.dll", NewAssembly = "Assembly-1.0.1.dll", AzurePipelines = true }); + } + } + + } + private static void Main(string[] args) { - if (args.Length != 2) + var result = CommandLine.Parser.Default.ParseArguments(args) + .WithParsed(opts => RunWithOptions(opts)); +#if DEBUG + Console.WriteLine("Done. Press any key to exit."); + Console.ReadKey(); +#endif + if (result.Tag == ParserResultType.NotParsed) { - Console.WriteLine("Usage: reference.dll new.dll"); Environment.ExitCode = 1; } - else - { + } - FileInfo referenceFile = new FileInfo(args[0]); - FileInfo newFile = new FileInfo(args[1]); - if (referenceFile.Exists && newFile.Exists) + private static void RunWithOptions(Options opts) + { + FileInfo referenceFile = new FileInfo(opts.ReferenceAssembly); + FileInfo newFile = new FileInfo(opts.NewAssembly); + if (referenceFile.Exists && newFile.Exists) + { + var refName = AssemblyName.GetAssemblyName(referenceFile.FullName); + var newName = AssemblyName.GetAssemblyName(newFile.FullName); + Console.WriteLine("{1}Using '{0}' as the reference assembly.", refName.FullName, opts.AzurePipelines ? "##vso[task.logdetail]" : string.Empty); + Console.WriteLine("{1}Using '{0}' as the new assembly.", refName.FullName, opts.AzurePipelines ? "##vso[task.logdetail]" : string.Empty); + using (PEReader referenceAssembly = new PEReader(File.OpenRead(referenceFile.FullName))) { - var refName = AssemblyName.GetAssemblyName(referenceFile.FullName); - var newName = AssemblyName.GetAssemblyName(newFile.FullName); - Console.WriteLine("Using '{0}' as the reference assembly.", refName.FullName); - Console.WriteLine("Using '{0}' as the new assembly.", refName.FullName); - using (PEReader referenceAssembly = new PEReader(File.OpenRead(referenceFile.FullName))) + using (PEReader newAssembly = new PEReader(File.OpenRead(newFile.FullName))) { - using (PEReader newAssembly = new PEReader(File.OpenRead(newFile.FullName))) + IMessageLogger logger = opts.AzurePipelines ? (IMessageLogger)new AzurePipelinesMessageLogger() : new ConsoleMessageLogger(); + Analyzer analyzer = new Analyzer(referenceAssembly, newAssembly, null, logger); + analyzer.Run(); + if (analyzer.HasRun) { - Analyzer analyzer = new Analyzer(referenceAssembly, newAssembly, null, null); - analyzer.Run(); - if (analyzer.HasRun) + if (analyzer.ResultStatistics.SeverityCounts.error > 0) { - Console.Error.WriteLine(string.Format("Analyzer done. {0} errors, {1} warnings, {2} informational items.", analyzer.ResultStatistics.SeverityCounts.error, analyzer.ResultStatistics.SeverityCounts.warning, analyzer.ResultStatistics.SeverityCounts.information)); - if (analyzer.ResultStatistics.SeverityCounts.error > 0) - { - Environment.ExitCode = -2; - } + Console.WriteLine(string.Format("{3}Analyzer done. {0} errors, {1} warnings, {2} informational items.", analyzer.ResultStatistics.SeverityCounts.error, analyzer.ResultStatistics.SeverityCounts.warning, analyzer.ResultStatistics.SeverityCounts.information, opts.AzurePipelines ? "##vso[task.complete result=SucceededWithIssues]" : string.Empty)); + Environment.ExitCode = -2; + return; } else { - Environment.ExitCode = -1; + Console.WriteLine(string.Format("{3}Analyzer done. {0} errors, {1} warnings, {2} informational items.", analyzer.ResultStatistics.SeverityCounts.error, analyzer.ResultStatistics.SeverityCounts.warning, analyzer.ResultStatistics.SeverityCounts.information, opts.AzurePipelines ? "##vso[task.complete result=Succeeded]" : string.Empty)); + return; } } - } + else + { + Console.WriteLine(string.Format("{0}Analyzer failed to run.", opts.AzurePipelines ? "##vso[task.complete result=Failed]" : string.Empty)); + Environment.ExitCode = -1; + return; + } + } } - else - { - if (!referenceFile.Exists) - Console.Error.WriteLine("Reference file '{0}' not found or inaccessible.", referenceFile.FullName); - if (!newFile.Exists) - Console.Error.WriteLine("New file '{0}' not found or inaccessible.", newFile.FullName); - } + + } + else + { + if (!referenceFile.Exists) + Console.Error.WriteLine("{1}Reference file '{0}' not found or inaccessible.", referenceFile.FullName, opts.AzurePipelines ? "##vso[task.logissue type=error]" : string.Empty); + if (!newFile.Exists) + Console.Error.WriteLine("{1}New file '{0}' not found or inaccessible.", newFile.FullName, opts.AzurePipelines ? "##vso[task.logissue type=error]" : string.Empty); + Environment.ExitCode = 2; + return; } -#if DEBUG - Console.WriteLine("Done. Press any key to exit."); - Console.ReadKey(); -#endif } } } \ No newline at end of file diff --git a/CompatibilityCheckerCoreCLI/CompatibilityCheckerCoreCLI.csproj b/CompatibilityCheckerCoreCLI/CompatibilityCheckerCoreCLI.csproj index 3c85359..e5cb810 100644 --- a/CompatibilityCheckerCoreCLI/CompatibilityCheckerCoreCLI.csproj +++ b/CompatibilityCheckerCoreCLI/CompatibilityCheckerCoreCLI.csproj @@ -16,6 +16,7 @@ + diff --git a/CompatibilityCheckerCoreCLI/Program.cs b/CompatibilityCheckerCoreCLI/Program.cs index 650fc09..c963027 100644 --- a/CompatibilityCheckerCoreCLI/Program.cs +++ b/CompatibilityCheckerCoreCLI/Program.cs @@ -2,6 +2,9 @@ using System.Reflection; using System.Reflection.PortableExecutable; using CompatibilityChecker; +using CommandLine; +using System.Collections.Generic; +using CommandLine.Text; namespace CompatibilityCheckerCoreCLI { @@ -10,59 +13,91 @@ namespace CompatibilityCheckerCoreCLI internal class Program { + public class Options + { + [Value(0, MetaName = "reference assembly", Required = true, HelpText = "The reference assembly.")] + public string ReferenceAssembly { get; set; } + + [Value(1, MetaName = "new assembly", Required = true, HelpText = "The new assembly.")] + public string NewAssembly { get; set; } + + [Option('a', "azure-pipelines", Required = false, Default = false, HelpText = "Include the logging prefixes for Azure Pipelines.")] + public bool AzurePipelines { get; set; } + + [Usage(ApplicationAlias = "cccc")] + public static IEnumerable Examples { + get { + yield return new Example("Compare versions", new Options { ReferenceAssembly = "Assembly-1.0.0.dll", NewAssembly = "Assembly-1.0.1.dll" }); + yield return new Example("Compare versions in Azure Pipelines as CI", new Options { ReferenceAssembly = "Assembly-1.0.0.dll", NewAssembly = "Assembly-1.0.1.dll", AzurePipelines = true }); + } + } + + } + private static void Main(string[] args) { - if (args.Length != 2) + var result = CommandLine.Parser.Default.ParseArguments(args) + .WithParsed(opts => RunWithOptions(opts)); +#if DEBUG + Console.WriteLine("Done. Press any key to exit."); + Console.ReadKey(); +#endif + if (result.Tag == ParserResultType.NotParsed) { - Console.WriteLine("Usage: reference.dll new.dll"); Environment.ExitCode = 1; } - else - { + } - FileInfo referenceFile = new FileInfo(args[0]); - FileInfo newFile = new FileInfo(args[1]); - if (referenceFile.Exists && newFile.Exists) + private static void RunWithOptions(Options opts) + { + FileInfo referenceFile = new FileInfo(opts.ReferenceAssembly); + FileInfo newFile = new FileInfo(opts.NewAssembly); + if (referenceFile.Exists && newFile.Exists) + { + var refName = AssemblyName.GetAssemblyName(referenceFile.FullName); + var newName = AssemblyName.GetAssemblyName(newFile.FullName); + Console.WriteLine("{1}Using '{0}' as the reference assembly.", refName.FullName, opts.AzurePipelines ? "##vso[task.logdetail]" : string.Empty); + Console.WriteLine("{1}Using '{0}' as the new assembly.", refName.FullName, opts.AzurePipelines ? "##vso[task.logdetail]" : string.Empty); + using (PEReader referenceAssembly = new PEReader(File.OpenRead(referenceFile.FullName))) { - var refName = AssemblyName.GetAssemblyName(referenceFile.FullName); - var newName = AssemblyName.GetAssemblyName(newFile.FullName); - Console.WriteLine("Using '{0}' as the reference assembly.", refName.FullName); - Console.WriteLine("Using '{0}' as the new assembly.", refName.FullName); - using (PEReader referenceAssembly = new PEReader(File.OpenRead(referenceFile.FullName))) + using (PEReader newAssembly = new PEReader(File.OpenRead(newFile.FullName))) { - using (PEReader newAssembly = new PEReader(File.OpenRead(newFile.FullName))) + IMessageLogger logger = opts.AzurePipelines ? (IMessageLogger)new AzurePipelinesMessageLogger() : new ConsoleMessageLogger(); + Analyzer analyzer = new Analyzer(referenceAssembly, newAssembly, null, logger); + analyzer.Run(); + if (analyzer.HasRun) { - Analyzer analyzer = new Analyzer(referenceAssembly, newAssembly, null, null); - analyzer.Run(); - if (analyzer.HasRun) + if (analyzer.ResultStatistics.SeverityCounts.error > 0) { - Console.Error.WriteLine(string.Format("Analyzer done. {0} errors, {1} warnings, {2} informational items.", analyzer.ResultStatistics.SeverityCounts.error, analyzer.ResultStatistics.SeverityCounts.warning, analyzer.ResultStatistics.SeverityCounts.information)); - if (analyzer.ResultStatistics.SeverityCounts.error > 0) - { - Environment.ExitCode = -2; - } - } - else + Console.WriteLine(string.Format("{3}Analyzer done. {0} errors, {1} warnings, {2} informational items.", analyzer.ResultStatistics.SeverityCounts.error, analyzer.ResultStatistics.SeverityCounts.warning, analyzer.ResultStatistics.SeverityCounts.information, opts.AzurePipelines ? "##vso[task.complete result=SucceededWithIssues]" : string.Empty)); + Environment.ExitCode = -2; + return; + } else { - Environment.ExitCode = -1; + Console.WriteLine(string.Format("{3}Analyzer done. {0} errors, {1} warnings, {2} informational items.", analyzer.ResultStatistics.SeverityCounts.error, analyzer.ResultStatistics.SeverityCounts.warning, analyzer.ResultStatistics.SeverityCounts.information, opts.AzurePipelines ? "##vso[task.complete result=Succeeded]" : string.Empty)); + return; } } - } + else + { + Console.WriteLine(string.Format("{0}Analyzer failed to run.", opts.AzurePipelines ? "##vso[task.complete result=Failed]" : string.Empty)); + Environment.ExitCode = -1; + return; + } + } } - else - { - if (!referenceFile.Exists) - Console.Error.WriteLine("Reference file '{0}' not found or inaccessible.", referenceFile.FullName); - if (!newFile.Exists) - Console.Error.WriteLine("New file '{0}' not found or inaccessible.", newFile.FullName); - Environment.ExitCode = 2; - } + + } + else + { + if (!referenceFile.Exists) + Console.Error.WriteLine("{1}Reference file '{0}' not found or inaccessible.", referenceFile.FullName, opts.AzurePipelines ? "##vso[task.logissue type=error]" : string.Empty); + if (!newFile.Exists) + Console.Error.WriteLine("{1}New file '{0}' not found or inaccessible.", newFile.FullName, opts.AzurePipelines ? "##vso[task.logissue type=error]" : string.Empty); + Environment.ExitCode = 2; + return; } -#if DEBUG - Console.WriteLine("Done. Press any key to exit."); - Console.ReadKey(); -#endif } } } \ No newline at end of file diff --git a/CompatibilityCheckerCoreCLI/Properties/PublishProfiles/FolderProfile.pubxml b/CompatibilityCheckerCoreCLI/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..b2304cb --- /dev/null +++ b/CompatibilityCheckerCoreCLI/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,16 @@ + + + + + FileSystem + Release + Any CPU + netcoreapp2.2 + bin\Release\netcoreapp2.2\publish\ + linux-x64 + false + <_IsPortable>true + + \ No newline at end of file diff --git a/CompatibilityCheckerCoreCLI/Properties/launchSettings.json b/CompatibilityCheckerCoreCLI/Properties/launchSettings.json index d66f7e3..cede676 100644 --- a/CompatibilityCheckerCoreCLI/Properties/launchSettings.json +++ b/CompatibilityCheckerCoreCLI/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "CompatibilityCheckerCoreExample": { "commandName": "Project", - "commandLineArgs": "\"..\\..\\..\\..\\MediaBrowser.Common.10.1.0.dll\" \"..\\..\\..\\..\\MediaBrowser.Common.10.2.0.dll\"" + "commandLineArgs": "\"..\\..\\..\\..\\MediaBrowser.Common_nuget.dll\" \"..\\..\\..\\..\\MediaBrowser.Common_artifact.dll\" --azure-pipelines" } } } \ No newline at end of file