Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(manager/npm): support parsing lockfileVersion=3 #22281

Merged
merged 26 commits into from Jun 6, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9ffa524
feat: support lockfileVersion 3
mjunker Apr 18, 2023
5108bb1
refactor: extract dependencies and added tests
mjunker May 17, 2023
7a69f69
chore: fix review findings
mjunker May 17, 2023
c6275d1
feat: added schema for packagelock
mjunker May 19, 2023
e4f6c6a
Merge branch 'main' into feat/merge_lockfile3
mjunker May 22, 2023
0ca1eb6
Merge branch 'main' into feat/merge_lockfile3
mjunker May 22, 2023
5bb44ae
chore: review findings
mjunker May 22, 2023
19a107f
Merge branch 'main' into feat/merge_lockfile3
rarkins May 22, 2023
c4dd274
chore: added missing test
mjunker May 23, 2023
6ff26fb
Merge branch 'main' into feat/merge_lockfile3
mjunker May 24, 2023
7e2837e
Merge branch 'main' into feat/merge_lockfile3
rarkins May 24, 2023
6820a53
Update lib/modules/manager/npm/extract/npm.spec.ts
mjunker May 24, 2023
a219b73
Update lib/modules/manager/npm/extract/npm.ts
mjunker May 24, 2023
d9b801a
Update lib/modules/manager/npm/extract/schema.ts
mjunker May 24, 2023
47bdb93
Merge branch 'main' into feat/merge_lockfile3
mjunker May 25, 2023
52aee73
Update lib/modules/manager/npm/extract/schema.ts
mjunker May 25, 2023
98f81d4
chore: review findings
mjunker May 25, 2023
476049d
chore: adjusted npm to PR 22405
mjunker May 25, 2023
17b40a4
Merge branch 'main' into feat/merge_lockfile3
mjunker May 25, 2023
6092124
Merge branch 'main' into feat/merge_lockfile3
mjunker May 30, 2023
5bc5659
Refactor schema
zharinov May 30, 2023
263f64c
Merge pull request #2 from zharinov/22281-suggestion
mjunker May 30, 2023
d4cd6f9
Merge branch 'main' into feat/merge_lockfile3
mjunker May 31, 2023
84b576c
Merge branch 'main' into feat/merge_lockfile3
mjunker Jun 2, 2023
4f12ce9
chore: fix test after merge issue
mjunker Jun 2, 2023
dd44790
Merge branch 'main' into feat/merge_lockfile3
mjunker Jun 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
80 changes: 80 additions & 0 deletions lib/modules/manager/npm/__fixtures__/npm9/package-lock.json

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

15 changes: 15 additions & 0 deletions lib/modules/manager/npm/__fixtures__/npm9/package.json
@@ -0,0 +1,15 @@
{
"name": "npm9",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"chalk": "^2.4.1"
}
}
31 changes: 0 additions & 31 deletions lib/modules/manager/npm/extract/__snapshots__/npm.spec.ts.snap

This file was deleted.

86 changes: 86 additions & 0 deletions lib/modules/manager/npm/extract/locked-versions.spec.ts
Expand Up @@ -535,4 +535,90 @@ describe('modules/manager/npm/extract/locked-versions', () => {
},
]);
});

