diff --git a/lib/manager/npm/post-update/node-version.spec.ts b/lib/manager/npm/post-update/node-version.spec.ts index 36702afb450e8d1c74338ed70a098a4cccb47037..9f045c63f1891e61a72989b5533cc030d7a55c6f 100644 --- a/lib/manager/npm/post-update/node-version.spec.ts +++ b/lib/manager/npm/post-update/node-version.spec.ts @@ -1,4 +1,5 @@ import { fs } from '../../../../test/util'; +import { isStable } from '../../../versioning/node'; import { getNodeConstraint } from './node-version'; jest.mock('../../../util/fs'); @@ -15,6 +16,18 @@ describe('getNodeConstraint', () => { const res = await getNodeConstraint(config); expect(res).toEqual('^12.16.0'); }); + it('augments to avoid node 15', async () => { + fs.readLocalFile = jest.fn(); + fs.readLocalFile.mockResolvedValueOnce(null); + fs.readLocalFile.mockResolvedValueOnce(null); + const res = await getNodeConstraint({ + ...config, + constraints: { node: '>= 12.16.0' }, + }); + const isAugmentedRange = res === '>= 12.16.0 <15'; + const node16IsStable = isStable('16.100.0'); + expect(isAugmentedRange || node16IsStable).toBe(true); + }); it('returns .node-version value', async () => { fs.readLocalFile = jest.fn(); fs.readLocalFile.mockResolvedValueOnce(null); diff --git a/lib/manager/npm/post-update/node-version.ts b/lib/manager/npm/post-update/node-version.ts index adaf0dff9c9fdeadc0a349f46ddc16002de9309e..8cbbc0b301265f643bf202fd22ec5239c062a42b 100644 --- a/lib/manager/npm/post-update/node-version.ts +++ b/lib/manager/npm/post-update/node-version.ts @@ -1,6 +1,7 @@ -import { validRange } from 'semver'; +import { satisfies, validRange } from 'semver'; import { logger } from '../../../logger'; import { getSiblingFileName, readLocalFile } from '../../../util/fs'; +import { isStable } from '../../../versioning/node'; import { PostUpdateConfig } from '../../common'; async function getNodeFile(filename: string): Promise<string> | null { @@ -31,11 +32,24 @@ export async function getNodeConstraint( config: PostUpdateConfig ): Promise<string> | null { const { packageFile } = config; - const constraint = + let constraint = (await getNodeFile(getSiblingFileName(packageFile, '.nvmrc'))) || (await getNodeFile(getSiblingFileName(packageFile, '.node-version'))) || getPackageJsonConstraint(config); - if (!constraint) { + // Avoid using node 15 if node 14 also satisfies the same constraint + // Remove this once node 16 is LTS + if (constraint) { + if ( + validRange(constraint) && + satisfies('14.100.0', constraint) && + satisfies('15.100.0', constraint) && + !isStable('16.100.0') && // this should return false as soon as Node 16 is LTS + validRange(`${constraint} <15`) + ) { + logger.debug('Augmenting constraint to avoid node 15'); + constraint = `${constraint} <15`; + } + } else { logger.debug('No node constraint found - using latest'); } return constraint;