mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-12 15:06:27 +00:00
feat: binarySource=docker avoid unstable tags (#12309)
This commit is contained in:
parent
b4665d35cf
commit
8571b3e68d
8 changed files with 24 additions and 81 deletions
|
@ -72,8 +72,7 @@ export async function generateLockFiles(
|
||||||
lernaCommand = lernaCommand.replace('--ignore-scripts ', '');
|
lernaCommand = lernaCommand.replace('--ignore-scripts ', '');
|
||||||
}
|
}
|
||||||
lernaCommand += cmdOptions;
|
lernaCommand += cmdOptions;
|
||||||
const allowUnstable = true; // lerna will pick the default installed npm@6 unless we use node@>=15
|
const tagConstraint = await getNodeConstraint(config);
|
||||||
const tagConstraint = await getNodeConstraint(config, allowUnstable);
|
|
||||||
const execOptions: ExecOptions = {
|
const execOptions: ExecOptions = {
|
||||||
cwd,
|
cwd,
|
||||||
extraEnv: {
|
extraEnv: {
|
||||||
|
@ -82,7 +81,7 @@ export async function generateLockFiles(
|
||||||
},
|
},
|
||||||
docker: {
|
docker: {
|
||||||
image: 'node',
|
image: 'node',
|
||||||
tagScheme: 'npm',
|
tagScheme: 'node',
|
||||||
tagConstraint,
|
tagConstraint,
|
||||||
preCommands,
|
preCommands,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { fs } from '../../../../test/util';
|
import { fs } from '../../../../test/util';
|
||||||
import { isStable } from '../../../versioning/node';
|
|
||||||
import { getNodeConstraint } from './node-version';
|
import { getNodeConstraint } from './node-version';
|
||||||
|
|
||||||
jest.mock('../../../util/fs');
|
jest.mock('../../../util/fs');
|
||||||
|
@ -16,45 +15,6 @@ describe('manager/npm/post-update/node-version', () => {
|
||||||
const res = await getNodeConstraint(config);
|
const res = await getNodeConstraint(config);
|
||||||
expect(res).toEqual('^12.16.0');
|
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('forces node 15 if v2 lockfile detected and constraint allows', async () => {
|
|
||||||
fs.readLocalFile.mockResolvedValueOnce(null);
|
|
||||||
fs.readLocalFile.mockResolvedValueOnce(null);
|
|
||||||
fs.readLocalFile.mockResolvedValueOnce('{"lockfileVersion":2}');
|
|
||||||
const res = await getNodeConstraint({
|
|
||||||
...config,
|
|
||||||
constraints: { node: '>= 12.16.0' },
|
|
||||||
});
|
|
||||||
const isAugmentedRange = res === '>=15 <17';
|
|
||||||
const node16IsStable = isStable('16.100.0');
|
|
||||||
expect(isAugmentedRange || node16IsStable).toBe(true);
|
|
||||||
});
|
|
||||||
it('forces node 15 if v2 lockfile detected and no constraint', async () => {
|
|
||||||
fs.readLocalFile.mockResolvedValueOnce(null);
|
|
||||||
fs.readLocalFile.mockResolvedValueOnce(null);
|
|
||||||
fs.readLocalFile.mockResolvedValueOnce('{"lockfileVersion":2}');
|
|
||||||
const res = await getNodeConstraint(
|
|
||||||
{
|
|
||||||
...config,
|
|
||||||
constraints: {},
|
|
||||||
},
|
|
||||||
true
|
|
||||||
);
|
|
||||||
const isAugmentedRange = res === '>=15';
|
|
||||||
const node16IsStable = isStable('16.100.0');
|
|
||||||
expect(isAugmentedRange || node16IsStable).toBe(true);
|
|
||||||
});
|
|
||||||
it('returns .node-version value', async () => {
|
it('returns .node-version value', async () => {
|
||||||
fs.readLocalFile = jest.fn();
|
fs.readLocalFile = jest.fn();
|
||||||
fs.readLocalFile.mockResolvedValueOnce(null);
|
fs.readLocalFile.mockResolvedValueOnce(null);
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { satisfies, validRange } from 'semver';
|
import { validRange } from 'semver';
|
||||||
import { logger } from '../../../logger';
|
import { logger } from '../../../logger';
|
||||||
import { getSiblingFileName, readLocalFile } from '../../../util/fs';
|
import { getSiblingFileName, readLocalFile } from '../../../util/fs';
|
||||||
import { regEx } from '../../../util/regex';
|
import { regEx } from '../../../util/regex';
|
||||||
import { isStable } from '../../../versioning/node';
|
|
||||||
import type { PostUpdateConfig } from '../../types';
|
import type { PostUpdateConfig } from '../../types';
|
||||||
|
|
||||||
async function getNodeFile(filename: string): Promise<string> | null {
|
async function getNodeFile(filename: string): Promise<string> | null {
|
||||||
|
@ -30,44 +29,14 @@ function getPackageJsonConstraint(config: PostUpdateConfig): string | null {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getNodeConstraint(
|
export async function getNodeConstraint(
|
||||||
config: PostUpdateConfig,
|
config: PostUpdateConfig
|
||||||
allowUnstable = false
|
|
||||||
): Promise<string> | null {
|
): Promise<string> | null {
|
||||||
const { packageFile } = config;
|
const { packageFile } = config;
|
||||||
let constraint =
|
const constraint =
|
||||||
(await getNodeFile(getSiblingFileName(packageFile, '.nvmrc'))) ||
|
(await getNodeFile(getSiblingFileName(packageFile, '.nvmrc'))) ||
|
||||||
(await getNodeFile(getSiblingFileName(packageFile, '.node-version'))) ||
|
(await getNodeFile(getSiblingFileName(packageFile, '.node-version'))) ||
|
||||||
getPackageJsonConstraint(config);
|
getPackageJsonConstraint(config);
|
||||||
let lockfileVersion = 1;
|
if (!constraint) {
|
||||||
try {
|
|
||||||
const lockFileName = getSiblingFileName(packageFile, 'package-lock.json');
|
|
||||||
lockfileVersion = JSON.parse(
|
|
||||||
await readLocalFile(lockFileName, 'utf8')
|
|
||||||
).lockfileVersion;
|
|
||||||
} catch (err) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
// 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')
|
|
||||||
) {
|
|
||||||
if (lockfileVersion === 2) {
|
|
||||||
logger.debug('Forcing node 15+ to ensure lockfileVersion=2 is used');
|
|
||||||
constraint = '>=15 <17';
|
|
||||||
} else if (validRange(`${constraint} <15`)) {
|
|
||||||
logger.debug('Augmenting constraint to avoid node 15');
|
|
||||||
constraint = `${constraint} <15`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (allowUnstable && lockfileVersion === 2) {
|
|
||||||
logger.debug('Using node >=15 for lockfileVersion=2');
|
|
||||||
constraint = '>=15';
|
|
||||||
} else {
|
|
||||||
logger.debug('No node constraint found - using latest');
|
logger.debug('No node constraint found - using latest');
|
||||||
}
|
}
|
||||||
return constraint;
|
return constraint;
|
||||||
|
|
|
@ -65,7 +65,7 @@ export async function generateLockFile(
|
||||||
},
|
},
|
||||||
docker: {
|
docker: {
|
||||||
image: 'node',
|
image: 'node',
|
||||||
tagScheme: 'npm',
|
tagScheme: 'node',
|
||||||
tagConstraint,
|
tagConstraint,
|
||||||
preCommands,
|
preCommands,
|
||||||
},
|
},
|
||||||
|
|
|
@ -38,7 +38,7 @@ export async function generateLockFile(
|
||||||
},
|
},
|
||||||
docker: {
|
docker: {
|
||||||
image: 'node',
|
image: 'node',
|
||||||
tagScheme: 'npm',
|
tagScheme: 'node',
|
||||||
tagConstraint,
|
tagConstraint,
|
||||||
preCommands,
|
preCommands,
|
||||||
},
|
},
|
||||||
|
|
|
@ -129,7 +129,7 @@ export async function generateLockFile(
|
||||||
extraEnv,
|
extraEnv,
|
||||||
docker: {
|
docker: {
|
||||||
image: 'node',
|
image: 'node',
|
||||||
tagScheme: 'npm',
|
tagScheme: 'node',
|
||||||
tagConstraint,
|
tagConstraint,
|
||||||
preCommands,
|
preCommands,
|
||||||
},
|
},
|
||||||
|
|
|
@ -95,6 +95,16 @@ describe('util/exec/docker/index', () => {
|
||||||
getPkgReleases.mockResolvedValueOnce({ releases } as never);
|
getPkgReleases.mockResolvedValueOnce({ releases } as never);
|
||||||
expect(await getDockerTag('foo', '^1.2.3', 'npm')).toBe('1.9.9');
|
expect(await getDockerTag('foo', '^1.2.3', 'npm')).toBe('1.9.9');
|
||||||
});
|
});
|
||||||
|
it('filters out node unstable', async () => {
|
||||||
|
const releases = [
|
||||||
|
{ version: '12.0.0' },
|
||||||
|
{ version: '13.0.1' },
|
||||||
|
{ version: '14.0.2' },
|
||||||
|
{ version: '15.0.2' },
|
||||||
|
];
|
||||||
|
getPkgReleases.mockResolvedValueOnce({ releases } as never);
|
||||||
|
expect(await getDockerTag('foo', '>=12', 'node')).toBe('14.0.2');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('removeDockerContainer', () => {
|
describe('removeDockerContainer', () => {
|
||||||
|
|
|
@ -93,6 +93,11 @@ export async function getDockerTag(
|
||||||
versions = versions.filter(
|
versions = versions.filter(
|
||||||
(version) => ver.isVersion(version) && ver.matches(version, constraint)
|
(version) => ver.isVersion(version) && ver.matches(version, constraint)
|
||||||
);
|
);
|
||||||
|
// Prefer stable versions over unstable, even if the range satisfies both types
|
||||||
|
if (!versions.every((version) => ver.isStable(version))) {
|
||||||
|
logger.debug('Filtering out unstable versions');
|
||||||
|
versions = versions.filter((version) => ver.isStable(version));
|
||||||
|
}
|
||||||
versions = versions.sort(ver.sortVersions.bind(ver));
|
versions = versions.sort(ver.sortVersions.bind(ver));
|
||||||
if (versions.length) {
|
if (versions.length) {
|
||||||
const version = versions.pop();
|
const version = versions.pop();
|
||||||
|
|
Loading…
Reference in a new issue