diff --git a/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/Context/State/IIssuesState.cs b/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/Context/State/IIssuesState.cs index 37618852..1d48b594 100644 --- a/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/Context/State/IIssuesState.cs +++ b/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/Context/State/IIssuesState.cs @@ -69,15 +69,29 @@ public interface IIssuesState IEnumerable Issues { get; } /// - /// Adds an issue to the data class. + /// Gets the list of issue providers and runs for which issues are read. + /// + IList<(IIssueProvider, string)> IssueProvidersAndRuns { get; } + + /// + /// Adds an issue to . + /// To read issues from an issue provider use . /// /// Issue which should be added. void AddIssue(IIssue issue); /// - /// Adds a list of issues to the data class. + /// Adds a list of issues to . + /// To read issues from an issue provider use . /// /// Issues which should be added. void AddIssues(IEnumerable issues); + + /// + /// Reads issues from an issue provider and adds the issues to . + /// + /// Issue provider used to read the issues. + /// Settings for reading the issues. Null for default values. + void AddIssues(IIssueProvider issueProvider, IReadIssuesSettings settings); } } diff --git a/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/Context/State/IssuesState.cs b/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/Context/State/IssuesState.cs index ef4ad7e6..1671fd7f 100644 --- a/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/Context/State/IssuesState.cs +++ b/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/Context/State/IssuesState.cs @@ -6,6 +6,7 @@ using Cake.Issues; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; namespace Cake.Frosting.Issues.Recipe { @@ -14,8 +15,12 @@ namespace Cake.Frosting.Issues.Recipe /// public class IssuesState : IIssuesState { + private readonly IIssuesContext context; + private readonly List issues = new List(); + private readonly List<(IIssueProvider, string)> issueProvidersAndRuns = new List<(IIssueProvider, string)>(); + /// public DirectoryPath RepositoryRootDirectory { get; } @@ -49,6 +54,9 @@ public class IssuesState : IIssuesState /// public IEnumerable Issues => this.issues.AsReadOnly(); + /// + public IList<(IIssueProvider, string)> IssueProvidersAndRuns => this.issueProvidersAndRuns.AsReadOnly(); + /// /// Creates a new instance of the class. /// @@ -63,6 +71,8 @@ public IssuesState( throw new ArgumentNullException(nameof(context)); } + this.context = context; + this.BuildRootDirectory = context.MakeAbsolute(context.Directory("./")); context.Information("Build script root directory: {0}", this.BuildRootDirectory); @@ -114,6 +124,28 @@ public void AddIssues(IEnumerable issues) this.issues.AddRange(issues); } + /// + public void AddIssues(IIssueProvider issueProvider, IReadIssuesSettings settings) + { + issueProvider.NotNull(nameof(issueProvider)); + + this.issueProvidersAndRuns.Add((issueProvider, settings?.Run)); + + // Define default settings. + var defaultSettings = new ReadIssuesSettings(this.ProjectRootDirectory); + + if (this.PullRequestSystem != null) + { + defaultSettings.FileLinkSettings = + this.PullRequestSystem.GetFileLinkSettings(context); + } + + AddIssues( + context.ReadIssues( + issueProvider, + GetSettings(settings, defaultSettings))); + } + /// /// Determines the repository info provider to use. /// @@ -212,5 +244,20 @@ private static IIssuesPullRequestSystem DeterminePullRequestSystem(IIssuesContex return null; } + + private static IReadIssuesSettings GetSettings(IReadIssuesSettings configuredSettings, IReadIssuesSettings defaultSettings) + { + if (configuredSettings == null) + { + return defaultSettings; + } + + if (configuredSettings.FileLinkSettings == null) + { + configuredSettings.FileLinkSettings = defaultSettings.FileLinkSettings; + } + + return configuredSettings; + } } } diff --git a/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/PullRequestSystems/AzureDevOpsPullRequestSystem.cs b/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/PullRequestSystems/AzureDevOpsPullRequestSystem.cs index 15d9b083..64601dd9 100644 --- a/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/PullRequestSystems/AzureDevOpsPullRequestSystem.cs +++ b/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/PullRequestSystems/AzureDevOpsPullRequestSystem.cs @@ -58,21 +58,43 @@ public override void SetPullRequestIssuesState(IIssuesContext context) // Set status for individual issue providers if (context.Parameters.PullRequestSystem.ShouldSetSeparatePullRequestStatusForEachIssueProviderAndRun) { - foreach (var providerGroup in context.State.Issues.GroupBy(x => x.ProviderType)) + // Determine issue providers and runs from the list of issues providers from which issues were read + // and issue providers and runs of the reported issues. + var issueProvidersAndRuns = + context.State.IssueProvidersAndRuns + .Select(x => + new + { + x.Item1.ProviderName, + Run = x.Item2 + }) + .Union( + context.State.Issues + .GroupBy(x => + new + { + x.ProviderName, + x.Run + }) + .Select(x => + new + { + x.Key.ProviderName, + x.Key.Run + })); + + foreach (var item in issueProvidersAndRuns) { - var issueProvider = providerGroup.Key; - foreach (var runGroup in providerGroup.GroupBy(x => x.Run)) + var issueProvider = item.ProviderName; + if (!string.IsNullOrEmpty(item.Run)) { - if (!string.IsNullOrEmpty(runGroup.Key)) - { - issueProvider += $"-{runGroup.Key}"; - } - - SetPullRequestStatus( - context, - runGroup, - issueProvider); + issueProvider += $" ({item.Run})"; } + + SetPullRequestStatus( + context, + context.State.Issues.Where(x => x.ProviderName == item.ProviderName && x.Run == item.Run), + issueProvider); } } } diff --git a/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/ReadIssuesTask.cs b/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/ReadIssuesTask.cs index 9d11944e..d4616e8d 100644 --- a/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/ReadIssuesTask.cs +++ b/Cake.Frosting.Issues.Recipe/Cake.Frosting.Issues.Recipe/ReadIssuesTask.cs @@ -20,117 +20,83 @@ public override void Run(IIssuesContext context) { context.NotNull(nameof(context)); - // Define default settings. - var defaultSettings = new ReadIssuesSettings(context.State.ProjectRootDirectory); - - if (context.State.PullRequestSystem != null) - { - defaultSettings.FileLinkSettings = - context.State.PullRequestSystem.GetFileLinkSettings(context); - } - // Read MSBuild log files created by XmlFileLogger. foreach (var logFile in context.Parameters.InputFiles.MsBuildXmlFileLoggerLogFilePaths) { - context.NotNull(nameof(context)); - context.State.AddIssues( - context.ReadIssues( - context.MsBuildIssuesFromFilePath( - logFile.Key, - context.MsBuildXmlFileLoggerFormat()), - GetSettings(logFile.Value, defaultSettings))); + context.MsBuildIssuesFromFilePath( + logFile.Key, + context.MsBuildXmlFileLoggerFormat()), + logFile.Value); } // Read MSBuild binary log files. foreach (var logFile in context.Parameters.InputFiles.MsBuildBinaryLogFilePaths) { context.State.AddIssues( - context.ReadIssues( - context.MsBuildIssuesFromFilePath( - logFile.Key, - context.MsBuildBinaryLogFileFormat()), - GetSettings(logFile.Value, defaultSettings))); + context.MsBuildIssuesFromFilePath( + logFile.Key, + context.MsBuildBinaryLogFileFormat()), + logFile.Value); } // Read InspectCode log files. foreach (var logFile in context.Parameters.InputFiles.InspectCodeLogFilePaths) { context.State.AddIssues( - context.ReadIssues( - context.InspectCodeIssuesFromFilePath(logFile.Key), - GetSettings(logFile.Value, defaultSettings))); + context.InspectCodeIssuesFromFilePath(logFile.Key), + logFile.Value); } // Read dupFinder log files. foreach (var logFile in context.Parameters.InputFiles.DupFinderLogFilePaths) { context.State.AddIssues( - context.ReadIssues( - context.DupFinderIssuesFromFilePath(logFile.Key), - GetSettings(logFile.Value, defaultSettings))); + context.DupFinderIssuesFromFilePath(logFile.Key), + logFile.Value); } // Read markdownlint-cli log files. foreach (var logFile in context.Parameters.InputFiles.MarkdownlintCliLogFilePaths) { context.State.AddIssues( - context.ReadIssues( - context.MarkdownlintIssuesFromFilePath( - logFile.Key, - context.MarkdownlintCliLogFileFormat()), - GetSettings(logFile.Value, defaultSettings))); + context.MarkdownlintIssuesFromFilePath( + logFile.Key, + context.MarkdownlintCliLogFileFormat()), + logFile.Value); } // Read markdownlint-cli log files created with --json. foreach (var logFile in context.Parameters.InputFiles.MarkdownlintCliJsonLogFilePaths) { context.State.AddIssues( - context.ReadIssues( - context.MarkdownlintIssuesFromFilePath( - logFile.Key, - context.MarkdownlintCliJsonLogFileFormat()), - GetSettings(logFile.Value, defaultSettings))); + context.MarkdownlintIssuesFromFilePath( + logFile.Key, + context.MarkdownlintCliJsonLogFileFormat()), + logFile.Value); } // Read markdownlint log files in version 1. foreach (var logFile in context.Parameters.InputFiles.MarkdownlintV1LogFilePaths) { context.State.AddIssues( - context.ReadIssues( - context.MarkdownlintIssuesFromFilePath( - logFile.Key, - context.MarkdownlintV1LogFileFormat()), - GetSettings(logFile.Value, defaultSettings))); + context.MarkdownlintIssuesFromFilePath( + logFile.Key, + context.MarkdownlintV1LogFileFormat()), + logFile.Value); } // Read ESLint log files in JSON format. foreach (var logFile in context.Parameters.InputFiles.EsLintJsonLogFilePaths) { context.State.AddIssues( - context.ReadIssues( - context.EsLintIssuesFromFilePath( - logFile.Key, - context.EsLintJsonFormat()), - GetSettings(logFile.Value, defaultSettings))); + context.EsLintIssuesFromFilePath( + logFile.Key, + context.EsLintJsonFormat()), + logFile.Value); } context.Information("{0} issues are found.", context.State.Issues.Count()); } - - private static IReadIssuesSettings GetSettings(IReadIssuesSettings configuredSettings, IReadIssuesSettings defaultSettings) - { - if (configuredSettings == null) - { - return defaultSettings; - } - - if (configuredSettings.FileLinkSettings == null) - { - configuredSettings.FileLinkSettings = defaultSettings.FileLinkSettings; - } - - return configuredSettings; - } } } diff --git a/Cake.Issues.Recipe/Content/build.cake b/Cake.Issues.Recipe/Content/build.cake index 73a5acfd..abb6f6b9 100644 --- a/Cake.Issues.Recipe/Content/build.cake +++ b/Cake.Issues.Recipe/Content/build.cake @@ -44,97 +44,80 @@ IssuesBuildTasks.ReadIssuesTask = Task("Read-Issues") .Description("Reads issues from the provided log files.") .Does((data) => { - // Define default settings. - var defaultSettings = new ReadIssuesSettings(data.ProjectRootDirectory); - - if (data.PullRequestSystem != null) - { - defaultSettings.FileLinkSettings = - data.PullRequestSystem.GetFileLinkSettings(Context, data); - } - // Read MSBuild log files created by XmlFileLogger. foreach (var logFile in IssuesParameters.InputFiles.MsBuildXmlFileLoggerLogFilePaths) { data.AddIssues( - ReadIssues( - MsBuildIssuesFromFilePath( - logFile.Key, - MsBuildXmlFileLoggerFormat), - GetSettings(logFile.Value, defaultSettings))); + MsBuildIssuesFromFilePath( + logFile.Key, + MsBuildXmlFileLoggerFormat), + logFile.Value); } // Read MSBuild binary log files. foreach (var logFile in IssuesParameters.InputFiles.MsBuildBinaryLogFilePaths) { data.AddIssues( - ReadIssues( - MsBuildIssuesFromFilePath( - logFile.Key, - MsBuildBinaryLogFileFormat), - GetSettings(logFile.Value, defaultSettings))); + MsBuildIssuesFromFilePath( + logFile.Key, + MsBuildBinaryLogFileFormat), + logFile.Value); } // Read InspectCode log files. foreach (var logFile in IssuesParameters.InputFiles.InspectCodeLogFilePaths) { data.AddIssues( - ReadIssues( - InspectCodeIssuesFromFilePath(logFile.Key), - GetSettings(logFile.Value, defaultSettings))); + InspectCodeIssuesFromFilePath(logFile.Key), + logFile.Value); } // Read dupFinder log files. foreach (var logFile in IssuesParameters.InputFiles.DupFinderLogFilePaths) { data.AddIssues( - ReadIssues( - DupFinderIssuesFromFilePath(logFile.Key), - GetSettings(logFile.Value, defaultSettings))); + DupFinderIssuesFromFilePath(logFile.Key), + logFile.Value); } // Read markdownlint-cli log files. foreach (var logFile in IssuesParameters.InputFiles.MarkdownlintCliLogFilePaths) { data.AddIssues( - ReadIssues( - MarkdownlintIssuesFromFilePath( - logFile.Key, - MarkdownlintCliLogFileFormat), - GetSettings(logFile.Value, defaultSettings))); + MarkdownlintIssuesFromFilePath( + logFile.Key, + MarkdownlintCliLogFileFormat), + logFile.Value); } // Read markdownlint-cli log files created with --json. foreach (var logFile in IssuesParameters.InputFiles.MarkdownlintCliJsonLogFilePaths) { data.AddIssues( - ReadIssues( - MarkdownlintIssuesFromFilePath( - logFile.Key, - MarkdownlintCliJsonLogFileFormat), - GetSettings(logFile.Value, defaultSettings))); + MarkdownlintIssuesFromFilePath( + logFile.Key, + MarkdownlintCliJsonLogFileFormat), + logFile.Value); } // Read markdownlint log files in version 1. foreach (var logFile in IssuesParameters.InputFiles.MarkdownlintV1LogFilePaths) { data.AddIssues( - ReadIssues( - MarkdownlintIssuesFromFilePath( - logFile.Key, - MarkdownlintV1LogFileFormat), - GetSettings(logFile.Value, defaultSettings))); + MarkdownlintIssuesFromFilePath( + logFile.Key, + MarkdownlintV1LogFileFormat), + logFile.Value); } // Read ESLint log files in JSON format. foreach (var logFile in IssuesParameters.InputFiles.EsLintJsonLogFilePaths) { data.AddIssues( - ReadIssues( - EsLintIssuesFromFilePath( - logFile.Key, - EsLintJsonFormat), - GetSettings(logFile.Value, defaultSettings))); + EsLintIssuesFromFilePath( + logFile.Key, + EsLintJsonFormat), + logFile.Value); } Information("{0} issues are found.", data.Issues.Count()); @@ -248,23 +231,4 @@ IssuesBuildTasks.SetPullRequestIssuesStateTask = Task("Set-PullRequestIssuesStat data.PullRequestSystem.SetPullRequestIssuesState(Context, data); }); -/////////////////////////////////////////////////////////////////////////////// -// HELPER Functions -/////////////////////////////////////////////////////////////////////////////// - -private static IReadIssuesSettings GetSettings(IReadIssuesSettings configuredSettings, IReadIssuesSettings defaultSettings) -{ - if (configuredSettings == null) - { - return defaultSettings; - } - - if (configuredSettings.FileLinkSettings == null) - { - configuredSettings.FileLinkSettings = defaultSettings.FileLinkSettings; - } - - return configuredSettings; -} - #load tasks/tasks.cake diff --git a/Cake.Issues.Recipe/Content/data/IssuesData.cake b/Cake.Issues.Recipe/Content/data/IssuesData.cake index 28a2f0cb..4fe56046 100644 --- a/Cake.Issues.Recipe/Content/data/IssuesData.cake +++ b/Cake.Issues.Recipe/Content/data/IssuesData.cake @@ -3,8 +3,12 @@ /// public class IssuesData { + private readonly ICakeContext context; + private readonly List issues = new List(); + private readonly List<(IIssueProvider, string)> issueProvidersAndRuns = new List<(IIssueProvider, string)>(); + /// /// Gets the root directory of the repository. /// @@ -68,6 +72,17 @@ public class IssuesData } } + /// + /// Gets the list of issue providers and runs for which issues are read. + /// + public IList<(IIssueProvider, string)> IssueProvidersAndRuns + { + get + { + return issueProvidersAndRuns.AsReadOnly(); + } + } + /// /// Creates a new instance of the class. /// @@ -77,6 +92,8 @@ public class IssuesData { context.NotNull(nameof(context)); + this.context = context; + this.BuildRootDirectory = context.MakeAbsolute(context.Directory("./")); context.Information("Build script root directory: {0}", this.BuildRootDirectory); @@ -118,7 +135,8 @@ public class IssuesData } /// - /// Adds a list of issues to the data class. + /// Adds a list of issues to . + /// To read issues from an issue provider use . /// Adds a list of issues to the data class. /// /// Issues which should be added. public void AddIssues(IEnumerable issues) @@ -128,6 +146,32 @@ public class IssuesData this.issues.AddRange(issues); } + /// + /// Reads issues from an issue provider and adds the issues to . + /// + /// Issue provider used to read the issues. + /// Settings for reading the issues. Null for default values. + public void AddIssues(IIssueProvider issueProvider, IReadIssuesSettings settings) + { + issueProvider.NotNull(nameof(issueProvider)); + + this.issueProvidersAndRuns.Add((issueProvider, settings?.Run)); + + // Define default settings. + var defaultSettings = new ReadIssuesSettings(this.ProjectRootDirectory); + + if (this.PullRequestSystem != null) + { + defaultSettings.FileLinkSettings = + this.PullRequestSystem.GetFileLinkSettings(this.context, this); + } + + AddIssues( + context.ReadIssues( + issueProvider, + GetSettings(settings, defaultSettings))); + } + /// /// Determines the repository info provider to use. /// @@ -216,4 +260,19 @@ public class IssuesData return null; } + + private static IReadIssuesSettings GetSettings(IReadIssuesSettings configuredSettings, IReadIssuesSettings defaultSettings) + { + if (configuredSettings == null) + { + return defaultSettings; + } + + if (configuredSettings.FileLinkSettings == null) + { + configuredSettings.FileLinkSettings = defaultSettings.FileLinkSettings; + } + + return configuredSettings; + } } diff --git a/Cake.Issues.Recipe/Content/tasks/pullrequestsystems/AzureDevOpsPullRequestSystem.cake b/Cake.Issues.Recipe/Content/tasks/pullrequestsystems/AzureDevOpsPullRequestSystem.cake index 641360b6..0b6663f7 100644 --- a/Cake.Issues.Recipe/Content/tasks/pullrequestsystems/AzureDevOpsPullRequestSystem.cake +++ b/Cake.Issues.Recipe/Content/tasks/pullrequestsystems/AzureDevOpsPullRequestSystem.cake @@ -49,22 +49,44 @@ public class AzureDevOpsPullRequestSystem : BasePullRequestSystem // Set status for individual issue providers if (IssuesParameters.PullRequestSystem.ShouldSetSeparatePullRequestStatusForEachIssueProviderAndRun) { - foreach (var providerGroup in data.Issues.GroupBy(x => x.ProviderType)) + // Determine issue providers and runs from the list of issues providers from which issues were read + // and issue providers and runs of the reported issues. + var issueProvidersAndRuns = + data.IssueProvidersAndRuns + .Select(x => + new + { + x.Item1.ProviderName, + Run = x.Item2 + }) + .Union( + data.Issues + .GroupBy(x => + new + { + x.ProviderName, + x.Run + }) + .Select(x => + new + { + x.Key.ProviderName, + x.Key.Run + })); + + foreach (var item in issueProvidersAndRuns) { - var issueProvider = providerGroup.Key; - foreach (var runGroup in providerGroup.GroupBy(x => x.Run)) + var issueProvider = item.ProviderName; + if (!string.IsNullOrEmpty(item.Run)) { - if (!string.IsNullOrEmpty(runGroup.Key)) - { - issueProvider += $"-{runGroup.Key}"; - } - - SetPullRequestStatus( - context, - data, - runGroup, - issueProvider); + issueProvider += $" ({item.Run})"; } + + SetPullRequestStatus( + context, + data, + data.Issues.Where(x => x.ProviderName == item.ProviderName && x.Run == item.Run), + issueProvider); } } }