Skip to content

Commit

Permalink
feat: improve cli yarn performance for yarn workspaces
Browse files Browse the repository at this point in the history
PS: Why isn't this signed..?

Co-authored-by: dotkas <[email protected]>
Co-authored-by: alina-ilie <[email protected]>
  • Loading branch information
dotkas and alina-ilie committed May 23, 2023
1 parent c1d47be commit 97a60a6
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 32 deletions.
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
"snyk-gradle-plugin": "3.26.4",
"snyk-module": "3.1.0",
"snyk-mvn-plugin": "2.32.3",
"snyk-nodejs-lockfile-parser": "1.49.0",
"snyk-nodejs-lockfile-parser": "1.51.0",
"snyk-nuget-plugin": "1.24.1",
"snyk-php-plugin": "1.9.2",
"snyk-policy": "^1.25.0",
Expand Down
15 changes: 13 additions & 2 deletions src/lib/plugins/nodejs-plugin/npm-lock-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,24 @@ async function buildDepGraph(
return await lockFileParser.parseYarnLockV1Project(
manifestFileContents,
lockFileContents,
options,
{
includeDevDeps: options.includeDevDeps,
includeOptionalDeps: options.includeOptionalDeps,
includePeerDeps: options.includePeerDeps || false,
pruneLevel: 'withinTopLevelDeps',
strictOutOfSync: options.strictOutOfSync,
},
);
case NodeLockfileVersion.YarnLockV2:
return await lockFileParser.parseYarnLockV2Project(
manifestFileContents,
lockFileContents,
options,
{
includeDevDeps: options.includeDevDeps,
includeOptionalDeps: options.includeOptionalDeps,
pruneWithinTopLevelDeps: true,
strictOutOfSync: options.strictOutOfSync,
},
);
case NodeLockfileVersion.NpmLockV2:
case NodeLockfileVersion.NpmLockV3:
Expand Down
63 changes: 42 additions & 21 deletions src/lib/plugins/nodejs-plugin/yarn-workspaces-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from '../get-multi-plugin-result';
import { getFileContents } from '../../get-file-contents';
import { NoSupportedManifestsFoundError } from '../../errors';
import { DepGraph } from '@snyk/dep-graph';

export async function processYarnWorkspaces(
root: string,
Expand Down Expand Up @@ -51,7 +52,6 @@ export async function processYarnWorkspaces(
},
scannedProjects: [],
};
let rootWorkspaceManifestContent = {};
// the folders must be ordered highest first
for (const directory of Object.keys(yarnTargetFiles)) {
debug(`Processing ${directory} as a potential Yarn workspace`);
Expand All @@ -63,6 +63,7 @@ export async function processYarnWorkspaces(
...yarnWorkspacesMap,
...getWorkspacesMap(packageJson),
};

for (const workspaceRoot of Object.keys(yarnWorkspacesMap)) {
const match = packageJsonBelongsToWorkspace(
packageJsonFileName,
Expand All @@ -78,7 +79,6 @@ export async function processYarnWorkspaces(
}
if (packageJsonFileName === workspaceRoot) {
isRootPackageJson = true;
rootWorkspaceManifestContent = JSON.parse(packageJson.content);
}
}

Expand All @@ -88,36 +88,57 @@ export async function processYarnWorkspaces(
);
continue;
}

try {
const rootDir = isYarnWorkspacePackage
? pathUtil.dirname(yarnWorkspacesFilesMap[packageJsonFileName].root)
: pathUtil.dirname(packageJsonFileName);
const rootYarnLockfileName = pathUtil.join(rootDir, 'yarn.lock');
const yarnLock = getFileContents(root, rootYarnLockfileName);

if (
rootWorkspaceManifestContent.hasOwnProperty('resolutions') &&
lockFileParser.getYarnLockfileType(yarnLock.content) ===
lockFileParser.LockfileType.yarn2
) {
const parsedManifestContent = JSON.parse(packageJson.content);
packageJson.content = JSON.stringify({
...parsedManifestContent,
resolutions: rootWorkspaceManifestContent['resolutions'],
});
}

const res = await lockFileParser.buildDepTree(
packageJson.content,
const lockfileVersion = lockFileParser.getYarnLockfileVersion(
yarnLock.content,
settings.dev,
lockFileParser.LockfileType.yarn,
settings.strictOutOfSync !== false,
);

let res: DepGraph;
switch (lockfileVersion) {
case lockFileParser.NodeLockfileVersion.YarnLockV1:
res = await lockFileParser.parseYarnLockV1Project(
packageJson.content,
yarnLock.content,
{
includeDevDeps: settings.dev || false,
includeOptionalDeps: false,
includePeerDeps: false,
pruneLevel: 'withinTopLevelDeps',
strictOutOfSync:
settings.strictOutOfSync === undefined
? true
: settings.strictOutOfSync,
},
);
break;
case lockFileParser.NodeLockfileVersion.YarnLockV2:
res = await lockFileParser.parseYarnLockV2Project(
packageJson.content,
yarnLock.content,
{
includeDevDeps: settings.dev || false,
includeOptionalDeps: false,
pruneWithinTopLevelDeps: true,
strictOutOfSync:
settings.strictOutOfSync === undefined
? true
: settings.strictOutOfSync,
},
);
break;
default:
throw new Error('Failed to build dep graph from current project');
}
const project: ScannedProjectCustom = {
packageManager: 'yarn',
targetFile: pathUtil.relative(root, packageJson.fileName),
depTree: res as any,
depGraph: res as any,
plugin: {
name: 'snyk-nodejs-lockfile-parser',
runtime: process.version,
Expand Down
2 changes: 1 addition & 1 deletion test/tap/cli-test/cli-test.yarn-workspaces.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const YarnWorkspacesTests: AcceptanceTests = {
t.equal(
e.message,
'\nTesting yarn-workspace-out-of-sync...\n\n' +
'Dependency snyk was not found in yarn.lock.' +
'Dependency snyk@1.320.0 was not found in yarn.lock.' +
' Your package.json and yarn.lock are probably out of sync.' +
' Please run "yarn install" and try again.',
'Contains enough info about err',
Expand Down

0 comments on commit 97a60a6

Please sign in to comment.