diff --git a/CHANGELOG.md b/CHANGELOG.md index ca79931c3..34f5f9154 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,11 @@ # Snyk Security Changelog -## [2.7,1] +## [2.7.1] - Add the Issue View Options panel to the Snyk Security Settings. +## [2.7.0] +- Fetch Snyk Consistent Ignores feature flag from the Language Server +- Conditionally render Code details panel from Language Server + ## [2.6.1] - Improve the validation of the custom endpoint and change the default to https://api.snyk.io. diff --git a/src/snyk/common/configuration/configuration.ts b/src/snyk/common/configuration/configuration.ts index c54c0e6f4..158b75982 100644 --- a/src/snyk/common/configuration/configuration.ts +++ b/src/snyk/common/configuration/configuration.ts @@ -2,7 +2,6 @@ import _ from 'lodash'; import path from 'path'; import { URL } from 'url'; import { IDE_NAME_SHORT, SNYK_TOKEN_KEY } from '../constants/general'; -import { SNYK_FEATURE_FLAG_COMMAND } from '../constants/commands'; import { ADVANCED_ADDITIONAL_PARAMETERS_SETTING, ADVANCED_ADVANCED_MODE_SETTING, diff --git a/src/snyk/extension.ts b/src/snyk/extension.ts index 60f25db5d..773041406 100644 --- a/src/snyk/extension.ts +++ b/src/snyk/extension.ts @@ -35,7 +35,6 @@ import { SNYK_VIEW_SUPPORT, SNYK_VIEW_WELCOME, } from './common/constants/views'; -import { FEATURE_FLAGS } from './common/constants/featureFlags'; import { ErrorHandler } from './common/error/errorHandler'; import { ErrorReporter } from './common/error/errorReporter'; import { ExperimentService } from './common/experiment/services/experimentService'; diff --git a/src/snyk/snykCode/codeSettings.ts b/src/snyk/snykCode/codeSettings.ts index d05b173f5..74b9704cf 100644 --- a/src/snyk/snykCode/codeSettings.ts +++ b/src/snyk/snykCode/codeSettings.ts @@ -1,8 +1,10 @@ import { IConfiguration } from '../common/configuration/configuration'; -import { SNYK_GET_SETTINGS_SAST_ENABLED } from '../common/constants/commands'; +import { SNYK_FEATURE_FLAG_COMMAND, SNYK_GET_SETTINGS_SAST_ENABLED } from '../common/constants/commands'; +import { FEATURE_FLAGS } from '../common/constants/featureFlags'; import { SNYK_CONTEXT } from '../common/constants/views'; import { IContextService } from '../common/services/contextService'; import { IOpenerService } from '../common/services/openerService'; +import { FeatureFlagStatus } from '../common/types'; import { IVSCodeCommands } from '../common/vscode/commands'; export interface ICodeSettings { @@ -43,6 +45,11 @@ export class CodeSettings implements ICodeSettings { } await this.contextService.setContext(SNYK_CONTEXT.CODE_ENABLED, codeEnabled); await this.contextService.setContext(SNYK_CONTEXT.CODE_LOCAL_ENGINE_ENABLED, localCodeEngineEnabled); + + // TODO: There is a follow-up task to refactor this to use the new feature flag service + const isConsistentIgnoresEnabled = await this.fetchFeatureFlag(FEATURE_FLAGS.consistentIgnores); + this.config.setFeatureFlag(FEATURE_FLAGS.consistentIgnores, isConsistentIgnoresEnabled); + return codeEnabled; } @@ -91,4 +98,19 @@ export class CodeSettings implements ICodeSettings { } private sleep = (duration: number) => new Promise(resolve => setTimeout(resolve, duration)); + + // TODO: There is a follow-up task to refactor this to use the new feature flag service + private async fetchFeatureFlag(flagName: string): Promise { + try { + const ffStatus = await this.commandExecutor.executeCommand( + SNYK_FEATURE_FLAG_COMMAND, + flagName, + ); + console.log('codeSettings.fetchFeatureFlag: ffStatus:', ffStatus); + return ffStatus?.ok ?? false; + } catch (error) { + console.warn(`Failed to fetch feature flag ${flagName}: ${error}`); + return false; + } + } } diff --git a/src/snyk/snykCode/views/suggestion/codeSuggestionWebviewProvider.ts b/src/snyk/snykCode/views/suggestion/codeSuggestionWebviewProvider.ts index ea972e0fb..a2be8eb65 100644 --- a/src/snyk/snykCode/views/suggestion/codeSuggestionWebviewProvider.ts +++ b/src/snyk/snykCode/views/suggestion/codeSuggestionWebviewProvider.ts @@ -32,6 +32,8 @@ import { readFileSync } from 'fs'; import { TextDocument } from '../../../common/vscode/types'; import { Suggestion, SuggestionMessage } from './types'; import { WebviewPanelSerializer } from '../../../snykCode/views/webviewPanelSerializer'; +import { configuration } from '../../../common/configuration/instance'; +import { FEATURE_FLAGS } from '../../../common/constants/featureFlags'; export class CodeSuggestionWebviewProvider extends WebviewProvider> @@ -88,9 +90,10 @@ export class CodeSuggestionWebviewProvider } async showPanel(issue: Issue): Promise { + const isIgnoresEnabled = configuration.getFeatureFlag(FEATURE_FLAGS.consistentIgnores); + try { await this.focusSecondEditorGroup(); - if (this.panel) { this.panel.title = this.getTitle(issue); this.panel.reveal(vscode.ViewColumn.Two, true); @@ -107,15 +110,19 @@ export class CodeSuggestionWebviewProvider this.registerListeners(); } - issue.additionalData.exampleCommitFixes = encodeExampleCommitFixes(issue.additionalData.exampleCommitFixes); - - this.panel.webview.html = this.getHtmlForWebview(this.panel.webview); - this.panel.iconPath = vscode.Uri.joinPath( - vscode.Uri.file(this.context.extensionPath), - 'media', - 'images', - 'snyk-code.svg', - ); + if (isIgnoresEnabled) { + this.panel.webview.html = issue.additionalData.details; + } else { + issue.additionalData.exampleCommitFixes = encodeExampleCommitFixes(issue.additionalData.exampleCommitFixes); + + this.panel.webview.html = this.getHtmlForWebview(this.panel.webview); + this.panel.iconPath = vscode.Uri.joinPath( + vscode.Uri.file(this.context.extensionPath), + 'media', + 'images', + 'snyk-code.svg', + ); + } void this.postSuggestMessage({ type: 'set', args: this.mapToModel(issue) }); void this.postLearnLessonMessage(issue); diff --git a/src/test/unit/snykCode/codeSettings.test.ts b/src/test/unit/snykCode/codeSettings.test.ts index 604e1e5b3..5d5e45b35 100644 --- a/src/test/unit/snykCode/codeSettings.test.ts +++ b/src/test/unit/snykCode/codeSettings.test.ts @@ -10,10 +10,13 @@ import { CodeSettings, ICodeSettings } from '../../../snyk/snykCode/codeSettings suite('Snyk Code Settings', () => { let settings: ICodeSettings; let setContextFake: SinonSpy; + let setFeatureFlagFake: SinonSpy; let contextService: IContextService; + let config: IConfiguration; setup(() => { setContextFake = sinon.fake(); + setFeatureFlagFake = sinon.fake(); contextService = { setContext: setContextFake, @@ -23,7 +26,11 @@ suite('Snyk Code Settings', () => { viewContext: {}, }; - settings = new CodeSettings(contextService, {} as IConfiguration, {} as IOpenerService, {} as IVSCodeCommands); + config = { + setFeatureFlag: setFeatureFlagFake, + } as unknown as IConfiguration; + + settings = new CodeSettings(contextService, config, {} as IOpenerService, {} as IVSCodeCommands); }); teardown(() => {