Skip to content

Commit 2f356e6

Browse files
authored
feat: support toggling of recommendations (#795)
1 parent cdef412 commit 2f356e6

File tree

6 files changed

+45
-5
lines changed

6 files changed

+45
-5
lines changed

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,11 @@
365365
"default": "",
366366
"description": "Specifies platform used for multi-arch images.",
367367
"scope": "window"
368+
},
369+
"redHatDependencyAnalytics.recommendations.enabled": {
370+
"type": "boolean",
371+
"default": true,
372+
"description": "Toggles recommending Red Hat repositories"
368373
}
369374
}
370375
}

src/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class Config {
1313
telemetryId: string;
1414
stackAnalysisCommand: string;
1515
trackRecommendationAcceptanceCommand: string;
16+
recommendationsEnabled: boolean;
1617
utmSource: string;
1718
exhortProxyUrl: string;
1819
matchManifestVersions: string;
@@ -91,6 +92,7 @@ class Config {
9192

9293
this.stackAnalysisCommand = commands.STACK_ANALYSIS_COMMAND;
9394
this.trackRecommendationAcceptanceCommand = commands.TRACK_RECOMMENDATION_ACCEPTANCE_COMMAND;
95+
this.recommendationsEnabled = rhdaConfig.recommendations.enabled;
9496
this.utmSource = GlobalState.UTM_SOURCE;
9597
this.exhortProxyUrl = this.getEffectiveHttpProxyUrl();
9698
/* istanbul ignore next */

src/dependencyAnalysis/diagnostics.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ import { VERSION_PLACEHOLDER, GRADLE } from '../constants';
1212
import { clearCodeActionsMap, registerCodeAction, generateSwitchToRecommendedVersionAction } from '../codeActionHandler';
1313
import { buildErrorMessage } from '../utils';
1414
import { AbstractDiagnosticsPipeline } from '../diagnosticsPipeline';
15-
import { Diagnostic, Uri } from 'vscode';
15+
import { Diagnostic, DiagnosticSeverity, Uri } from 'vscode';
1616
import { notifications, outputChannelDep } from '../extension';
17+
import { globalConfig } from '../config';
1718

1819
/**
1920
* Implementation of DiagnosticsPipeline interface.
@@ -44,11 +45,16 @@ class DiagnosticsPipeline extends AbstractDiagnosticsPipeline<DependencyData> {
4445
const vulnerability = new Vulnerability(getRange(dependency), ref, dependencyData);
4546

4647
const vulnerabilityDiagnostic = vulnerability.getDiagnostic();
48+
if (vulnerabilityDiagnostic.severity === DiagnosticSeverity.Information && !globalConfig.recommendationsEnabled) {
49+
return;
50+
}
51+
4752
this.diagnostics.push(vulnerabilityDiagnostic);
4853

4954
const loc = vulnerabilityDiagnostic.range.start.line + '|' + vulnerabilityDiagnostic.range.start.character;
5055

5156
dependencyData.forEach(dd => {
57+
// TODO: we never use DiagnosticSeverity.Hint aka 3, so this always selects dd.remediationRef
5258
const actionRef = vulnerabilityDiagnostic.severity < 3 ? dd.remediationRef : dd.recommendationRef;
5359
if (actionRef) {
5460
this.createCodeAction(loc, actionRef, dependency.context, dd.sourceId, vulnerabilityDiagnostic);
@@ -91,7 +97,7 @@ class DiagnosticsPipeline extends AbstractDiagnosticsPipeline<DependencyData> {
9197
*/
9298
async function performDiagnostics(diagnosticFilePath: Uri, contents: string, provider: IDependencyProvider) {
9399
try {
94-
const dependencies = await provider.collect(contents);
100+
const dependencies = provider.collect(contents);
95101
const ecosystem = provider.getEcosystem();
96102
const dependencyMap = new DependencyMap(dependencies, ecosystem);
97103

src/imageAnalysis/diagnostics.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ import { AbstractDiagnosticsPipeline } from '../diagnosticsPipeline';
1010
import { clearCodeActionsMap, registerCodeAction, generateRedirectToRecommendedVersionAction } from '../codeActionHandler';
1111
import { executeImageAnalysis, ImageData } from './analysis';
1212
import { Vulnerability } from '../vulnerability';
13-
import { Diagnostic, Uri } from 'vscode';
13+
import { Diagnostic, DiagnosticSeverity, Uri } from 'vscode';
1414
import { notifications, outputChannelDep } from '../extension';
15+
import { globalConfig } from '../config';
1516

1617
/**
1718
* Implementation of DiagnosticsPipeline interface.
@@ -41,12 +42,16 @@ class DiagnosticsPipeline extends AbstractDiagnosticsPipeline<ImageData> {
4142
const vulnerability = new Vulnerability(getRange(image), image.name.value, imageData);
4243

4344
const vulnerabilityDiagnostic = vulnerability.getDiagnostic();
45+
if (vulnerabilityDiagnostic.severity === DiagnosticSeverity.Information && !globalConfig.recommendationsEnabled) {
46+
return;
47+
}
48+
4449
this.diagnostics.push(vulnerabilityDiagnostic);
4550

4651
const loc = vulnerabilityDiagnostic.range.start.line + '|' + vulnerabilityDiagnostic.range.start.character;
4752

4853
imageData.forEach(id => {
49-
if (id.recommendationRef) {
54+
if (id.recommendationRef && globalConfig.recommendationsEnabled) {
5055
this.createCodeAction(loc, id.recommendationRef, id.sourceId, vulnerabilityDiagnostic);
5156
}
5257

src/vulnerability.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ Recommendation: ${artifactData.recommendationRef || 'No Red Hat recommendations'
7474
const messages = this.artifactData.map(ad => {
7575
if (hasIssues && ad.issuesCount > 0) {
7676
return this.generateVulnerabilityInfo(ad);
77-
} else if (!hasIssues) {
77+
} else if (!hasIssues && globalConfig.recommendationsEnabled) {
7878
return this.generateRecommendation(ad);
7979
}
8080
return '';

test/vulnerability.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,4 +262,26 @@ suite('Vulnerability tests', () => {
262262
const diagnostic = vulnerability.getDiagnostic();
263263
expect(diagnostic.severity).to.eql(DiagnosticSeverity.Error);
264264
});
265+
266+
test('should return diagnostic without recommendations', async () => {
267+
config.globalConfig.recommendationsEnabled = false;
268+
269+
const mockDependencyData: MockDependencyData[] = [
270+
new MockDependencyData('osv(osv)', 2, mockRecommendationRef, 'mockRemediationRef', 'HIGH'),
271+
];
272+
const vulnerability = new Vulnerability(
273+
mockRange,
274+
mockMavenRef,
275+
mockDependencyData
276+
);
277+
278+
const diagnostic = vulnerability.getDiagnostic();
279+
expect(diagnostic.message.replace(/\s/g, '')).to.eql(`
280+
mockGroupId1/mockArtifact1@mockVersion
281+
282+
osv(osv) vulnerability info:
283+
Known security vulnerabilities: 2
284+
Highest severity: HIGH
285+
`.replace(/\s/g, ''));
286+
});
265287
});

0 commit comments

Comments
 (0)