Skip to content

Commit

Permalink
feat: fetch feature flag for Code Consistent Ignores [IDE-274] (#455)
Browse files Browse the repository at this point in the history
* feat: add Snyk Code feature flag to settings and configuration

- Added a new feature flag `snykCodeLsp` to enable the Snyk Code Panel Rendering via LSP.

* feat: scaffolding Code panel rendering based on FF

* fix: remove unnecessary view for migration

* feat: add `details` field to `CodeIssueData`

* feat: add new webview provider for feature flag-driven panel

* feat: handle feature flag in config file to react to changes in the orgs

* chore: revert providers initialisation order

* revert: addition feature preview in settings and configuration

* refactor: remove unnecessary `CodeDetailPanelProvider`

- The conditional rendering logic can be achieved in `CodeSuggestionWebviewProvider`

* fix: remove unnecessary var declaration

* refactor: move feature flag fetching to `ConfigurationWatcher`
  • Loading branch information
Cata authored May 13, 2024
1 parent 58bd8ae commit 1d2b3b7
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 2 deletions.
15 changes: 15 additions & 0 deletions src/snyk/common/configuration/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ 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';

Check warning on line 5 in src/snyk/common/configuration/configuration.ts

View workflow job for this annotation

GitHub Actions / build / Build and Test (ubuntu-latest)

'SNYK_FEATURE_FLAG_COMMAND' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 5 in src/snyk/common/configuration/configuration.ts

View workflow job for this annotation

GitHub Actions / build / Build and Test (macos-latest)

'SNYK_FEATURE_FLAG_COMMAND' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 5 in src/snyk/common/configuration/configuration.ts

View workflow job for this annotation

GitHub Actions / build / Build and Test (windows-latest)

'SNYK_FEATURE_FLAG_COMMAND' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 5 in src/snyk/common/configuration/configuration.ts

View workflow job for this annotation

GitHub Actions / build / Build and Test (macos-latest)

'SNYK_FEATURE_FLAG_COMMAND' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 5 in src/snyk/common/configuration/configuration.ts

View workflow job for this annotation

GitHub Actions / build / Build and Test (ubuntu-latest)

'SNYK_FEATURE_FLAG_COMMAND' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 5 in src/snyk/common/configuration/configuration.ts

View workflow job for this annotation

GitHub Actions / build / Build and Test (windows-latest)

'SNYK_FEATURE_FLAG_COMMAND' is defined but never used. Allowed unused vars must match /^_/u
import {
ADVANCED_ADDITIONAL_PARAMETERS_SETTING,
ADVANCED_ADVANCED_MODE_SETTING,
Expand Down Expand Up @@ -54,6 +55,10 @@ export interface IConfiguration {

authHost: string;

getFeatureFlag(flagName: string): boolean;

setFeatureFlag(flagName: string, value: boolean): void;

getToken(): Promise<string | undefined>;

setToken(token: string | undefined): Promise<void>;
Expand Down Expand Up @@ -115,6 +120,8 @@ export class Configuration implements IConfiguration {
private readonly defaultAuthHost = 'https://snyk.io';
private readonly defaultOssApiEndpoint = `${this.defaultAuthHost}/api/v1`;

private featureFlag: { [key: string]: boolean } = {};

constructor(private processEnv: NodeJS.ProcessEnv = process.env, private workspace: IVSCodeWorkspace) {}

getInsecure(): boolean {
Expand All @@ -134,6 +141,14 @@ export class Configuration implements IConfiguration {
return preview;
}

getFeatureFlag(flagName: string): boolean {
return this.featureFlag[flagName] ?? false;
}

setFeatureFlag(flagName: string, value: boolean): void {
this.featureFlag[flagName] = value;
}

private static async getPackageJsonConfig(): Promise<{ version: string; preview: boolean }> {
return (await import(path.join('../../../..', 'package.json'))) as { version: string; preview: boolean };
}
Expand Down
1 change: 1 addition & 0 deletions src/snyk/common/constants/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const SNYK_WORKSPACE_SCAN_COMMAND = 'snyk.workspace.scan';
export const SNYK_TRUST_WORKSPACE_FOLDERS_COMMAND = 'snyk.trustWorkspaceFolders';
export const SNYK_GET_ACTIVE_USER = 'snyk.getActiveUser';
export const SNYK_CODE_FIX_DIFFS_COMMAND = 'snyk.code.fixDiffs';
export const SNYK_FEATURE_FLAG_COMMAND = 'snyk.getFeatureFlagStatus';

// custom Snyk constants used in commands
export const SNYK_CONTEXT_PREFIX = 'snyk:';
3 changes: 3 additions & 0 deletions src/snyk/common/constants/featureFlags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const FEATURE_FLAGS = {
consistentIgnores: 'snykCodeConsistentIgnores',
};
1 change: 1 addition & 0 deletions src/snyk/common/languageServer/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export type CodeIssueData = {
isSecurityType: boolean;
priorityScore: number;
hasAIFix: boolean;
details: string; // HTML from the LSP
};

export type ExampleCommitFix = {
Expand Down
5 changes: 5 additions & 0 deletions src/snyk/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,8 @@ export function languageToString(language: Language): string {
return PJSON;
}
}

export type FeatureFlagStatus = {
ok: boolean;
userMessage?: string;
};
25 changes: 24 additions & 1 deletion src/snyk/common/watchers/configurationWatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,29 @@ import {
CODE_QUALITY_ENABLED_SETTING,
CODE_SECURITY_ENABLED_SETTING,
IAC_ENABLED_SETTING,
ADVANCED_ORGANIZATION,
OSS_ENABLED_SETTING,
SEVERITY_FILTER_SETTING,
TRUSTED_FOLDERS,
} from '../constants/settings';
import { FEATURE_FLAGS } from '../constants/featureFlags';
import { ErrorHandler } from '../error/errorHandler';
import { ILog } from '../logger/interfaces';
import { errorsLogs } from '../messages/errors';
import SecretStorageAdapter from '../vscode/secretStorage';
import { IWatcher } from './interfaces';
import { IVSCodeCommands } from '../vscode/commands';
import { SNYK_FEATURE_FLAG_COMMAND } from '../constants/commands';
import { FeatureFlagStatus } from '../types';

class ConfigurationWatcher implements IWatcher {
constructor(private readonly logger: ILog) {}
constructor(private readonly logger: ILog, private commandExecutor: IVSCodeCommands) {}

private async onChangeConfiguration(extension: IExtension, key: string): Promise<void> {
if (key === ADVANCED_ORGANIZATION) {
const isEnabled = await this.fetchFeatureFlag(FEATURE_FLAGS.consistentIgnores);
configuration.setFeatureFlag(FEATURE_FLAGS.consistentIgnores, isEnabled);
}
if (key === ADVANCED_ADVANCED_MODE_SETTING) {
return extension.checkAdvancedMode();
} else if (key === OSS_ENABLED_SETTING) {
Expand Down Expand Up @@ -63,6 +72,7 @@ class ConfigurationWatcher implements IWatcher {
const change = [
ADVANCED_ADVANCED_MODE_SETTING,
ADVANCED_AUTOSCAN_OSS_SETTING,
ADVANCED_ORGANIZATION,
OSS_ENABLED_SETTING,
CODE_SECURITY_ENABLED_SETTING,
CODE_QUALITY_ENABLED_SETTING,
Expand All @@ -88,6 +98,19 @@ class ConfigurationWatcher implements IWatcher {
}
});
}

private async fetchFeatureFlag(flagName: string): Promise<boolean> {
try {
const ffStatus = await this.commandExecutor.executeCommand<FeatureFlagStatus>(
SNYK_FEATURE_FLAG_COMMAND,
flagName,
);
return ffStatus?.ok ?? false;
} catch (error) {
console.warn(`Failed to fetch feature flag ${flagName}: ${error}`);
return false;
}
}
}

export default ConfigurationWatcher;
5 changes: 4 additions & 1 deletion src/snyk/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
SNYK_VIEW_SUPPORT,
SNYK_VIEW_WELCOME,
} from './common/constants/views';
import { FEATURE_FLAGS } from './common/constants/featureFlags';

Check warning on line 38 in src/snyk/extension.ts

View workflow job for this annotation

GitHub Actions / build / Build and Test (ubuntu-latest)

'FEATURE_FLAGS' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 38 in src/snyk/extension.ts

View workflow job for this annotation

GitHub Actions / build / Build and Test (macos-latest)

'FEATURE_FLAGS' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 38 in src/snyk/extension.ts

View workflow job for this annotation

GitHub Actions / build / Build and Test (windows-latest)

'FEATURE_FLAGS' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 38 in src/snyk/extension.ts

View workflow job for this annotation

GitHub Actions / build / Build and Test (macos-latest)

'FEATURE_FLAGS' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 38 in src/snyk/extension.ts

View workflow job for this annotation

GitHub Actions / build / Build and Test (ubuntu-latest)

'FEATURE_FLAGS' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 38 in src/snyk/extension.ts

View workflow job for this annotation

GitHub Actions / build / Build and Test (windows-latest)

'FEATURE_FLAGS' is defined but never used. Allowed unused vars must match /^_/u
import { ErrorHandler } from './common/error/errorHandler';
import { ErrorReporter } from './common/error/errorReporter';
import { ExperimentService } from './common/experiment/services/experimentService';
Expand Down Expand Up @@ -118,7 +119,7 @@ class SnykExtension extends SnykLib implements IExtension {

SecretStorageAdapter.init(vscodeContext);

this.configurationWatcher = new ConfigurationWatcher(Logger);
this.configurationWatcher = new ConfigurationWatcher(Logger, vsCodeCommands);
this.notificationService = new NotificationService(vsCodeWindow, vsCodeCommands, configuration, Logger);

this.statusBarItem.show();
Expand Down Expand Up @@ -366,6 +367,8 @@ class SnykExtension extends SnykLib implements IExtension {
// The codeEnabled context depends on an LS command
await this.languageServer.start();

// Fetch feature flag to determine whether to use the new LSP-based rendering.

// initialize contexts
await this.contextService.setContext(SNYK_CONTEXT.INITIALIZED, true);

Expand Down
1 change: 1 addition & 0 deletions src/test/unit/common/services/learnService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ suite('LearnService', () => {
isSecurityType: true,
priorityScore: 880,
hasAIFix: false,
details: 'not used',
},
title: 'not used',
severity: IssueSeverity.Critical,
Expand Down

0 comments on commit 1d2b3b7

Please sign in to comment.