Skip to content

Commit 1ed7d11

Browse files
author
Almog Ben-David
committed
refactor: replace cc parser with split functions
1 parent 707801d commit 1ed7d11

File tree

4 files changed

+74
-33
lines changed

4 files changed

+74
-33
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
"dependencies": {
7676
"@open-policy-agent/opa-wasm": "^1.2.0",
7777
"@snyk/cli-interface": "2.11.0",
78-
"@snyk/cloud-config-parser": "^1.9.2",
78+
"@snyk/cloud-config-parser": "^1.10.2",
7979
"@snyk/code-client": "4.0.0",
8080
"@snyk/dep-graph": "^1.27.1",
8181
"@snyk/fix": "1.650.0",
@@ -147,7 +147,7 @@
147147
"devDependencies": {
148148
"@types/cross-spawn": "^6.0.2",
149149
"@types/fs-extra": "^9.0.11",
150-
"@types/jest": "^26.0.20",
150+
"@types/jest": "^27.0.1",
151151
"@types/lodash": "^4.14.161",
152152
"@types/needle": "^2.0.4",
153153
"@types/node": "^14.14.31",

src/cli/commands/test/iac-local-execution/extract-line-number.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ import { IaCErrorCodes } from './types';
22
import { CustomError } from '../../../../lib/errors';
33
import {
44
CloudConfigFileTypes,
5-
issuesToLineNumbers,
5+
MapsDocIdToTree,
6+
getLineNumber,
67
} from '@snyk/cloud-config-parser';
78
import { UnsupportedFileTypeError } from './file-parser';
89
import * as analytics from '../../../../lib/analytics';
910
import * as Debug from 'debug';
1011
import { getErrorStringCode } from './error-utils';
1112
const debug = Debug('iac-extract-line-number');
1213

13-
function getFileTypeForLineNumber(fileType: string): CloudConfigFileTypes {
14+
export function getFileTypeForParser(fileType: string): CloudConfigFileTypes {
1415
switch (fileType) {
1516
case 'yaml':
1617
case 'yml':
@@ -25,16 +26,12 @@ function getFileTypeForLineNumber(fileType: string): CloudConfigFileTypes {
2526
}
2627

2728
export function extractLineNumber(
28-
fileContent: string,
29-
fileType: string,
3029
cloudConfigPath: string[],
30+
fileType: CloudConfigFileTypes,
31+
treeByDocId: MapsDocIdToTree,
3132
): number {
3233
try {
33-
return issuesToLineNumbers(
34-
fileContent,
35-
getFileTypeForLineNumber(fileType),
36-
cloudConfigPath,
37-
);
34+
return getLineNumber(cloudConfigPath, fileType, treeByDocId);
3835
} catch {
3936
const err = new FailedToExtractLineNumberError();
4037
analytics.add('error-code', err.code);

src/cli/commands/test/iac-local-execution/results-formatter.ts

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ import * as path from 'path';
1212
import { SEVERITY } from '../../../../lib/snyk-test/common';
1313
import { IacProjectType } from '../../../../lib/iac/constants';
1414
import { CustomError } from '../../../../lib/errors';
15-
import { extractLineNumber } from './extract-line-number';
15+
import { extractLineNumber, getFileTypeForParser } from './extract-line-number';
1616
import { getErrorStringCode } from './error-utils';
1717
import { isLocalFolder } from '../../../../lib/detect';
18+
import { MapsDocIdToTree, getTrees } from '@snyk/cloud-config-parser';
1819

1920
const SEVERITIES = [SEVERITY.LOW, SEVERITY.MEDIUM, SEVERITY.HIGH];
2021

@@ -53,27 +54,24 @@ function formatScanResult(
5354
meta: TestMeta,
5455
options: IaCTestFlags,
5556
): FormattedResult {
57+
const fileType = getFileTypeForParser(scanResult.fileType);
58+
let treeByDocId: MapsDocIdToTree;
59+
try {
60+
treeByDocId = getTrees(fileType, scanResult.fileContent);
61+
} catch (err) {
62+
// we do nothing intentionally.
63+
// Even if the building of the tree fails in the external parser,
64+
// we still pass an undefined tree and not calculated line number for those
65+
}
66+
5667
const formattedIssues = scanResult.violatedPolicies.map((policy) => {
5768
const cloudConfigPath =
5869
scanResult.docId !== undefined
5970
? [`[DocId: ${scanResult.docId}]`].concat(parsePath(policy.msg))
6071
: policy.msg.split('.');
6172

62-
const flagsRequiringLineNumber = [
63-
'json',
64-
'sarif',
65-
'json-file-output',
66-
'sarif-file-output',
67-
];
68-
const shouldExtractLineNumber = flagsRequiringLineNumber.some(
69-
(flag) => options[flag],
70-
);
71-
const lineNumber: number = shouldExtractLineNumber
72-
? extractLineNumber(
73-
scanResult.fileContent,
74-
scanResult.fileType,
75-
cloudConfigPath,
76-
)
73+
const lineNumber: number = treeByDocId
74+
? extractLineNumber(cloudConfigPath, fileType, treeByDocId)
7775
: -1;
7876

7977
return {

test/jest/unit/iac-unit-tests/results-formatter.spec.ts

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@ import {
1010
policyStub,
1111
generateScanResults,
1212
} from './results-formatter.fixtures';
13-
import { issuesToLineNumbers } from '@snyk/cloud-config-parser';
13+
import * as cloudConfigParserModule from '@snyk/cloud-config-parser';
1414
import { PolicyMetadata } from '../../../../src/cli/commands/test/iac-local-execution/types';
1515

16-
jest.mock('@snyk/cloud-config-parser');
17-
16+
jest.mock('@snyk/cloud-config-parser', () => ({
17+
...jest.requireActual('@snyk/cloud-config-parser'),
18+
}));
19+
const validTree = { '0': { nodes: [] } };
1820
describe('formatScanResults', () => {
1921
it.each([
2022
[
2123
{ severityThreshold: SEVERITY.HIGH },
22-
expectedFormattedResultsWithoutLineNumber,
24+
expectedFormattedResultsWithLineNumber,
2325
],
2426
[
2527
{ severityThreshold: SEVERITY.HIGH, sarif: true },
@@ -40,7 +42,10 @@ describe('formatScanResults', () => {
4042
])(
4143
'given %p options object, returns the expected results',
4244
(optionsObject, expectedResult) => {
43-
(issuesToLineNumbers as jest.Mock).mockReturnValue(3);
45+
jest
46+
.spyOn(cloudConfigParserModule, 'getTrees')
47+
.mockReturnValue(validTree);
48+
jest.spyOn(cloudConfigParserModule, 'getLineNumber').mockReturnValue(3);
4449
const formattedResults = formatScanResults(
4550
generateScanResults(),
4651
optionsObject,
@@ -51,9 +56,50 @@ describe('formatScanResults', () => {
5156
expect(formattedResults[0]).toEqual(expectedResult);
5257
},
5358
);
54-
// TODO: add tests for the multi-doc yaml grouping
5559
});
5660

61+
describe('parser failures should return -1 for lineNumber', () => {
62+
beforeEach(async () => {
63+
jest.restoreAllMocks();
64+
});
65+
66+
it('creates a valid tree, but the getLineNumber() fails', () => {
67+
jest.spyOn(cloudConfigParserModule, 'getTrees').mockReturnValue(validTree);
68+
jest
69+
.spyOn(cloudConfigParserModule, 'getLineNumber')
70+
.mockImplementation(() => {
71+
throw new Error();
72+
});
73+
const formattedResults = formatScanResults(
74+
generateScanResults(),
75+
{ severityThreshold: SEVERITY.HIGH },
76+
meta,
77+
);
78+
79+
expect(formattedResults.length).toEqual(1);
80+
expect(formattedResults[0]).toEqual(
81+
expectedFormattedResultsWithoutLineNumber,
82+
);
83+
});
84+
85+
it('sends an invalid tree and getLineNumber() fails', () => {
86+
jest
87+
.spyOn(cloudConfigParserModule, 'getTrees')
88+
.mockReturnValue(null as any);
89+
const formattedResults = formatScanResults(
90+
generateScanResults(),
91+
{ severityThreshold: SEVERITY.HIGH },
92+
meta,
93+
);
94+
95+
expect(formattedResults.length).toEqual(1);
96+
expect(formattedResults[0]).toEqual(
97+
expectedFormattedResultsWithoutLineNumber,
98+
);
99+
});
100+
});
101+
102+
// TODO: add tests for the multi-doc yaml grouping
57103
describe('filterPoliciesBySeverity', () => {
58104
it('returns the formatted results filtered by severity - no default threshold', () => {
59105
const scanResults = generateScanResults();

0 commit comments

Comments
 (0)