diff --git a/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap b/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap index f9b6e422bb0f756d00582144b4535356c3a3745a..06024603d866fc4bcc98c46c3b40bb8c72a2daf9 100644 --- a/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap +++ b/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap @@ -2,6 +2,7 @@ exports[`manager/npm/extract .extractPackageFile() catches invalid names 1`] = ` Object { + "compatibility": Object {}, "deps": Array [ Object { "depName": "kgabis/parson", @@ -29,6 +30,11 @@ Object { exports[`manager/npm/extract .extractPackageFile() extracts engines 1`] = ` Object { + "compatibility": Object { + "node": ">= 8.9.2", + "npm": "^8.0.0", + "yarn": "disabled", + }, "deps": Array [ Object { "currentValue": "1.6.0", @@ -131,6 +137,7 @@ Object { exports[`manager/npm/extract .extractPackageFile() extracts non-npmjs 1`] = ` Object { + "compatibility": Object {}, "deps": Array [ Object { "currentValue": "github:owner/a", @@ -292,6 +299,7 @@ Object { exports[`manager/npm/extract .extractPackageFile() extracts npm package alias 1`] = ` Object { + "compatibility": Object {}, "deps": Array [ Object { "currentValue": "1", @@ -339,6 +347,9 @@ Object { exports[`manager/npm/extract .extractPackageFile() extracts volta 1`] = ` Object { + "compatibility": Object { + "node": "8.9.2", + }, "deps": Array [ Object { "commitMessageTopic": "Node.js", @@ -401,6 +412,9 @@ Object { exports[`manager/npm/extract .extractPackageFile() extracts volta yarn unknown-version 1`] = ` Object { + "compatibility": Object { + "node": "8.9.2", + }, "deps": Array [ Object { "commitMessageTopic": "Node.js", @@ -457,6 +471,7 @@ Object { exports[`manager/npm/extract .extractPackageFile() finds "npmClient":"npm" in lerna.json 1`] = ` Object { + "compatibility": Object {}, "deps": Array [ Object { "currentValue": "6.5.0", @@ -591,6 +606,7 @@ Object { exports[`manager/npm/extract .extractPackageFile() finds "npmClient":"yarn" in lerna.json 1`] = ` Object { + "compatibility": Object {}, "deps": Array [ Object { "currentValue": "6.5.0", @@ -725,6 +741,7 @@ Object { exports[`manager/npm/extract .extractPackageFile() finds a lock file 1`] = ` Object { + "compatibility": Object {}, "deps": Array [ Object { "currentValue": "6.5.0", @@ -859,6 +876,7 @@ Object { exports[`manager/npm/extract .extractPackageFile() finds complex yarn workspaces 1`] = ` Object { + "compatibility": Object {}, "deps": Array [], "ignoreNpmrcFile": undefined, "lernaClient": "npm", @@ -881,6 +899,7 @@ Object { exports[`manager/npm/extract .extractPackageFile() finds lerna 1`] = ` Object { + "compatibility": Object {}, "deps": Array [ Object { "currentValue": "6.5.0", @@ -1015,6 +1034,7 @@ Object { exports[`manager/npm/extract .extractPackageFile() finds simple yarn workspaces 1`] = ` Object { + "compatibility": Object {}, "deps": Array [], "ignoreNpmrcFile": undefined, "lernaClient": "npm", @@ -1037,6 +1057,7 @@ Object { exports[`manager/npm/extract .extractPackageFile() returns an array of dependencies 1`] = ` Object { + "compatibility": Object {}, "deps": Array [ Object { "currentValue": "6.5.0", diff --git a/lib/manager/npm/extract/index.ts b/lib/manager/npm/extract/index.ts index e2cd307971f788859ce4239c74426c5ebb3e0bd8..2bd6c2316ce910c6d668621ad32b673e3eba2110 100644 --- a/lib/manager/npm/extract/index.ts +++ b/lib/manager/npm/extract/index.ts @@ -148,6 +148,8 @@ export async function extractPackageFile( resolutions: 'resolutions', }; + const compatibility: Record<string, any> = {}; + function extractDependency( depType: string, depName: string, @@ -168,12 +170,15 @@ export async function extractPackageFile( dep.datasource = datasourceGithubTags.id; dep.lookupName = 'nodejs/node'; dep.versioning = nodeVersioning.id; + compatibility.node = dep.currentValue; } else if (depName === 'yarn') { dep.datasource = datasourceNpm.id; dep.commitMessageTopic = 'Yarn'; + compatibility.yarn = dep.currentValue; } else if (depName === 'npm') { dep.datasource = datasourceNpm.id; dep.commitMessageTopic = 'npm'; + compatibility.npm = dep.currentValue; } else { dep.skipReason = SkipReason.UnknownEngines; } @@ -351,6 +356,7 @@ export async function extractPackageFile( lernaPackages, skipInstalls, yarnWorkspacesPackages, + compatibility, }; } diff --git a/lib/manager/npm/post-update/node-version.spec.ts b/lib/manager/npm/post-update/node-version.spec.ts index f287dbbccc0b65c5488fd73a36f53229fb2c3446..e529d1d3236f6923b7209d9cba3d26e4605614bb 100644 --- a/lib/manager/npm/post-update/node-version.spec.ts +++ b/lib/manager/npm/post-update/node-version.spec.ts @@ -5,41 +5,42 @@ import { getNodeConstraint } from './node-version'; const fs = mocked(fs_); describe('getNodeConstraint', () => { + const config = { + packageFile: 'package.json', + compatibility: { node: '^12.16.0' }, + }; it('returns package.json range', async () => { fs.readLocalFile = jest.fn(); fs.readLocalFile.mockResolvedValueOnce(null); fs.readLocalFile.mockResolvedValueOnce(null); - fs.readLocalFile.mockResolvedValueOnce('{"engines":{"node":"^12.16.0"}}'); - const res = await getNodeConstraint({ packageFile: 'package.json' }); + const res = await getNodeConstraint(config); expect(res).toEqual('^12.16.0'); }); it('returns .node-version value', async () => { fs.readLocalFile = jest.fn(); fs.readLocalFile.mockResolvedValueOnce(null); fs.readLocalFile.mockResolvedValueOnce('12.16.1\n'); - const res = await getNodeConstraint({ packageFile: 'package.json' }); + const res = await getNodeConstraint(config); expect(res).toEqual('12.16.1'); }); it('returns .nvmrc value', async () => { fs.readLocalFile = jest.fn(); fs.readLocalFile.mockResolvedValueOnce('12.16.2\n'); - const res = await getNodeConstraint({ packageFile: 'package.json' }); + const res = await getNodeConstraint(config); expect(res).toEqual('12.16.2'); }); it('ignores unusable ranges in dotfiles', async () => { fs.readLocalFile = jest.fn(); fs.readLocalFile.mockResolvedValueOnce('latest'); fs.readLocalFile.mockResolvedValueOnce('lts'); - fs.readLocalFile.mockResolvedValueOnce('{"engines":{"node":"^12.16.0"}}'); - const res = await getNodeConstraint({ packageFile: 'package.json' }); + const res = await getNodeConstraint(config); expect(res).toEqual('^12.16.0'); }); it('returns no constraint', async () => { fs.readLocalFile = jest.fn(); fs.readLocalFile.mockResolvedValueOnce(null); fs.readLocalFile.mockResolvedValueOnce(null); - fs.readLocalFile.mockResolvedValueOnce('{}'); - const res = await getNodeConstraint({ packageFile: 'package.json' }); + const res = await getNodeConstraint({ ...config, compatibility: null }); expect(res).toBeNull(); }); }); diff --git a/lib/manager/npm/post-update/node-version.ts b/lib/manager/npm/post-update/node-version.ts index 2c664e2a8e992a8faf60a0e3f0cb4b65c7dae294..b929499b63137e88f8dc17426cdbfcab2bdb9106 100644 --- a/lib/manager/npm/post-update/node-version.ts +++ b/lib/manager/npm/post-update/node-version.ts @@ -18,18 +18,13 @@ async function getNodeFile(filename: string): Promise<string> | null { return null; } -async function getPackageJsonConstraint( - filename: string +function getPackageJsonConstraint( + config: PostUpdateConfig ): Promise<string> | null { - try { - const pj = JSON.parse(await readLocalFile(filename, 'utf8')); - const constraint = pj?.engines?.node; - if (constraint && validRange(constraint)) { - logger.debug(`Using node constraint "${constraint}" from package.json`); - return constraint; - } - } catch (err) { - // do nothing + const constraint = config.compatibility?.node; + if (constraint && validRange(constraint)) { + logger.debug(`Using node constraint "${constraint}" from package.json`); + return constraint; } return null; } @@ -41,7 +36,7 @@ export async function getNodeConstraint( const constraint = (await getNodeFile(getSiblingFileName(packageFile, '.nvmrc'))) || (await getNodeFile(getSiblingFileName(packageFile, '.node-version'))) || - (await getPackageJsonConstraint(packageFile)); + getPackageJsonConstraint(config); if (!constraint) { logger.debug('No node constraint found - using latest'); } diff --git a/lib/workers/repository/extract/__snapshots__/manager-files.spec.ts.snap b/lib/workers/repository/extract/__snapshots__/manager-files.spec.ts.snap index 8d00958e6fe702c0d756db97af61c174d495bdc1..bdb8c7cc7f2215c0632400dbfbc107498f266430 100644 --- a/lib/workers/repository/extract/__snapshots__/manager-files.spec.ts.snap +++ b/lib/workers/repository/extract/__snapshots__/manager-files.spec.ts.snap @@ -3,6 +3,7 @@ exports[`workers/repository/extract/manager-files getManagerPackageFiles() returns files with extractAllPackageFiles 1`] = ` Array [ Object { + "compatibility": Object {}, "deps": Array [ Object { "currentValue": "2.0.0",