Skip to content

Commit

Permalink
Merge pull request #118 from snyk/feat/analysis-context
Browse files Browse the repository at this point in the history
feat: add additional context for analysis request
  • Loading branch information
saark-snyk authored Dec 21, 2021
2 parents e7f1afc + b800cea commit e50e6f4
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 20 deletions.
1 change: 1 addition & 0 deletions src/analysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export async function analyzeFolders(options: FileAnalysisOptions): Promise<File
...options.connection,
...options.analysisOptions,
shard: calcHash(fileBundle.baseDir),
analysisContext: options.analysisContext,
});

if (analysisResults.type === 'legacy') {
Expand Down
13 changes: 3 additions & 10 deletions src/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ErrorCodes, GenericErrorTypes, DEFAULT_ERROR_MESSAGES, MAX_RETRY_ATTEMP
import { BundleFiles, SupportedFiles } from './interfaces/files.interface';
import { AnalysisResult } from './interfaces/analysis-result.interface';
import { makeRequest, Payload } from './needle';
import { AnalysisOptions, AnalysisContext } from './interfaces/analysis-options.interface';

type ResultSuccess<T> = { type: 'success'; value: T };
type ResultError<E> = {
Expand Down Expand Up @@ -327,15 +328,7 @@ const GET_ANALYSIS_ERROR_MESSAGES: { [P in GetAnalysisErrorCodes]: string } = {
[ErrorCodes.serverError]: 'Getting analysis failed',
};

export interface AnalysisOptions {
readonly shard?: string;
readonly severity?: number;
readonly limitToFiles?: string[];
readonly prioritized?: boolean;
readonly legacy?: boolean;
}

export interface GetAnalysisOptions extends ConnectionOptions, AnalysisOptions {
export interface GetAnalysisOptions extends ConnectionOptions, AnalysisOptions, AnalysisContext {
bundleHash: string;
}

Expand All @@ -356,7 +349,7 @@ export async function getAnalysis(
limitToFiles: options.limitToFiles || [],
...(options.shard ? { shard: options.shard } : null),
},
...pick(options, ['severity', 'prioritized', 'legacy']),
...pick(options, ['severity', 'prioritized', 'legacy', 'analysisContext']),
},
};

Expand Down
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as constants from './constants';
import { getGlobPatterns } from './files';

import { SupportedFiles, FileAnalysis } from './interfaces/files.interface';
import { AnalysisSeverity } from './interfaces/analysis-options.interface';
import { AnalysisSeverity, AnalysisContext } from './interfaces/analysis-options.interface';
import {
AnalysisResult,
AnalysisResultLegacy,
Expand Down Expand Up @@ -37,4 +37,5 @@ export {
checkSession,
getIpFamily,
IpFamily,
AnalysisContext,
};
24 changes: 22 additions & 2 deletions src/interfaces/analysis-options.interface.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,33 @@
import { SupportedFiles } from '..';
import { AnalysisOptions, ConnectionOptions } from '../http';
import { ConnectionOptions } from '../http';

export interface AnalysisOptions {
readonly shard?: string;
readonly severity?: number;
readonly limitToFiles?: string[];
readonly prioritized?: boolean;
readonly legacy?: boolean;
}

// eslint-disable-next-line import/prefer-default-export, no-shadow
export enum AnalysisSeverity {
info = 1,
warning = 2,
critical = 3,
}
export interface FileAnalysisOptions {

export interface AnalysisContext {
analysisContext?: {
orgPublicId?: string;
orgDisplayName?: string;
projectPublicId?: string;
projectName?: string;
initiator: 'IDE' | 'CLI';
flow?: string;
};
}

export interface FileAnalysisOptions extends AnalysisContext {
connection: ConnectionOptions;
analysisOptions: AnalysisOptions;
fileOptions: AnalyzeFoldersOptions;
Expand Down
48 changes: 41 additions & 7 deletions tests/analysis.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import jsonschema from 'jsonschema';
import { analyzeFolders, extendAnalysis } from '../src/analysis';
import { uploadRemoteBundle } from '../src/bundles';
import { baseURL, sessionToken, source, TEST_TIMEOUT } from './constants/base';
import { sampleProjectPath, bundleFiles, bundleFilesFull, bundleExtender } from './constants/sample';
import { sampleProjectPath, bundleFilesFull, bundleExtender } from './constants/sample';
import { emitter } from '../src/emitter';
import { AnalysisResponseProgress } from '../src/http';
import { SupportedFiles } from '../src/interfaces/files.interface';
import { AnalysisSeverity } from '../src/interfaces/analysis-options.interface';
import { AnalysisSeverity, AnalysisContext } from '../src/interfaces/analysis-options.interface';
import * as sarifSchema from './sarif-schema-2.1.0.json';
import * as needle from '../src/needle';

describe('Functional test of analysis', () => {
describe('analyzeFolders', () => {
Expand Down Expand Up @@ -77,8 +78,8 @@ describe('Functional test of analysis', () => {
if (!sampleRes) return; // TS trick
expect(sampleRes.ruleIndex).toBeDefined();
if (!sampleRes.ruleIndex) return; // TS trick
expect(sampleRes!.ruleId).toEqual(
bundle.analysisResults.sarif.runs[0].tool.driver.rules![sampleRes!.ruleIndex!].id,
expect(sampleRes.ruleId).toEqual(
bundle.analysisResults.sarif.runs[0].tool.driver.rules![sampleRes.ruleIndex].id,
);

expect(bundle.analysisResults.timing.analysis).toBeGreaterThanOrEqual(
Expand Down Expand Up @@ -228,7 +229,7 @@ describe('Functional test of analysis', () => {
type Awaited<T> = T extends PromiseLike<infer U> ? Awaited<U> : T;
let extendedBundle!: Awaited<ReturnType<typeof extendAnalysis>>;
try {
await extender.exec();
extender.exec();
extendedBundle = await extendAnalysis({
...fileAnalysis,
files: extender.files.all,
Expand All @@ -237,7 +238,7 @@ describe('Functional test of analysis', () => {
console.error(err);
expect(err).toBeFalsy();
} finally {
await extender.restore();
extender.restore();
}
expect(extendedBundle).toBeTruthy();
if (!extendedBundle) return; // TS trick
Expand All @@ -262,7 +263,7 @@ describe('Functional test of analysis', () => {
if (!sampleRes) return; // TS trick
expect(sampleRes.ruleIndex).toBeDefined();
if (!sampleRes.ruleIndex) return; // TS trick
expect(sampleRes!.ruleId).toEqual(sarifResults.runs[0].tool.driver.rules![sampleRes!.ruleIndex!].id);
expect(sampleRes.ruleId).toEqual(sarifResults.runs[0].tool.driver.rules![sampleRes.ruleIndex].id);

expect(extendedBundle.analysisResults.timing.analysis).toBeGreaterThanOrEqual(
extendedBundle.analysisResults.timing.fetchingCode,
Expand Down Expand Up @@ -295,5 +296,38 @@ describe('Functional test of analysis', () => {
},
TEST_TIMEOUT,
);

it('sends analysis metadata for analysis request', async () => {
const analysisContext: AnalysisContext = {
analysisContext: {
flow: 'test',
initiator: 'CLI',
orgDisplayName: 'org',
orgPublicId: 'id',
projectName: 'proj',
projectPublicId: 'id',
},
};

const makeRequestSpy = jest.spyOn(needle, 'makeRequest');

await analyzeFolders({
connection: { baseURL, sessionToken, source },
analysisOptions: {
severity: 1,
},
fileOptions: {
paths: [sampleProjectPath],
symlinksEnabled: false,
},
...analysisContext,
});
const makeRequestSpyLastCalledWith = makeRequestSpy.mock.calls[makeRequestSpy.mock.calls.length - 1][0];
expect(makeRequestSpyLastCalledWith).toEqual(
expect.objectContaining({
body: expect.objectContaining(analysisContext),
}),
);
});
});
});

0 comments on commit e50e6f4

Please sign in to comment.