diff --git a/src/Sarif.WorkItems/SarifWorkItemModel.cs b/src/Sarif.WorkItems/SarifWorkItemModel.cs index 4d2294974..65d2e0997 100644 --- a/src/Sarif.WorkItems/SarifWorkItemModel.cs +++ b/src/Sarif.WorkItems/SarifWorkItemModel.cs @@ -81,7 +81,7 @@ public class SarifWorkItemModel : WorkItemModel this.BodyOrDescription = Environment.NewLine + - sarifLog.CreateWorkItemDescription(this.Context, LocationUris) + + sarifLog.CreateWorkItemDescription(this.Context) + descriptionFooter; // These properties are Azure DevOps-specific. All ADO work item board diff --git a/src/Sarif.WorkItems/SarifWorkItemsExtensions.cs b/src/Sarif.WorkItems/SarifWorkItemsExtensions.cs index 3c844ac0d..8ce1cc30d 100644 --- a/src/Sarif.WorkItems/SarifWorkItemsExtensions.cs +++ b/src/Sarif.WorkItems/SarifWorkItemsExtensions.cs @@ -141,23 +141,32 @@ public static int GetAggregateFilableResultsCount(this SarifLog log) .Sum() ?? 0; } - public static string CreateWorkItemDescription(this SarifLog log, SarifWorkItemContext context, IList locationUris) + public static string CreateWorkItemDescription(this SarifLog log, SarifWorkItemContext context) { int totalResults = log.GetAggregateFilableResultsCount(); List toolNames = log.GetToolNames(); string phrasedToolNames = toolNames.ToAndPhrase(); string multipleToolsFooter = toolNames.Count > 1 ? WorkItemsResources.MultipleToolsFooter : string.Empty; + IEnumerable results = log.Runs?[0]?.Results.Where(r => r.ShouldBeFiled()); Uri runRepositoryUri = log?.Runs.FirstOrDefault()?.VersionControlProvenance?.FirstOrDefault().RepositoryUri; - Uri detectionLocationUri = !string.IsNullOrEmpty(runRepositoryUri?.OriginalString) ? runRepositoryUri : locationUris?[0]; + Uri detectionLocationUri = !string.IsNullOrEmpty(runRepositoryUri?.OriginalString) ? + runRepositoryUri : + results?.FirstOrDefault().Locations?[0].PhysicalLocation?.ArtifactLocation?.Uri; string detectionLocation = (detectionLocationUri?.IsAbsoluteUri == true && detectionLocationUri?.Scheme == "https") ? context.CreateLinkText(detectionLocationUri.OriginalString, detectionLocationUri?.OriginalString) : detectionLocationUri?.OriginalString; - if (locationUris?.Count > 1) + int locCount = results + .Where(r => r.Locations != null) + .SelectMany(r => r.Locations) + .Where(l => l.PhysicalLocation != null && l.PhysicalLocation.ArtifactLocation != null && l.PhysicalLocation.ArtifactLocation.Uri != null) + .Count(); + + if (locCount > 1) { - int additionalLocations = locationUris.Count - 1; + int additionalLocations = locCount - 1; detectionLocation = $"{detectionLocation} (+{additionalLocations} locations)"; } diff --git a/src/Test.UnitTests.Sarif.WorkItems/SarifWorkItemExtensionsTests.cs b/src/Test.UnitTests.Sarif.WorkItems/SarifWorkItemExtensionsTests.cs index 37176c6e8..028826a5b 100644 --- a/src/Test.UnitTests.Sarif.WorkItems/SarifWorkItemExtensionsTests.cs +++ b/src/Test.UnitTests.Sarif.WorkItems/SarifWorkItemExtensionsTests.cs @@ -225,6 +225,94 @@ public void SarifWorkItemExtensions_GetRunToolNames_FetchesAllRunToolNames() toolNames.Count.Should().Be(0); } + [Fact] + public void SarifWorkItemExtensions_CreateWorkItemDescription_SingleResultMultipleLocations() + { + string toolName = "TestToolName"; + string firstLocation = @"C:\Test\Data\File1.sarif"; + string additionLocationCount = "2"; + + SarifLog sarifLog = TestData.CreateOneIdThreeLocations(); + sarifLog.Runs[0].VersionControlProvenance = null; + + string description = sarifLog.CreateWorkItemDescription(new SarifWorkItemContext() { CurrentProvider = Microsoft.WorkItems.FilingClient.SourceControlProvider.AzureDevOps }); + + description.Should().BeEquivalentTo($"This work item contains 1 '{toolName}' issue(s) detected in {firstLocation} (+{additionLocationCount} locations). Click the 'Scans' tab to review results."); + } + + [Fact] + public void SarifWorkItemExtensions_CreateWorkItemDescription_SingleResultWithMultipleArtifacts() + { + string toolName = "TestToolName"; + string firstLocation = @"C:\Test\Data\File1.sarif"; + string secondLocation = @"C:\Test\Data\File2.sarif"; + string thirdLocation = @"C:\Test\Data\File3.sarif"; + + SarifLog sarifLog = TestData.CreateSimpleLogWithRules(0, 1); + sarifLog.Runs[0].Results[0].Locations = new[] + { + new Location + { + PhysicalLocation = new PhysicalLocation + { + ArtifactLocation = new ArtifactLocation + { + Uri = new Uri(firstLocation), + } + } + } + }; + + sarifLog.Runs[0].Results[0].RelatedLocations = new[] + { + new Location + { + PhysicalLocation = new PhysicalLocation + { + ArtifactLocation = new ArtifactLocation + { + Uri = new Uri(secondLocation), + } + } + } + }; + + sarifLog.Runs[0].Results[0].CodeFlows = new[] + { + new CodeFlow + { + ThreadFlows = new[] + { + new ThreadFlow + { + Locations = new[] + { + new ThreadFlowLocation + { + Location = new Location + { + PhysicalLocation = new PhysicalLocation + { + ArtifactLocation = new ArtifactLocation + { + Uri = new Uri(thirdLocation), + } + } + } + } + } + } + } + } + }; + + sarifLog.Runs[0].VersionControlProvenance = null; + + string description = sarifLog.CreateWorkItemDescription(new SarifWorkItemContext() { CurrentProvider = Microsoft.WorkItems.FilingClient.SourceControlProvider.AzureDevOps }); + + description.Should().BeEquivalentTo($"This work item contains 1 '{toolName}' issue(s) detected in {firstLocation}. Click the 'Scans' tab to review results."); + } + private static readonly string ToolName = Guid.NewGuid().ToString(); public Tuple[] ResultsWithVariousRuleExpressions = new[]