describe('lockfileVersion 3', () => {
it('uses package-lock.json with npm v9.0.0', async () => {
npm.getNpmLock.mockReturnValue({
lockedVersions: {
a: '1.0.0',
b: '2.0.0',
c: '3.0.0',
},
lockfileVersion: 3,
});
const packageFiles = [
{
managerData: {
npmLock: 'package-lock.json',
},
extractedConstraints: {},
deps: [
{ depName: 'a', currentValue: '1.0.0' },
{ depName: 'b', currentValue: '2.0.0' },
],
packageFile: 'some-file',
},
];
await getLockedVersions(packageFiles);
expect(packageFiles).toEqual([
{
extractedConstraints: {
npm: '>=7',
},
deps: [
{ currentValue: '1.0.0', depName: 'a', lockedVersion: '1.0.0' },
{ currentValue: '2.0.0', depName: 'b', lockedVersion: '2.0.0' },
],
packageFile: 'some-file',
lockFiles: ['package-lock.json'],
managerData: {
npmLock: 'package-lock.json',
},
},
]);
});

it('uses package-lock.json with npm v7.0.0', async () => {
npm.getNpmLock.mockReturnValue({
lockedVersions: {
a: '1.0.0',
b: '2.0.0',
c: '3.0.0',
},
lockfileVersion: 3,
});
const packageFiles = [
{
managerData: {
npmLock: 'package-lock.json',
},
extractedConstraints: {
npm: '^9.0.0',
},
deps: [
{ depName: 'a', currentValue: '1.0.0' },
{ depName: 'b', currentValue: '2.0.0' },
],
packageFile: 'some-file',
},
];
await getLockedVersions(packageFiles);
expect(packageFiles).toEqual([
{
extractedConstraints: {
npm: '^9.0.0',
},
deps: [
{ currentValue: '1.0.0', depName: 'a', lockedVersion: '1.0.0' },
{ currentValue: '2.0.0', depName: 'b', lockedVersion: '2.0.0' },
],
packageFile: 'some-file',
lockFiles: ['package-lock.json'],
managerData: {
npmLock: 'package-lock.json',
},
},
]);
});
});
});
5 changes: 5 additions & 0 deletions lib/modules/manager/npm/extract/locked-versions.ts
Expand Up @@ -80,6 +80,11 @@ export async function getLockedVersions(
} else {
packageFile.extractedConstraints!.npm = '<9';
}
} else if (
lockfileVersion === 3 &&
!packageFile.extractedConstraints?.npm
) {
packageFile.extractedConstraints!.npm = '>=7';
}
mjunker marked this conversation as resolved.
Show resolved Hide resolved
for (const dep of packageFile.deps) {
// TODO: types (#7154)
Expand Down
45 changes: 43 additions & 2 deletions lib/modules/manager/npm/extract/npm.spec.ts
Expand Up @@ -16,19 +16,60 @@ describe('modules/manager/npm/extract/npm', () => {
const plocktest1Lock = Fixtures.get('plocktest1/package-lock.json', '..');
fs.readLocalFile.mockResolvedValueOnce(plocktest1Lock as never);
const res = await getNpmLock('package.json');
expect(res).toMatchSnapshot();
expect(res).toEqual({
lockedVersions: {
'ansi-styles': '3.2.1',
chalk: '2.4.1',
'color-convert': '1.9.1',
'color-name': '1.1.3',
'escape-string-regexp': '1.0.5',
'has-flag': '3.0.0',
'supports-color': '5.4.0',
},
lockfileVersion: 1,
});
expect(Object.keys(res.lockedVersions)).toHaveLength(7);
expect(res.lockfileVersion).toBe(1);
});

it('extracts npm 7 lockfile', async () => {
const npm7Lock = Fixtures.get('npm7/package-lock.json', '..');
fs.readLocalFile.mockResolvedValueOnce(npm7Lock as never);
const res = await getNpmLock('package.json');
expect(res).toMatchSnapshot();
expect(res).toEqual({
lockedVersions: {
'ansi-styles': '3.2.1',
chalk: '2.4.1',
'color-convert': '1.9.1',
'color-name': '1.1.3',
'escape-string-regexp': '1.0.5',
'has-flag': '3.0.0',
'supports-color': '5.4.0',
},
lockfileVersion: 2,
});
expect(Object.keys(res.lockedVersions)).toHaveLength(7);
expect(res.lockfileVersion).toBe(2);
});

it('extracts npm 9 lockfile', async () => {
const npm9Lock = Fixtures.get('npm9/package-lock.json', '..');
fs.readLocalFile.mockResolvedValueOnce(npm9Lock as never);
mjunker marked this conversation as resolved.
Show resolved Hide resolved
const res = await getNpmLock('package.json');
expect(res).toEqual({
lockedVersions: {
'ansi-styles': '3.2.1',
chalk: '2.4.2',
'color-convert': '1.9.3',
'color-name': '1.1.3',
'escape-string-regexp': '1.0.5',
'has-flag': '3.0.0',
'supports-color': '5.5.0',
},
lockfileVersion: 3,
});
});

it('returns empty if no deps', async () => {
fs.readLocalFile.mockResolvedValueOnce('{}');
const res = await getNpmLock('package.json');
Expand Down
21 changes: 18 additions & 3 deletions lib/modules/manager/npm/extract/npm.ts
Expand Up @@ -8,9 +8,7 @@ export async function getNpmLock(filePath: string): Promise<LockFile> {
try {
const lockParsed = JSON.parse(lockRaw);
const lockedVersions: Record<string, string> = {};
for (const [entry, val] of Object.entries(
(lockParsed.dependencies || {}) as LockFileEntry
)) {
for (const [entry, val] of Object.entries(getPackages(lockParsed))) {
logger.trace({ entry, version: val.version });
lockedVersions[entry] = val.version;
}
Expand All @@ -20,3 +18,20 @@ export async function getNpmLock(filePath: string): Promise<LockFile> {
return { lockedVersions: {} };
}
}
function getPackages(lockParsed: any): LockFileEntry {
let packages: LockFileEntry = {};

if (
mjunker marked this conversation as resolved.
Show resolved Hide resolved
(lockParsed.lockfileVersion === 1 || lockParsed.lockfileVersion === 2) &&
lockParsed.dependencies
) {
packages = lockParsed.dependencies;
} else if (lockParsed.lockfileVersion === 3 && lockParsed.packages) {
packages = Object.fromEntries(
Object.entries(lockParsed.packages)
.filter(([key]) => !!key) // filter out root entry
.map(([key, val]) => [key.replace(`node_modules/`, ''), val])
) as LockFileEntry;
}
return packages;
}