From cd30e1bb34d0faf9b47083ffa61a0c1712ac9172 Mon Sep 17 00:00:00 2001 From: acke Date: Fri, 12 Jul 2024 15:28:11 +0200 Subject: [PATCH 01/11] feat: add ui elements to open and select base branch IDE-446 --- media/images/branch_icon.svg | 3 +++ media/pencil.svg | 3 +++ package.json | 6 ++++++ src/snyk/base/services/authenticationService.ts | 13 +++++++++++++ src/snyk/common/commands/commandController.ts | 5 +++++ src/snyk/common/constants/commands.ts | 1 + src/snyk/common/views/issueTreeProvider.ts | 17 +++++++++++++++++ src/snyk/common/views/treeNode.ts | 6 +++++- src/snyk/extension.ts | 2 ++ src/snyk/snykCode/views/issueTreeProvider.ts | 9 ++++++++- .../snykCode/views/securityIssueTreeProvider.ts | 2 ++ src/snyk/snykIac/views/iacIssueTreeProvider.ts | 9 ++++++++- .../providers/ossVulnerabilityTreeProvider.ts | 8 +++++++- 13 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 media/images/branch_icon.svg create mode 100644 media/pencil.svg diff --git a/media/images/branch_icon.svg b/media/images/branch_icon.svg new file mode 100644 index 000000000..0345758b3 --- /dev/null +++ b/media/images/branch_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/media/pencil.svg b/media/pencil.svg new file mode 100644 index 000000000..f682f5453 --- /dev/null +++ b/media/pencil.svg @@ -0,0 +1,3 @@ + + + diff --git a/package.json b/package.json index 3e5dfc5a4..2dfcd9689 100644 --- a/package.json +++ b/package.json @@ -341,6 +341,12 @@ "category": "Snyk", "icon": "$(run)" }, + { + "command": "snyk.setBaseBranch", + "title": "Set Base Branch", + "category": "Snyk", + "icon": "$(sign-in)" + }, { "command": "snyk.settings", "title": "Settings", diff --git a/src/snyk/base/services/authenticationService.ts b/src/snyk/base/services/authenticationService.ts index 77730cdf3..c492edcc4 100644 --- a/src/snyk/base/services/authenticationService.ts +++ b/src/snyk/base/services/authenticationService.ts @@ -17,6 +17,8 @@ export interface IAuthenticationService { setToken(): Promise; + setBaseBranch(): Promise; + updateToken(token: string): Promise; } @@ -64,6 +66,17 @@ export class AuthenticationService implements IAuthenticationService { return await this.clientAdapter.getLanguageClient().sendNotification(DID_CHANGE_CONFIGURATION_METHOD, {}); } + //TODO: move this function to another service + async setBaseBranch(): Promise { + const branch = await this.window.showInputBox({ + //TODO: replace 'main' with the list of local branches + placeHolder: 'main', + }); + + //TODO: capture the value of branch, and send this to Snyk Language Server. + return; + } + validateToken(token: string) { let valid = uuidValidate(token); if (valid) return true; diff --git a/src/snyk/common/commands/commandController.ts b/src/snyk/common/commands/commandController.ts index c96b1b6c3..3a65b75f4 100644 --- a/src/snyk/common/commands/commandController.ts +++ b/src/snyk/common/commands/commandController.ts @@ -8,6 +8,7 @@ import { IacIssueCommandArg } from '../../snykIac/views/interfaces'; import { OssService } from '../../snykOss/ossService'; import { SNYK_INITIATE_LOGIN_COMMAND, + SNYK_SET_BASE_BRANCH_COMMAND, SNYK_LOGIN_COMMAND, SNYK_OPEN_BROWSER_COMMAND, SNYK_SET_TOKEN_COMMAND, @@ -60,6 +61,10 @@ export class CommandController { await this.executeCommand(SNYK_SET_TOKEN_COMMAND, this.authService.setToken.bind(this.authService)); } + async setBaseBranch(): Promise { + await this.executeCommand(SNYK_SET_BASE_BRANCH_COMMAND, this.authService.setBaseBranch.bind(this.authService)); + } + async openLocal(path: Uri, range?: Range): Promise { try { await this.window.showTextDocumentViaUri(path, { viewColumn: 1, selection: range }); diff --git a/src/snyk/common/constants/commands.ts b/src/snyk/common/constants/commands.ts index 6a118f9d4..8eff414ee 100644 --- a/src/snyk/common/constants/commands.ts +++ b/src/snyk/common/constants/commands.ts @@ -5,6 +5,7 @@ export const VSCODE_ADD_COMMENT_COMMAND = 'editor.action.addCommentLine'; // custom Snyk commands export const SNYK_START_COMMAND = 'snyk.start'; +export const SNYK_SET_BASE_BRANCH_COMMAND = 'snyk.setBaseBranch'; export const SNYK_INITIATE_LOGIN_COMMAND = 'snyk.initiateLogin'; export const SNYK_SET_TOKEN_COMMAND = 'snyk.setToken'; export const SNYK_ENABLE_CODE_COMMAND = 'snyk.enableCode'; diff --git a/src/snyk/common/views/issueTreeProvider.ts b/src/snyk/common/views/issueTreeProvider.ts index ade44e095..8818f467d 100644 --- a/src/snyk/common/views/issueTreeProvider.ts +++ b/src/snyk/common/views/issueTreeProvider.ts @@ -49,6 +49,8 @@ export abstract class ProductIssueTreeProvider extends AnalysisTreeNodeProvid filteredIssues?: Issue[], ): Command; + abstract setBaseBranchCommand(): Command; + getRootChildren(): TreeNode[] { const nodes: TreeNode[] = []; @@ -89,6 +91,7 @@ export abstract class ProductIssueTreeProvider extends AnalysisTreeNodeProvid const ignoredIssueCount = this.getIgnoredCount(); const topNodes: (TreeNode | null)[] = [ + this.getBaseBranch(), new TreeNode({ text: this.getIssueFoundText(totalIssueCount, ignoredIssueCount), }), @@ -109,6 +112,20 @@ export abstract class ProductIssueTreeProvider extends AnalysisTreeNodeProvid return nodes; } + getBaseBranch(): TreeNode | null { + const deltaFindingsEnabled = this.configuration.getDeltaFindingsEnabled(); + + //TODO: get the actual base branch from Snyk Language Server + if (deltaFindingsEnabled) { + return new TreeNode({ + text: 'Base branch: main', + icon: NODE_ICONS.branch, + command: this.setBaseBranchCommand(), + }); + } + return null; + } + getFixableIssuesNode(_fixableIssueCount: number): TreeNode | null { return null; // optionally overridden by products } diff --git a/src/snyk/common/views/treeNode.ts b/src/snyk/common/views/treeNode.ts index 9ecdf8893..9a88c8e8f 100644 --- a/src/snyk/common/views/treeNode.ts +++ b/src/snyk/common/views/treeNode.ts @@ -7,7 +7,7 @@ export interface INodeIcon { ['dark']: string; } -type NODE_ICON_TYPE = 'critical' | 'high' | 'medium' | 'low' | 'error'; +type NODE_ICON_TYPE = 'critical' | 'high' | 'medium' | 'low' | 'error' | 'branch'; export const NODE_ICONS: { [key in NODE_ICON_TYPE]: INodeIcon } = { critical: { @@ -30,6 +30,10 @@ export const NODE_ICONS: { [key in NODE_ICON_TYPE]: INodeIcon } = { light: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'warning.svg'), dark: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'warning.svg'), }, + branch: { + light: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'branch_icon.svg'), + dark: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'branch_icon.svg'), + }, }; export type InternalType = { diff --git a/src/snyk/extension.ts b/src/snyk/extension.ts index d41d624ba..8c94266c1 100644 --- a/src/snyk/extension.ts +++ b/src/snyk/extension.ts @@ -19,6 +19,7 @@ import { SNYK_OPEN_ISSUE_COMMAND, SNYK_OPEN_LOCAL_COMMAND, SNYK_SET_TOKEN_COMMAND, + SNYK_SET_BASE_BRANCH_COMMAND, SNYK_SETTINGS_COMMAND, SNYK_SHOW_LS_OUTPUT_COMMAND, SNYK_SHOW_OUTPUT_COMMAND, @@ -409,6 +410,7 @@ class SnykExtension extends SnykLib implements IExtension { ), vscode.commands.registerCommand(SNYK_INITIATE_LOGIN_COMMAND, () => this.commandController.initiateLogin()), vscode.commands.registerCommand(SNYK_SET_TOKEN_COMMAND, () => this.commandController.setToken()), + vscode.commands.registerCommand(SNYK_SET_BASE_BRANCH_COMMAND, () => this.commandController.setBaseBranch()), vscode.commands.registerCommand(SNYK_ENABLE_CODE_COMMAND, () => this.commandController.executeCommand(SNYK_ENABLE_CODE_COMMAND, () => this.enableCode()), ), diff --git a/src/snyk/snykCode/views/issueTreeProvider.ts b/src/snyk/snykCode/views/issueTreeProvider.ts index d8b91ef84..40a151806 100644 --- a/src/snyk/snykCode/views/issueTreeProvider.ts +++ b/src/snyk/snykCode/views/issueTreeProvider.ts @@ -1,7 +1,7 @@ import { Command, Range } from 'vscode'; import { OpenCommandIssueType, OpenIssueCommandArg } from '../../common/commands/types'; import { IConfiguration } from '../../common/configuration/configuration'; -import { SNYK_OPEN_ISSUE_COMMAND } from '../../common/constants/commands'; +import { SNYK_OPEN_ISSUE_COMMAND, SNYK_SET_BASE_BRANCH_COMMAND } from '../../common/constants/commands'; import { CodeIssueData, Issue } from '../../common/languageServer/types'; import { IContextService } from '../../common/services/contextService'; import { IProductService } from '../../common/services/productService'; @@ -70,6 +70,13 @@ export class IssueTreeProvider extends ProductIssueTreeProvider { }; } + setBaseBranchCommand(): Command { + return { + command: SNYK_SET_BASE_BRANCH_COMMAND, + title: '', + }; + } + isFixableIssue(issue: Issue): boolean { return issue.additionalData.hasAIFix; } diff --git a/src/snyk/snykCode/views/securityIssueTreeProvider.ts b/src/snyk/snykCode/views/securityIssueTreeProvider.ts index f1d30ee1b..ad4028ee1 100644 --- a/src/snyk/snykCode/views/securityIssueTreeProvider.ts +++ b/src/snyk/snykCode/views/securityIssueTreeProvider.ts @@ -42,11 +42,13 @@ export default class CodeSecurityIssueTreeProvider extends IssueTreeProvider { protected getIssueFoundText(nIssues: number, ignoredIssueCount: number): string { if (nIssues > 0) { let text; + if (nIssues === 1) { text = `${nIssues} vulnerability found by Snyk`; } else { text = `✋ ${nIssues} vulnerabilities found by Snyk`; } + const isIgnoresEnabled = configuration.getFeatureFlag(FEATURE_FLAGS.consistentIgnores); if (isIgnoresEnabled) { text += `, ${ignoredIssueCount} ignored`; diff --git a/src/snyk/snykIac/views/iacIssueTreeProvider.ts b/src/snyk/snykIac/views/iacIssueTreeProvider.ts index 9af547e99..a05479f10 100644 --- a/src/snyk/snykIac/views/iacIssueTreeProvider.ts +++ b/src/snyk/snykIac/views/iacIssueTreeProvider.ts @@ -2,7 +2,7 @@ import { Command, Range } from 'vscode'; import { OpenCommandIssueType, OpenIssueCommandArg } from '../../common/commands/types'; import { IConfiguration } from '../../common/configuration/configuration'; import { configuration } from '../../common/configuration/instance'; -import { SNYK_OPEN_ISSUE_COMMAND } from '../../common/constants/commands'; +import { SNYK_OPEN_ISSUE_COMMAND, SNYK_SET_BASE_BRANCH_COMMAND } from '../../common/constants/commands'; import { SNYK_ANALYSIS_STATUS } from '../../common/constants/views'; import { IacIssueData, Issue } from '../../common/languageServer/types'; import { IContextService } from '../../common/services/contextService'; @@ -81,4 +81,11 @@ export default class IacIssueTreeProvider extends ProductIssueTreeProvider Date: Fri, 12 Jul 2024 16:09:46 +0200 Subject: [PATCH 02/11] fix: updated ui elements with a pencil to indicate that branch is editable --- media/{ => images}/pencil.svg | 0 src/snyk/common/views/issueTreeProvider.ts | 2 +- src/snyk/common/views/treeNode.ts | 6 +++++- src/snyk/snykCode/views/securityIssueTreeProvider.ts | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) rename media/{ => images}/pencil.svg (100%) diff --git a/media/pencil.svg b/media/images/pencil.svg similarity index 100% rename from media/pencil.svg rename to media/images/pencil.svg diff --git a/src/snyk/common/views/issueTreeProvider.ts b/src/snyk/common/views/issueTreeProvider.ts index 8818f467d..9dd11e9d5 100644 --- a/src/snyk/common/views/issueTreeProvider.ts +++ b/src/snyk/common/views/issueTreeProvider.ts @@ -119,7 +119,7 @@ export abstract class ProductIssueTreeProvider extends AnalysisTreeNodeProvid if (deltaFindingsEnabled) { return new TreeNode({ text: 'Base branch: main', - icon: NODE_ICONS.branch, + icon: NODE_ICONS.pencil, command: this.setBaseBranchCommand(), }); } diff --git a/src/snyk/common/views/treeNode.ts b/src/snyk/common/views/treeNode.ts index 9a88c8e8f..553ad0bf2 100644 --- a/src/snyk/common/views/treeNode.ts +++ b/src/snyk/common/views/treeNode.ts @@ -7,7 +7,7 @@ export interface INodeIcon { ['dark']: string; } -type NODE_ICON_TYPE = 'critical' | 'high' | 'medium' | 'low' | 'error' | 'branch'; +type NODE_ICON_TYPE = 'critical' | 'high' | 'medium' | 'low' | 'error' | 'branch' | 'pencil'; export const NODE_ICONS: { [key in NODE_ICON_TYPE]: INodeIcon } = { critical: { @@ -34,6 +34,10 @@ export const NODE_ICONS: { [key in NODE_ICON_TYPE]: INodeIcon } = { light: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'branch_icon.svg'), dark: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'branch_icon.svg'), }, + pencil: { + light: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'branch_icon.svg'), + dark: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'pencil.svg'), + }, }; export type InternalType = { diff --git a/src/snyk/snykCode/views/securityIssueTreeProvider.ts b/src/snyk/snykCode/views/securityIssueTreeProvider.ts index ad4028ee1..a806a4584 100644 --- a/src/snyk/snykCode/views/securityIssueTreeProvider.ts +++ b/src/snyk/snykCode/views/securityIssueTreeProvider.ts @@ -42,13 +42,13 @@ export default class CodeSecurityIssueTreeProvider extends IssueTreeProvider { protected getIssueFoundText(nIssues: number, ignoredIssueCount: number): string { if (nIssues > 0) { let text; - + if (nIssues === 1) { text = `${nIssues} vulnerability found by Snyk`; } else { text = `✋ ${nIssues} vulnerabilities found by Snyk`; } - + const isIgnoresEnabled = configuration.getFeatureFlag(FEATURE_FLAGS.consistentIgnores); if (isIgnoresEnabled) { text += `, ${ignoredIssueCount} ignored`; From 430756021d6f977f3c74f664da5aa9f2b7c4cafb Mon Sep 17 00:00:00 2001 From: Catalina Oyaneder Date: Mon, 15 Jul 2024 12:16:48 +0100 Subject: [PATCH 03/11] fix: display base branch only for Code in issue tree --- src/snyk/common/constants/views.ts | 1 + src/snyk/common/services/productService.ts | 8 +++++++- src/snyk/common/views/issueTreeProvider.ts | 11 ++++++++--- src/snyk/snykCode/codeService.ts | 2 ++ src/snyk/snykIac/iacService.ts | 2 ++ src/snyk/snykOss/ossService.ts | 2 ++ src/test/unit/common/services/productService.test.ts | 2 ++ 7 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/snyk/common/constants/views.ts b/src/snyk/common/constants/views.ts index d2e6819fb..7b3952c00 100644 --- a/src/snyk/common/constants/views.ts +++ b/src/snyk/common/constants/views.ts @@ -21,6 +21,7 @@ export const SNYK_CONTEXT = { ERROR: 'error', MODE: 'mode', ADVANCED: 'advanced', + DELTA_FINDINGS_ENABLED: 'deltaFindingsEnabled', }; export const SNYK_ERROR_CODES = { diff --git a/src/snyk/common/services/productService.ts b/src/snyk/common/services/productService.ts index efb4f06b1..ab1e03bb6 100644 --- a/src/snyk/common/services/productService.ts +++ b/src/snyk/common/services/productService.ts @@ -4,7 +4,7 @@ import { IConfiguration } from '../configuration/configuration'; import { IWorkspaceTrust } from '../configuration/trustedFolders'; import { CodeActionsProvider } from '../editor/codeActionsProvider'; import { ILanguageServer } from '../languageServer/languageServer'; -import { Issue, Scan, ScanStatus } from '../languageServer/types'; +import { Issue, Scan, ScanProduct, ScanStatus } from '../languageServer/types'; import { ILog } from '../logger/interfaces'; import { IViewManagerService } from '../services/viewManagerService'; import { IProductWebviewProvider } from '../views/webviewProvider'; @@ -29,6 +29,8 @@ export interface IProductService extends AnalysisStatusProvider, Disposable { } export abstract class ProductService extends AnalysisStatusProvider implements IProductService { + abstract readonly productType: ScanProduct; + private _result: ProductResult; readonly newResultAvailable$ = new Subject(); @@ -59,6 +61,10 @@ export abstract class ProductService extends AnalysisStatusProvider implement abstract refreshTreeView(): void; + public getSnykProductType(): ScanProduct { + return this.productType; + } + registerCodeActionsProvider(provider: CodeActionsProvider) { this.languages.registerCodeActionsProvider({ scheme: 'file', language: '*' }, provider); } diff --git a/src/snyk/common/views/issueTreeProvider.ts b/src/snyk/common/views/issueTreeProvider.ts index 9dd11e9d5..cd2c835ad 100644 --- a/src/snyk/common/views/issueTreeProvider.ts +++ b/src/snyk/common/views/issueTreeProvider.ts @@ -1,10 +1,10 @@ import _, { flatten } from 'lodash'; import * as vscode from 'vscode'; // todo: invert dependency import { IConfiguration, IssueViewOptions } from '../../common/configuration/configuration'; -import { Issue, IssueSeverity } from '../../common/languageServer/types'; +import { Issue, IssueSeverity, ScanProduct } from '../../common/languageServer/types'; import { messages as commonMessages } from '../../common/messages/analysisMessages'; import { IContextService } from '../../common/services/contextService'; -import { IProductService } from '../../common/services/productService'; +import { IProductService, ProductService } from '../../common/services/productService'; import { AnalysisTreeNodeProvider } from '../../common/views/analysisTreeNodeProvider'; import { INodeIcon, InternalType, NODE_ICONS, TreeNode } from '../../common/views/treeNode'; import { IVSCodeLanguages } from '../../common/vscode/languages'; @@ -91,12 +91,17 @@ export abstract class ProductIssueTreeProvider extends AnalysisTreeNodeProvid const ignoredIssueCount = this.getIgnoredCount(); const topNodes: (TreeNode | null)[] = [ - this.getBaseBranch(), new TreeNode({ text: this.getIssueFoundText(totalIssueCount, ignoredIssueCount), }), this.getFixableIssuesNode(this.getFixableCount()), ]; + + const isSnykCodeProduct = (this.productService as ProductService).getSnykProductType() === ScanProduct.Code; + if (isSnykCodeProduct) { + topNodes.unshift(this.getBaseBranch()); + } + const noSeverityFiltersSelectedWarning = this.getNoSeverityFiltersSelectedTreeNode(); if (noSeverityFiltersSelectedWarning !== null) { topNodes.push(noSeverityFiltersSelectedWarning); diff --git a/src/snyk/snykCode/codeService.ts b/src/snyk/snykCode/codeService.ts index 946a2fdb9..cd179f5a0 100644 --- a/src/snyk/snykCode/codeService.ts +++ b/src/snyk/snykCode/codeService.ts @@ -14,6 +14,8 @@ import { SnykCodeActionsProvider } from './codeActions/codeIssuesActionsProvider import { ICodeSuggestionWebviewProvider } from './views/interfaces'; export class SnykCodeService extends ProductService { + public readonly productType = ScanProduct.Code; + constructor( extensionContext: ExtensionContext, config: IConfiguration, diff --git a/src/snyk/snykIac/iacService.ts b/src/snyk/snykIac/iacService.ts index 137a07755..d82f4656f 100644 --- a/src/snyk/snykIac/iacService.ts +++ b/src/snyk/snykIac/iacService.ts @@ -14,6 +14,8 @@ import { IacCodeActionsProvider } from './codeActions/iacCodeActionsProvider'; import { IIacSuggestionWebviewProvider } from './views/interfaces'; export class IacService extends ProductService { + public readonly productType = ScanProduct.InfrastructureAsCode; + constructor( extensionContext: ExtensionContext, config: IConfiguration, diff --git a/src/snyk/snykOss/ossService.ts b/src/snyk/snykOss/ossService.ts index c88b20cc0..2d588a615 100644 --- a/src/snyk/snykOss/ossService.ts +++ b/src/snyk/snykOss/ossService.ts @@ -14,6 +14,8 @@ import { IOssSuggestionWebviewProvider } from './interfaces'; import { OssCodeActionsProvider } from './providers/ossCodeActionsProvider'; export class OssService extends ProductService { + public readonly productType = ScanProduct.OpenSource; + constructor( extensionContext: ExtensionContext, config: IConfiguration, diff --git a/src/test/unit/common/services/productService.test.ts b/src/test/unit/common/services/productService.test.ts index 5b073ae20..82f14f9b2 100644 --- a/src/test/unit/common/services/productService.test.ts +++ b/src/test/unit/common/services/productService.test.ts @@ -18,6 +18,8 @@ type ProductData = { productName: string; }; class MockProductService extends ProductService { + productType: ScanProduct; + subscribeToLsScanMessages(): Subscription { return this.languageServer.scan$.subscribe((scan: Scan) => { super.handleLsScanMessage(scan as Scan); From 262090893081a7f50527e6184d42f3d81ad6c9f9 Mon Sep 17 00:00:00 2001 From: Catalina Oyaneder Date: Mon, 15 Jul 2024 16:23:37 +0100 Subject: [PATCH 04/11] feat: render Delta Security Code based on feature flag --- package.json | 7 ++++++- src/snyk/common/configuration/configuration.ts | 2 ++ src/snyk/common/constants/views.ts | 1 + src/snyk/extension.ts | 14 ++++++++++++-- src/test/unit/common/configuration.test.ts | 2 ++ 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 2dfcd9689..95c0667f2 100644 --- a/package.json +++ b/package.json @@ -252,7 +252,12 @@ { "id": "snyk.views.analysis.code.security", "name": "Code Security", - "when": "snyk:initialized && snyk:loggedIn && snyk:codeEnabled && snyk:workspaceFound && !snyk:error" + "when": "snyk:initialized && snyk:loggedIn && snyk:codeEnabled && snyk:workspaceFound && !snyk:error && !snyk:deltaFindingsEnabled" + }, + { + "id": "snyk.views.analysis.code.security.delta", + "name": "Code Security - New Issues", + "when": "snyk:initialized && snyk:loggedIn && snyk:codeEnabled && snyk:workspaceFound && !snyk:error && snyk:deltaFindingsEnabled" }, { "id": "snyk.views.analysis.configuration", diff --git a/src/snyk/common/configuration/configuration.ts b/src/snyk/common/configuration/configuration.ts index c782c0013..170ce2cfb 100644 --- a/src/snyk/common/configuration/configuration.ts +++ b/src/snyk/common/configuration/configuration.ts @@ -54,6 +54,7 @@ export interface SeverityFilter { export type PreviewFeatures = { advisor: boolean | undefined; + deltaFindings: boolean | undefined; }; export interface IConfiguration { @@ -423,6 +424,7 @@ export class Configuration implements IConfiguration { getPreviewFeatures(): PreviewFeatures { const defaultSetting: PreviewFeatures = { advisor: false, + deltaFindings: false, }; const userSetting = diff --git a/src/snyk/common/constants/views.ts b/src/snyk/common/constants/views.ts index 7b3952c00..720f7eff6 100644 --- a/src/snyk/common/constants/views.ts +++ b/src/snyk/common/constants/views.ts @@ -1,6 +1,7 @@ export const SNYK_VIEW_WELCOME = 'snyk.views.welcome'; export const SNYK_VIEW_ANALYSIS_CODE_ENABLEMENT = 'snyk.views.analysis.code.enablement'; export const SNYK_VIEW_ANALYSIS_CODE_SECURITY = 'snyk.views.analysis.code.security'; +export const SNYK_VIEW_ANALYSIS_CODE_SECURITY_WITH_DELTA = 'snyk.views.analysis.code.security.delta'; export const SNYK_VIEW_ANALYSIS_CODE_QUALITY = 'snyk.views.analysis.code.quality'; export const SNYK_VIEW_ANALYSIS_OSS = 'snyk.views.analysis.oss'; export const SNYK_VIEW_SUPPORT = 'snyk.views.support'; diff --git a/src/snyk/extension.ts b/src/snyk/extension.ts index 8c94266c1..70de4884d 100644 --- a/src/snyk/extension.ts +++ b/src/snyk/extension.ts @@ -31,6 +31,7 @@ import { SNYK_VIEW_ANALYSIS_CODE_ENABLEMENT, SNYK_VIEW_ANALYSIS_CODE_QUALITY, SNYK_VIEW_ANALYSIS_CODE_SECURITY, + SNYK_VIEW_ANALYSIS_CODE_SECURITY_WITH_DELTA, SNYK_VIEW_ANALYSIS_IAC, SNYK_VIEW_ANALYSIS_OSS, SNYK_VIEW_SUPPORT, @@ -125,6 +126,11 @@ class SnykExtension extends SnykLib implements IExtension { this.statusBarItem.show(); + const previewFeatures = configuration.getPreviewFeatures(); + if (previewFeatures.deltaFindings) { + await this.contextService.setContext(SNYK_CONTEXT.DELTA_FINDINGS_ENABLED, true); + } + const languageClientAdapter = new LanguageClientAdapter(); this.authService = new AuthenticationService( this.contextService, @@ -261,7 +267,11 @@ class SnykExtension extends SnykLib implements IExtension { vsCodeLanguages, ); - const codeSecurityTree = vscode.window.createTreeView(SNYK_VIEW_ANALYSIS_CODE_SECURITY, { + const securityCodeView = previewFeatures.deltaFindings + ? SNYK_VIEW_ANALYSIS_CODE_SECURITY_WITH_DELTA + : SNYK_VIEW_ANALYSIS_CODE_SECURITY; + + const codeSecurityTree = vscode.window.createTreeView(securityCodeView, { treeDataProvider: codeSecurityIssueProvider, }); const codeQualityTree = vscode.window.createTreeView(SNYK_VIEW_ANALYSIS_CODE_QUALITY, { @@ -269,7 +279,7 @@ class SnykExtension extends SnykLib implements IExtension { }); vscodeContext.subscriptions.push( - vscode.window.registerTreeDataProvider(SNYK_VIEW_ANALYSIS_CODE_SECURITY, codeSecurityIssueProvider), + vscode.window.registerTreeDataProvider(securityCodeView, codeSecurityIssueProvider), vscode.window.registerTreeDataProvider(SNYK_VIEW_ANALYSIS_CODE_QUALITY, codeQualityIssueProvider), codeSecurityTree, codeQualityTree, diff --git a/src/test/unit/common/configuration.test.ts b/src/test/unit/common/configuration.test.ts index 94f8dbf78..d39bb5105 100644 --- a/src/test/unit/common/configuration.test.ts +++ b/src/test/unit/common/configuration.test.ts @@ -94,12 +94,14 @@ suite('Configuration', () => { deepStrictEqual(configuration.getPreviewFeatures(), { advisor: false, + deltaFindings: false, } as PreviewFeatures); }); test('Preview features: some features enabled', () => { const previewFeatures = { advisor: false, + deltaFindings: false, } as PreviewFeatures; const workspace = stubWorkspaceConfiguration(FEATURES_PREVIEW_SETTING, previewFeatures); From 0a7438b503dbdd3136f47fd82aa1ea4a1b125683 Mon Sep 17 00:00:00 2001 From: Catalina Oyaneder Date: Mon, 15 Jul 2024 16:48:34 +0100 Subject: [PATCH 05/11] feat: render Delta Code Quality based on feature flag --- package.json | 7 ++++++- src/snyk/common/constants/views.ts | 1 + src/snyk/extension.ts | 15 ++++++++++----- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 95c0667f2..749ccef8e 100644 --- a/package.json +++ b/package.json @@ -267,7 +267,12 @@ { "id": "snyk.views.analysis.code.quality", "name": "Code Quality", - "when": "snyk:initialized && snyk:loggedIn && snyk:codeEnabled && snyk:workspaceFound && !snyk:error" + "when": "snyk:initialized && snyk:loggedIn && snyk:codeEnabled && snyk:workspaceFound && !snyk:error && !snyk:deltaFindingsEnabled" + }, + { + "id": "snyk.views.analysis.code.quality.delta", + "name": "Code Quality - New Issues", + "when": "snyk:initialized && snyk:loggedIn && snyk:codeEnabled && snyk:workspaceFound && !snyk:error && snyk:deltaFindingsEnabled" }, { "id": "snyk.views.analysis.code.enablement", diff --git a/src/snyk/common/constants/views.ts b/src/snyk/common/constants/views.ts index 720f7eff6..6bc6dfb0d 100644 --- a/src/snyk/common/constants/views.ts +++ b/src/snyk/common/constants/views.ts @@ -3,6 +3,7 @@ export const SNYK_VIEW_ANALYSIS_CODE_ENABLEMENT = 'snyk.views.analysis.code.enab export const SNYK_VIEW_ANALYSIS_CODE_SECURITY = 'snyk.views.analysis.code.security'; export const SNYK_VIEW_ANALYSIS_CODE_SECURITY_WITH_DELTA = 'snyk.views.analysis.code.security.delta'; export const SNYK_VIEW_ANALYSIS_CODE_QUALITY = 'snyk.views.analysis.code.quality'; +export const SNYK_VIEW_ANALYSIS_CODE_QUALITY_WITH_DELTA = 'snyk.views.analysis.code.quality.delta'; export const SNYK_VIEW_ANALYSIS_OSS = 'snyk.views.analysis.oss'; export const SNYK_VIEW_SUPPORT = 'snyk.views.support'; export const SNYK_VIEW_SUGGESTION_CODE = 'snyk.views.suggestion.code'; diff --git a/src/snyk/extension.ts b/src/snyk/extension.ts index 70de4884d..0efafb383 100644 --- a/src/snyk/extension.ts +++ b/src/snyk/extension.ts @@ -30,6 +30,7 @@ import { SNYK_CONTEXT, SNYK_VIEW_ANALYSIS_CODE_ENABLEMENT, SNYK_VIEW_ANALYSIS_CODE_QUALITY, + SNYK_VIEW_ANALYSIS_CODE_QUALITY_WITH_DELTA, SNYK_VIEW_ANALYSIS_CODE_SECURITY, SNYK_VIEW_ANALYSIS_CODE_SECURITY_WITH_DELTA, SNYK_VIEW_ANALYSIS_IAC, @@ -267,20 +268,24 @@ class SnykExtension extends SnykLib implements IExtension { vsCodeLanguages, ); - const securityCodeView = previewFeatures.deltaFindings - ? SNYK_VIEW_ANALYSIS_CODE_SECURITY_WITH_DELTA - : SNYK_VIEW_ANALYSIS_CODE_SECURITY; + let securityCodeView = SNYK_VIEW_ANALYSIS_CODE_SECURITY; + let codeQualityView = SNYK_VIEW_ANALYSIS_CODE_QUALITY; + if (previewFeatures.deltaFindings) { + securityCodeView = SNYK_VIEW_ANALYSIS_CODE_SECURITY_WITH_DELTA; + codeQualityView = SNYK_VIEW_ANALYSIS_CODE_QUALITY_WITH_DELTA; + } const codeSecurityTree = vscode.window.createTreeView(securityCodeView, { treeDataProvider: codeSecurityIssueProvider, }); - const codeQualityTree = vscode.window.createTreeView(SNYK_VIEW_ANALYSIS_CODE_QUALITY, { + + const codeQualityTree = vscode.window.createTreeView(codeQualityView, { treeDataProvider: codeQualityIssueProvider, }); vscodeContext.subscriptions.push( vscode.window.registerTreeDataProvider(securityCodeView, codeSecurityIssueProvider), - vscode.window.registerTreeDataProvider(SNYK_VIEW_ANALYSIS_CODE_QUALITY, codeQualityIssueProvider), + vscode.window.registerTreeDataProvider(codeQualityView, codeQualityIssueProvider), codeSecurityTree, codeQualityTree, ); From 97fbfaa8dacd9af2f118e1b9b65156b8fc8c3b4d Mon Sep 17 00:00:00 2001 From: Catalina Oyaneder Date: Mon, 15 Jul 2024 17:18:21 +0100 Subject: [PATCH 06/11] fix: integration test --- src/test/integration/issueTreeProvider.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/integration/issueTreeProvider.test.ts b/src/test/integration/issueTreeProvider.test.ts index 53e31f38f..b0263aca6 100644 --- a/src/test/integration/issueTreeProvider.test.ts +++ b/src/test/integration/issueTreeProvider.test.ts @@ -2,7 +2,7 @@ import sinon from 'sinon'; import * as vscode from 'vscode'; import { IVSCodeLanguages } from '../../snyk/common/vscode/languages'; -import { CodeIssueData } from '../../snyk/common/languageServer/types'; +import { CodeIssueData, ScanProduct } from '../../snyk/common/languageServer/types'; import { IContextService } from '../../snyk/common/services/contextService'; import { IProductService } from '../../snyk/common/services/productService'; import { IssueTreeProvider } from '../../snyk/snykCode/views/issueTreeProvider'; @@ -30,6 +30,7 @@ suite('Code Issue Tree Provider', () => { result: { values: () => [[]], }, + getSnykProductType: () => ScanProduct.Code, } as unknown as IProductService; configuration.setFeatureFlag(FEATURE_FLAGS.consistentIgnores, true); languages = {} as unknown as IVSCodeLanguages; From bda657884e12b7c240273e6b095682f4a3a3cb64 Mon Sep 17 00:00:00 2001 From: Catalina Oyaneder Date: Tue, 16 Jul 2024 11:48:58 +0100 Subject: [PATCH 07/11] fix: add gear and scan icons to delta tree views --- package.json | 4 ++-- src/snyk/common/views/issueTreeProvider.ts | 2 +- src/snyk/common/views/treeNode.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 749ccef8e..b1c6df4bc 100644 --- a/package.json +++ b/package.json @@ -320,12 +320,12 @@ "view/title": [ { "command": "snyk.start", - "when": "view == 'snyk.views.analysis.code.security' || view == 'snyk.views.analysis.code.quality' || view == 'snyk.views.analysis.oss' || view == 'snyk.views.analysis.configuration'", + "when": "view == 'snyk.views.analysis.code.security' || view == 'snyk.views.analysis.code.security.delta' || view == 'snyk.views.analysis.code.quality' || view == 'snyk.views.analysis.code.quality.delta' || view == 'snyk.views.analysis.oss' || view == 'snyk.views.analysis.configuration'", "group": "navigation" }, { "command": "snyk.settings", - "when": "view == 'snyk.views.analysis.code.security' || view == 'snyk.views.analysis.code.quality' || view == 'snyk.views.analysis.oss' || view == 'snyk.views.welcome' || view == 'snyk.views.analysis.configuration'", + "when": "view == 'snyk.views.analysis.code.security' || view == 'snyk.views.analysis.code.security.delta' || view == 'snyk.views.analysis.code.quality' || view == 'snyk.views.analysis.code.quality.delta' || view == 'snyk.views.analysis.oss' || view == 'snyk.views.welcome' || view == 'snyk.views.analysis.configuration'", "group": "navigation" } ], diff --git a/src/snyk/common/views/issueTreeProvider.ts b/src/snyk/common/views/issueTreeProvider.ts index cd2c835ad..3b1433cce 100644 --- a/src/snyk/common/views/issueTreeProvider.ts +++ b/src/snyk/common/views/issueTreeProvider.ts @@ -124,7 +124,7 @@ export abstract class ProductIssueTreeProvider extends AnalysisTreeNodeProvid if (deltaFindingsEnabled) { return new TreeNode({ text: 'Base branch: main', - icon: NODE_ICONS.pencil, + icon: NODE_ICONS.branch, command: this.setBaseBranchCommand(), }); } diff --git a/src/snyk/common/views/treeNode.ts b/src/snyk/common/views/treeNode.ts index 553ad0bf2..96143203c 100644 --- a/src/snyk/common/views/treeNode.ts +++ b/src/snyk/common/views/treeNode.ts @@ -35,7 +35,7 @@ export const NODE_ICONS: { [key in NODE_ICON_TYPE]: INodeIcon } = { dark: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'branch_icon.svg'), }, pencil: { - light: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'branch_icon.svg'), + light: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'pencil.svg'), dark: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'pencil.svg'), }, }; From b6dc508c6180bdc08ed2bb9f20e316652c43e44e Mon Sep 17 00:00:00 2001 From: Catalina Oyaneder Date: Tue, 16 Jul 2024 16:41:54 +0100 Subject: [PATCH 08/11] refactor: remove base branch placeholder command --- package.json | 6 ------ src/snyk/base/services/authenticationService.ts | 13 ------------- src/snyk/common/commands/commandController.ts | 5 ----- src/snyk/common/constants/commands.ts | 1 - src/snyk/common/views/issueTreeProvider.ts | 3 --- src/snyk/extension.ts | 2 -- src/snyk/snykCode/views/issueTreeProvider.ts | 9 +-------- src/snyk/snykIac/views/iacIssueTreeProvider.ts | 9 +-------- .../providers/ossVulnerabilityTreeProvider.ts | 8 +------- 9 files changed, 3 insertions(+), 53 deletions(-) diff --git a/package.json b/package.json index b1c6df4bc..0f090c1b9 100644 --- a/package.json +++ b/package.json @@ -351,12 +351,6 @@ "category": "Snyk", "icon": "$(run)" }, - { - "command": "snyk.setBaseBranch", - "title": "Set Base Branch", - "category": "Snyk", - "icon": "$(sign-in)" - }, { "command": "snyk.settings", "title": "Settings", diff --git a/src/snyk/base/services/authenticationService.ts b/src/snyk/base/services/authenticationService.ts index c492edcc4..77730cdf3 100644 --- a/src/snyk/base/services/authenticationService.ts +++ b/src/snyk/base/services/authenticationService.ts @@ -17,8 +17,6 @@ export interface IAuthenticationService { setToken(): Promise; - setBaseBranch(): Promise; - updateToken(token: string): Promise; } @@ -66,17 +64,6 @@ export class AuthenticationService implements IAuthenticationService { return await this.clientAdapter.getLanguageClient().sendNotification(DID_CHANGE_CONFIGURATION_METHOD, {}); } - //TODO: move this function to another service - async setBaseBranch(): Promise { - const branch = await this.window.showInputBox({ - //TODO: replace 'main' with the list of local branches - placeHolder: 'main', - }); - - //TODO: capture the value of branch, and send this to Snyk Language Server. - return; - } - validateToken(token: string) { let valid = uuidValidate(token); if (valid) return true; diff --git a/src/snyk/common/commands/commandController.ts b/src/snyk/common/commands/commandController.ts index 3a65b75f4..c96b1b6c3 100644 --- a/src/snyk/common/commands/commandController.ts +++ b/src/snyk/common/commands/commandController.ts @@ -8,7 +8,6 @@ import { IacIssueCommandArg } from '../../snykIac/views/interfaces'; import { OssService } from '../../snykOss/ossService'; import { SNYK_INITIATE_LOGIN_COMMAND, - SNYK_SET_BASE_BRANCH_COMMAND, SNYK_LOGIN_COMMAND, SNYK_OPEN_BROWSER_COMMAND, SNYK_SET_TOKEN_COMMAND, @@ -61,10 +60,6 @@ export class CommandController { await this.executeCommand(SNYK_SET_TOKEN_COMMAND, this.authService.setToken.bind(this.authService)); } - async setBaseBranch(): Promise { - await this.executeCommand(SNYK_SET_BASE_BRANCH_COMMAND, this.authService.setBaseBranch.bind(this.authService)); - } - async openLocal(path: Uri, range?: Range): Promise { try { await this.window.showTextDocumentViaUri(path, { viewColumn: 1, selection: range }); diff --git a/src/snyk/common/constants/commands.ts b/src/snyk/common/constants/commands.ts index 8eff414ee..6a118f9d4 100644 --- a/src/snyk/common/constants/commands.ts +++ b/src/snyk/common/constants/commands.ts @@ -5,7 +5,6 @@ export const VSCODE_ADD_COMMENT_COMMAND = 'editor.action.addCommentLine'; // custom Snyk commands export const SNYK_START_COMMAND = 'snyk.start'; -export const SNYK_SET_BASE_BRANCH_COMMAND = 'snyk.setBaseBranch'; export const SNYK_INITIATE_LOGIN_COMMAND = 'snyk.initiateLogin'; export const SNYK_SET_TOKEN_COMMAND = 'snyk.setToken'; export const SNYK_ENABLE_CODE_COMMAND = 'snyk.enableCode'; diff --git a/src/snyk/common/views/issueTreeProvider.ts b/src/snyk/common/views/issueTreeProvider.ts index 3b1433cce..159dc5c05 100644 --- a/src/snyk/common/views/issueTreeProvider.ts +++ b/src/snyk/common/views/issueTreeProvider.ts @@ -49,8 +49,6 @@ export abstract class ProductIssueTreeProvider extends AnalysisTreeNodeProvid filteredIssues?: Issue[], ): Command; - abstract setBaseBranchCommand(): Command; - getRootChildren(): TreeNode[] { const nodes: TreeNode[] = []; @@ -125,7 +123,6 @@ export abstract class ProductIssueTreeProvider extends AnalysisTreeNodeProvid return new TreeNode({ text: 'Base branch: main', icon: NODE_ICONS.branch, - command: this.setBaseBranchCommand(), }); } return null; diff --git a/src/snyk/extension.ts b/src/snyk/extension.ts index 0efafb383..57b717032 100644 --- a/src/snyk/extension.ts +++ b/src/snyk/extension.ts @@ -19,7 +19,6 @@ import { SNYK_OPEN_ISSUE_COMMAND, SNYK_OPEN_LOCAL_COMMAND, SNYK_SET_TOKEN_COMMAND, - SNYK_SET_BASE_BRANCH_COMMAND, SNYK_SETTINGS_COMMAND, SNYK_SHOW_LS_OUTPUT_COMMAND, SNYK_SHOW_OUTPUT_COMMAND, @@ -425,7 +424,6 @@ class SnykExtension extends SnykLib implements IExtension { ), vscode.commands.registerCommand(SNYK_INITIATE_LOGIN_COMMAND, () => this.commandController.initiateLogin()), vscode.commands.registerCommand(SNYK_SET_TOKEN_COMMAND, () => this.commandController.setToken()), - vscode.commands.registerCommand(SNYK_SET_BASE_BRANCH_COMMAND, () => this.commandController.setBaseBranch()), vscode.commands.registerCommand(SNYK_ENABLE_CODE_COMMAND, () => this.commandController.executeCommand(SNYK_ENABLE_CODE_COMMAND, () => this.enableCode()), ), diff --git a/src/snyk/snykCode/views/issueTreeProvider.ts b/src/snyk/snykCode/views/issueTreeProvider.ts index 40a151806..d8b91ef84 100644 --- a/src/snyk/snykCode/views/issueTreeProvider.ts +++ b/src/snyk/snykCode/views/issueTreeProvider.ts @@ -1,7 +1,7 @@ import { Command, Range } from 'vscode'; import { OpenCommandIssueType, OpenIssueCommandArg } from '../../common/commands/types'; import { IConfiguration } from '../../common/configuration/configuration'; -import { SNYK_OPEN_ISSUE_COMMAND, SNYK_SET_BASE_BRANCH_COMMAND } from '../../common/constants/commands'; +import { SNYK_OPEN_ISSUE_COMMAND } from '../../common/constants/commands'; import { CodeIssueData, Issue } from '../../common/languageServer/types'; import { IContextService } from '../../common/services/contextService'; import { IProductService } from '../../common/services/productService'; @@ -70,13 +70,6 @@ export class IssueTreeProvider extends ProductIssueTreeProvider { }; } - setBaseBranchCommand(): Command { - return { - command: SNYK_SET_BASE_BRANCH_COMMAND, - title: '', - }; - } - isFixableIssue(issue: Issue): boolean { return issue.additionalData.hasAIFix; } diff --git a/src/snyk/snykIac/views/iacIssueTreeProvider.ts b/src/snyk/snykIac/views/iacIssueTreeProvider.ts index a05479f10..9af547e99 100644 --- a/src/snyk/snykIac/views/iacIssueTreeProvider.ts +++ b/src/snyk/snykIac/views/iacIssueTreeProvider.ts @@ -2,7 +2,7 @@ import { Command, Range } from 'vscode'; import { OpenCommandIssueType, OpenIssueCommandArg } from '../../common/commands/types'; import { IConfiguration } from '../../common/configuration/configuration'; import { configuration } from '../../common/configuration/instance'; -import { SNYK_OPEN_ISSUE_COMMAND, SNYK_SET_BASE_BRANCH_COMMAND } from '../../common/constants/commands'; +import { SNYK_OPEN_ISSUE_COMMAND } from '../../common/constants/commands'; import { SNYK_ANALYSIS_STATUS } from '../../common/constants/views'; import { IacIssueData, Issue } from '../../common/languageServer/types'; import { IContextService } from '../../common/services/contextService'; @@ -81,11 +81,4 @@ export default class IacIssueTreeProvider extends ProductIssueTreeProvider Date: Tue, 16 Jul 2024 17:35:30 +0100 Subject: [PATCH 09/11] fix: add dark and light icons for delta --- media/images/branch-dark.svg | 3 +++ media/images/{branch_icon.svg => branch-light.svg} | 2 +- media/images/{pencil.svg => pencil-dark.svg} | 0 media/images/pencil-light.svg | 3 +++ src/snyk/common/views/treeNode.ts | 8 ++++---- 5 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 media/images/branch-dark.svg rename media/images/{branch_icon.svg => branch-light.svg} (98%) rename media/images/{pencil.svg => pencil-dark.svg} (100%) create mode 100644 media/images/pencil-light.svg diff --git a/media/images/branch-dark.svg b/media/images/branch-dark.svg new file mode 100644 index 000000000..870771a1e --- /dev/null +++ b/media/images/branch-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/media/images/branch_icon.svg b/media/images/branch-light.svg similarity index 98% rename from media/images/branch_icon.svg rename to media/images/branch-light.svg index 0345758b3..9ef778737 100644 --- a/media/images/branch_icon.svg +++ b/media/images/branch-light.svg @@ -1,3 +1,3 @@ - + diff --git a/media/images/pencil.svg b/media/images/pencil-dark.svg similarity index 100% rename from media/images/pencil.svg rename to media/images/pencil-dark.svg diff --git a/media/images/pencil-light.svg b/media/images/pencil-light.svg new file mode 100644 index 000000000..7af23297f --- /dev/null +++ b/media/images/pencil-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/snyk/common/views/treeNode.ts b/src/snyk/common/views/treeNode.ts index 96143203c..53241b7dc 100644 --- a/src/snyk/common/views/treeNode.ts +++ b/src/snyk/common/views/treeNode.ts @@ -31,12 +31,12 @@ export const NODE_ICONS: { [key in NODE_ICON_TYPE]: INodeIcon } = { dark: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'warning.svg'), }, branch: { - light: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'branch_icon.svg'), - dark: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'branch_icon.svg'), + light: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'branch-light.svg'), + dark: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'branch-dark.svg'), }, pencil: { - light: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'pencil.svg'), - dark: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'pencil.svg'), + light: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'pencil-light.svg'), + dark: path.join(__filename, '..', '..', '..', '..', '..', 'media', 'images', 'pencil-dark.svg'), }, }; From ac09779d62c9a8e42f87f05afa3d28b1a8398106 Mon Sep 17 00:00:00 2001 From: Catalina Oyaneder Date: Tue, 16 Jul 2024 17:45:53 +0100 Subject: [PATCH 10/11] refactor: consistent message across products when no issues are found --- src/snyk/common/views/issueTreeProvider.ts | 5 ++++- src/snyk/snykCode/views/securityIssueTreeProvider.ts | 4 ++-- src/snyk/snykIac/views/iacIssueTreeProvider.ts | 5 ++++- src/snyk/snykOss/constants/messages.ts | 2 +- src/snyk/snykOss/providers/ossVulnerabilityTreeProvider.ts | 7 ++++--- src/test/integration/issueTreeProvider.test.ts | 2 +- 6 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/snyk/common/views/issueTreeProvider.ts b/src/snyk/common/views/issueTreeProvider.ts index 159dc5c05..9d89ed09b 100644 --- a/src/snyk/common/views/issueTreeProvider.ts +++ b/src/snyk/common/views/issueTreeProvider.ts @@ -294,7 +294,10 @@ export abstract class ProductIssueTreeProvider extends AnalysisTreeNodeProvid } protected getIssueFoundText(nIssues: number, _: number): string { - return `Snyk found ${!nIssues ? 'no issues! ✅' : `${nIssues} issue${nIssues === 1 ? '' : 's'}`}`; + if (!nIssues) { + return '✅ Congrats! No issues found!'; + } + return `Snyk found ${nIssues} issue${nIssues === 1 ? '' : 's'}`; } protected getIssueDescriptionText(dir: string | undefined, issueCount: number): string | undefined { diff --git a/src/snyk/snykCode/views/securityIssueTreeProvider.ts b/src/snyk/snykCode/views/securityIssueTreeProvider.ts index a806a4584..590e33844 100644 --- a/src/snyk/snykCode/views/securityIssueTreeProvider.ts +++ b/src/snyk/snykCode/views/securityIssueTreeProvider.ts @@ -44,7 +44,7 @@ export default class CodeSecurityIssueTreeProvider extends IssueTreeProvider { let text; if (nIssues === 1) { - text = `${nIssues} vulnerability found by Snyk`; + text = `${nIssues} issue found by Snyk`; } else { text = `✋ ${nIssues} vulnerabilities found by Snyk`; } @@ -55,7 +55,7 @@ export default class CodeSecurityIssueTreeProvider extends IssueTreeProvider { } return text; } else { - return '✅ Congrats! No vulnerabilities found!'; + return '✅ Congrats! No issues found!'; } } } diff --git a/src/snyk/snykIac/views/iacIssueTreeProvider.ts b/src/snyk/snykIac/views/iacIssueTreeProvider.ts index 9af547e99..2a676ee33 100644 --- a/src/snyk/snykIac/views/iacIssueTreeProvider.ts +++ b/src/snyk/snykIac/views/iacIssueTreeProvider.ts @@ -49,7 +49,10 @@ export default class IacIssueTreeProvider extends ProductIssueTreeProvider[]): Issue[] { diff --git a/src/snyk/snykOss/constants/messages.ts b/src/snyk/snykOss/constants/messages.ts index ef01e4ddf..a0af4b11c 100644 --- a/src/snyk/snykOss/constants/messages.ts +++ b/src/snyk/snykOss/constants/messages.ts @@ -23,7 +23,7 @@ export const messages = { treeView: { cookingDependencies: 'Scanning...', runTest: 'Run scan for Open Source security vulnerabilities.', - noVulnerabilitiesFound: ' ✅ Congrats! Snyk found no vulnerabilities.', + noVulnerabilitiesFound: ' ✅ Congrats! No issues found!', singleVulnerabilityFound: 'Snyk found 1 vulnerability', vulnerability: 'vulnerability', vulnerabilities: 'vulnerabilities', diff --git a/src/snyk/snykOss/providers/ossVulnerabilityTreeProvider.ts b/src/snyk/snykOss/providers/ossVulnerabilityTreeProvider.ts index 5fdd38183..ccd1c06df 100644 --- a/src/snyk/snykOss/providers/ossVulnerabilityTreeProvider.ts +++ b/src/snyk/snykOss/providers/ossVulnerabilityTreeProvider.ts @@ -154,9 +154,10 @@ export default class OssIssueTreeProvider extends ProductIssueTreeProvider[]): Issue[] { diff --git a/src/test/integration/issueTreeProvider.test.ts b/src/test/integration/issueTreeProvider.test.ts index b0263aca6..c982d262b 100644 --- a/src/test/integration/issueTreeProvider.test.ts +++ b/src/test/integration/issueTreeProvider.test.ts @@ -82,7 +82,7 @@ suite('Code Issue Tree Provider', () => { sinon.stub(issueTreeProvider, 'getResultNodes').returns([]); const rootChildren = issueTreeProvider.getRootChildren(); strictEqual(rootChildren.length, 2); - strictEqual(rootChildren[0].label, 'Snyk found no issues! ✅'); + strictEqual(rootChildren[0].label, '✅ Congrats! No issues found!'); strictEqual(rootChildren[1].label, 'There are no vulnerabilities fixable by Snyk DeepCode AI'); }); From 8c9805cc2a95ac999593bad6730f163e2efa6a1d Mon Sep 17 00:00:00 2001 From: Catalina Oyaneder Date: Wed, 17 Jul 2024 13:26:33 +0100 Subject: [PATCH 11/11] chore: add CHANGELOG --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6997e282..a735ced7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Snyk Security Changelog +## [2.14.0] +- Add UI components for selecting a base branch for delta findings for Code and Code Quality behind a feature flag. + ### [2.13.1] - Refactor the Suggestion Panel for OSS so it's more secure and will be supported in other IDEs