diff --git a/domain/ide/workspace/folder.go b/domain/ide/workspace/folder.go index df52e7ee8..8aa755b16 100644 --- a/domain/ide/workspace/folder.go +++ b/domain/ide/workspace/folder.go @@ -200,33 +200,65 @@ func (f *Folder) processResults(scanData snyk.ScanData) { if !dedupMap[f.getUniqueIssueID(issue)] { cachedIssues = append(cachedIssues, issue) - - if scanData.SeverityCount == nil { - scanData.SeverityCount = make(map[product.Product]map[string]int) - } - - if scanData.SeverityCount[issue.Product] == nil { - scanData.SeverityCount[issue.Product] = make(map[string]int) - scanData.SeverityCount[issue.Product]["Critical"] = 0 - scanData.SeverityCount[issue.Product]["High"] = 0 - scanData.SeverityCount[issue.Product]["Medium"] = 0 - scanData.SeverityCount[issue.Product]["Low"] = 0 - } - - scanData.SeverityCount[issue.Product][issue.Severity.String()]++ + incrementSeverityCount(&scanData, issue) } f.documentDiagnosticCache.Store(issue.AffectedFilePath, cachedIssues) } log.Debug().Str("method", "processResults").Interface("scanData", scanData).Msg("Finished processing results. Sending analytics.") - sendAnalytics(scanData) + sendAnalytics(&scanData) // Filter and publish cached diagnostics f.FilterAndPublishCachedDiagnostics(scanData.Product) } -func sendAnalytics(data snyk.ScanData) { +func incrementSeverityCount(scanData *snyk.ScanData, issue snyk.Issue) { + issueProduct := issue.Product + if issueProduct == "" { + log.Debug().Str("method", "incrementSeverityCount").Msg("Issue product is empty. Setting to unknown") + issueProduct = "unknown" + } + + initializeSeverityCountForProduct(scanData, issueProduct) + + severityCount, exists := scanData.SeverityCount[issueProduct] + if !exists { + severityCount = snyk.SeverityCount{} + } + + switch issue.Severity { + case snyk.Critical: + severityCount.Critical++ + case snyk.High: + severityCount.High++ + case snyk.Medium: + severityCount.Medium++ + case snyk.Low: + severityCount.Low++ + } + + scanData.SeverityCount[issueProduct] = severityCount // reassign the value to the map +} + +func initializeSeverityCountForProduct(scanData *snyk.ScanData, productType product.Product) { + if scanData.SeverityCount == nil { + scanData.SeverityCount = make(map[product.Product]snyk.SeverityCount) + } + + if productType == "" { + log.Debug().Str("method", "initializeSeverityCountForProduct").Msg("Product is empty. Setting to unknown") + productType = "unknown" + } + + if _, exists := scanData.SeverityCount[productType]; !exists { + scanData.SeverityCount[productType] = snyk.SeverityCount{} + } +} + +func sendAnalytics(data *snyk.ScanData) { + initializeSeverityCountForProduct(data, data.Product) + c := config.CurrentConfig() gafConfig := c.Engine().GetConfiguration() @@ -256,10 +288,10 @@ func sendAnalytics(data snyk.ScanData) { scanEvent.Data.Attributes.EventType = "Scan done" scanEvent.Data.Attributes.Status = "Success" scanEvent.Data.Attributes.ScanType = string(data.Product) - scanEvent.Data.Attributes.UniqueIssueCount.Critical = data.SeverityCount[data.Product]["critical"] - scanEvent.Data.Attributes.UniqueIssueCount.High = data.SeverityCount[data.Product]["high"] - scanEvent.Data.Attributes.UniqueIssueCount.Medium = data.SeverityCount[data.Product]["medium"] - scanEvent.Data.Attributes.UniqueIssueCount.Low = data.SeverityCount[data.Product]["low"] + scanEvent.Data.Attributes.UniqueIssueCount.Critical = data.SeverityCount[data.Product].Critical + scanEvent.Data.Attributes.UniqueIssueCount.High = data.SeverityCount[data.Product].High + scanEvent.Data.Attributes.UniqueIssueCount.Medium = data.SeverityCount[data.Product].Medium + scanEvent.Data.Attributes.UniqueIssueCount.Low = data.SeverityCount[data.Product].Low scanEvent.Data.Attributes.DurationMs = fmt.Sprintf("%d", data.DurationMs) scanEvent.Data.Attributes.TimestampFinished = data.TimestampFinished diff --git a/domain/ide/workspace/folder_test.go b/domain/ide/workspace/folder_test.go index 5460a2061..08cfa865a 100644 --- a/domain/ide/workspace/folder_test.go +++ b/domain/ide/workspace/folder_test.go @@ -65,7 +65,7 @@ func Test_Scan_WhenNoIssues_shouldNotProcessResults(t *testing.T) { f := NewFolder("dummy", "dummy", snyk.NewTestScanner(), hoverRecorder, snyk.NewMockScanNotifier(), notification.NewNotifier()) data := snyk.ScanData{ - Product: "unknown", + Product: "", Issues: []snyk.Issue{}, } f.processResults(data) @@ -517,13 +517,13 @@ func Test_processResults_ShouldCountSeverityByProduct(t *testing.T) { scanData := snyk.ScanData{ Product: product.ProductOpenSource, - SeverityCount: make(map[product.Product]map[string]int), + SeverityCount: make(map[product.Product]snyk.SeverityCount), Issues: []snyk.Issue{ {Severity: snyk.Critical, Product: product.ProductOpenSource}, {Severity: snyk.Critical, Product: product.ProductOpenSource}, {Severity: snyk.High, Product: product.ProductOpenSource}, {Severity: snyk.High, Product: product.ProductOpenSource}, - {Severity: snyk.Critical, Product: product.ProductInfrastructureAsCode}, + {Severity: snyk.Critical, Product: product.ProductInfrastructureAsCode}, // SeverityCount incremented by ScanData.Product }, } @@ -534,7 +534,58 @@ func Test_processResults_ShouldCountSeverityByProduct(t *testing.T) { f.processResults(scanData) // Assert - require.Equal(t, 2, scanData.SeverityCount[product.ProductOpenSource][snyk.Critical.String()]) + require.Equal(t, 2, scanData.SeverityCount[product.ProductOpenSource].Critical) +} + +func Test_IncrementSeverityCount(t *testing.T) { + c := testutil.UnitTest(t) + c.SetAnalyticsEnabled(false) + + engineMock, gafConfig := setUpEngineMock(t, c) + + NewMockFolderWithScanNotifier(notification.NewNotifier()) + + issue := snyk.Issue{ + Severity: snyk.Critical, + Product: product.ProductOpenSource, + } + + scanData := snyk.ScanData{ + Product: product.ProductOpenSource, + SeverityCount: make(map[product.Product]snyk.SeverityCount), + Issues: []snyk.Issue{issue}, + } + + engineMock.EXPECT().GetConfiguration().AnyTimes().Return(gafConfig) + engineMock.EXPECT().InvokeWithInputAndConfig(localworkflows.WORKFLOWID_REPORT_ANALYTICS, gomock.Any(), gomock.Any()).Times(0) + + // Act + incrementSeverityCount(&scanData, scanData.Issues[0]) + + // Assert + require.Equal(t, 1, scanData.SeverityCount[product.ProductOpenSource].Critical) +} + +func Test_initializeSeverityCountForProductWhenScanDataIsEmpty(t *testing.T) { + c := testutil.UnitTest(t) + + engineMock, gafConfig := setUpEngineMock(t, c) + + NewMockFolderWithScanNotifier(notification.NewNotifier()) + + engineMock.EXPECT().GetConfiguration().AnyTimes().Return(gafConfig) + engineMock.EXPECT().InvokeWithInputAndConfig(localworkflows.WORKFLOWID_REPORT_ANALYTICS, gomock.Any(), gomock.Any()).Times(0) + + scanData := snyk.ScanData{} + + // Act + initializeSeverityCountForProduct(&scanData, "") + + // Assert + require.Equal(t, 0, scanData.SeverityCount["unknown"].Critical) + require.Equal(t, 0, scanData.SeverityCount["unknown"].High) + require.Equal(t, 0, scanData.SeverityCount["unknown"].Medium) + require.Equal(t, 0, scanData.SeverityCount["unknown"].Low) } func NewMockFolder(notifier noti.Notifier) *Folder { diff --git a/domain/snyk/scan_result_processor.go b/domain/snyk/scan_result_processor.go index c1e79a565..35b9396bf 100644 --- a/domain/snyk/scan_result_processor.go +++ b/domain/snyk/scan_result_processor.go @@ -32,8 +32,16 @@ type ScanData struct { High int Medium int Low int - SeverityCount map[product.Product]map[string]int + SeverityCount map[product.Product]SeverityCount } + +type SeverityCount struct { + Critical int + High int + Medium int + Low int +} + type ScanResultProcessor = func(scanData ScanData) //type ScanResultProcessor = func(product product.Product, issues []Issue, err error) diff --git a/infrastructure/cli/install/discovery_test.go b/infrastructure/cli/install/discovery_test.go index 826f5fb67..bbf37b568 100644 --- a/infrastructure/cli/install/discovery_test.go +++ b/infrastructure/cli/install/discovery_test.go @@ -41,6 +41,9 @@ func TestDiscovery_DownloadURL(t *testing.T) { Windows: &ReleaseAsset{ URL: "windows-download-url", }, + MacOSARM64: &ReleaseAsset{ + URL: "macos-arm64-download-url", + }, }, } diff --git a/internal/product/product.go b/internal/product/product.go index dbd3cfe17..fe4cc2243 100644 --- a/internal/product/product.go +++ b/internal/product/product.go @@ -25,6 +25,7 @@ const ( ProductCode Product = "Snyk Code" ProductInfrastructureAsCode Product = "Snyk IaC" ProductContainer Product = "Snyk Container" + ProductUnknown Product = "" ) const (