mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-12 06:56:24 +00:00
feat: new 'lockfile-update' rangeStrategy (#3108)
Adds a new `rangeStrategy` value `lockfile-update'. Enabling this means you will get PRs that contain updates for the versions in your lock file (currently npm and yarn only) even if the range in the `package.json` file hasn't changed because the update is "in range". Closes #1382
This commit is contained in:
parent
baf5d264c9
commit
62d92660b2
13 changed files with 200 additions and 29 deletions
|
@ -593,7 +593,14 @@ const options = [
|
||||||
description: 'Policy for how to modify/update existing ranges.',
|
description: 'Policy for how to modify/update existing ranges.',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: 'replace',
|
default: 'replace',
|
||||||
allowedValues: ['auto', 'pin', 'bump', 'replace', 'widen'],
|
allowedValues: [
|
||||||
|
'auto',
|
||||||
|
'pin',
|
||||||
|
'bump',
|
||||||
|
'replace',
|
||||||
|
'widen',
|
||||||
|
'update-lockfile',
|
||||||
|
],
|
||||||
cli: false,
|
cli: false,
|
||||||
env: false,
|
env: false,
|
||||||
},
|
},
|
||||||
|
@ -825,7 +832,7 @@ const options = [
|
||||||
description: 'Branch topic',
|
description: 'Branch topic',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default:
|
default:
|
||||||
'{{{depNameSanitized}}}-{{{newMajor}}}{{#if isPatch}}.{{{newMinor}}}{{/if}}.x',
|
'{{{depNameSanitized}}}-{{{newMajor}}}{{#if isPatch}}.{{{newMinor}}}{{/if}}.x{{#if isLockfileUpdate}}-lockfile{{/if}}',
|
||||||
cli: false,
|
cli: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,11 +39,16 @@ function determineLockFileDirs(config, packageFiles) {
|
||||||
}
|
}
|
||||||
continue; // eslint-disable-line no-continue
|
continue; // eslint-disable-line no-continue
|
||||||
}
|
}
|
||||||
|
if (upgrade.isLockfileUpdate) {
|
||||||
|
yarnLockDirs.push(upgrade.yarnLock);
|
||||||
|
npmLockDirs.push(upgrade.npmLock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
config.upgrades.every(
|
config.upgrades.every(
|
||||||
upgrade => upgrade.updateType === 'lockFileMaintenance'
|
upgrade =>
|
||||||
|
upgrade.updateType === 'lockFileMaintenance' || upgrade.isLockfileUpdate
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
|
@ -366,12 +371,16 @@ async function getAdditionalFiles(config, packageFiles) {
|
||||||
const lockFileDir = path.dirname(lockFile);
|
const lockFileDir = path.dirname(lockFile);
|
||||||
const fileName = path.basename(lockFile);
|
const fileName = path.basename(lockFile);
|
||||||
logger.debug(`Generating ${fileName} for ${lockFileDir}`);
|
logger.debug(`Generating ${fileName} for ${lockFileDir}`);
|
||||||
|
const upgrades = config.upgrades.filter(
|
||||||
|
upgrade => upgrade.npmLock === lockFile
|
||||||
|
);
|
||||||
const res = await npm.generateLockFile(
|
const res = await npm.generateLockFile(
|
||||||
upath.join(config.localDir, lockFileDir),
|
upath.join(config.localDir, lockFileDir),
|
||||||
env,
|
env,
|
||||||
fileName,
|
fileName,
|
||||||
config.skipInstalls,
|
config.skipInstalls,
|
||||||
config.binarySource
|
config.binarySource,
|
||||||
|
upgrades
|
||||||
);
|
);
|
||||||
if (res.error) {
|
if (res.error) {
|
||||||
// istanbul ignore if
|
// istanbul ignore if
|
||||||
|
@ -415,10 +424,14 @@ async function getAdditionalFiles(config, packageFiles) {
|
||||||
const lockFileDir = path.dirname(lockFile);
|
const lockFileDir = path.dirname(lockFile);
|
||||||
logger.debug(`Generating yarn.lock for ${lockFileDir}`);
|
logger.debug(`Generating yarn.lock for ${lockFileDir}`);
|
||||||
const lockFileName = upath.join(lockFileDir, 'yarn.lock');
|
const lockFileName = upath.join(lockFileDir, 'yarn.lock');
|
||||||
|
const upgrades = config.upgrades.filter(
|
||||||
|
upgrade => upgrade.yarnLock === lockFile
|
||||||
|
);
|
||||||
const res = await yarn.generateLockFile(
|
const res = await yarn.generateLockFile(
|
||||||
upath.join(config.localDir, lockFileDir),
|
upath.join(config.localDir, lockFileDir),
|
||||||
env,
|
env,
|
||||||
config
|
config,
|
||||||
|
upgrades
|
||||||
);
|
);
|
||||||
if (res.error) {
|
if (res.error) {
|
||||||
// istanbul ignore if
|
// istanbul ignore if
|
||||||
|
|
|
@ -12,7 +12,8 @@ async function generateLockFile(
|
||||||
env,
|
env,
|
||||||
filename,
|
filename,
|
||||||
skipInstalls,
|
skipInstalls,
|
||||||
binarySource
|
binarySource,
|
||||||
|
upgrades = []
|
||||||
) {
|
) {
|
||||||
logger.debug(`Spawning npm install to create ${cwd}/${filename}`);
|
logger.debug(`Spawning npm install to create ${cwd}/${filename}`);
|
||||||
let lockFile = null;
|
let lockFile = null;
|
||||||
|
@ -76,6 +77,19 @@ async function generateLockFile(
|
||||||
}));
|
}));
|
||||||
logger.debug(`npm stdout:\n${stdout}`);
|
logger.debug(`npm stdout:\n${stdout}`);
|
||||||
logger.debug(`npm stderr:\n${stderr}`);
|
logger.debug(`npm stderr:\n${stderr}`);
|
||||||
|
const lockUpdates = upgrades.filter(upgrade => upgrade.isLockfileUpdate);
|
||||||
|
if (lockUpdates.length) {
|
||||||
|
const updateCmd =
|
||||||
|
cmd +
|
||||||
|
lockUpdates
|
||||||
|
.map(update => ` ${update.depName}@${update.toVersion}`)
|
||||||
|
.join('');
|
||||||
|
({ stdout, stderr } = await exec(updateCmd, {
|
||||||
|
cwd,
|
||||||
|
shell: true,
|
||||||
|
env,
|
||||||
|
}));
|
||||||
|
}
|
||||||
const duration = process.hrtime(startTime);
|
const duration = process.hrtime(startTime);
|
||||||
const seconds = Math.round(duration[0] + duration[1] / 1e9);
|
const seconds = Math.round(duration[0] + duration[1] / 1e9);
|
||||||
lockFile = await fs.readFile(upath.join(cwd, filename), 'utf8');
|
lockFile = await fs.readFile(upath.join(cwd, filename), 'utf8');
|
||||||
|
|
|
@ -7,7 +7,7 @@ module.exports = {
|
||||||
generateLockFile,
|
generateLockFile,
|
||||||
};
|
};
|
||||||
|
|
||||||
async function generateLockFile(cwd, env, config = {}) {
|
async function generateLockFile(cwd, env, config = {}, upgrades = []) {
|
||||||
const { binarySource, yarnIntegrity } = config;
|
const { binarySource, yarnIntegrity } = config;
|
||||||
logger.debug(`Spawning yarn install to create ${cwd}/yarn.lock`);
|
logger.debug(`Spawning yarn install to create ${cwd}/yarn.lock`);
|
||||||
let lockFile = null;
|
let lockFile = null;
|
||||||
|
@ -73,22 +73,37 @@ async function generateLockFile(cwd, env, config = {}) {
|
||||||
cmd = 'yarn';
|
cmd = 'yarn';
|
||||||
}
|
}
|
||||||
logger.debug(`Using yarn: ${cmd}`);
|
logger.debug(`Using yarn: ${cmd}`);
|
||||||
cmd += ' install';
|
let cmdExtras = '';
|
||||||
cmd += ' --ignore-scripts';
|
cmdExtras += ' --ignore-scripts';
|
||||||
cmd += ' --ignore-engines';
|
cmdExtras += ' --ignore-engines';
|
||||||
cmd += ' --ignore-platform';
|
cmdExtras += ' --ignore-platform';
|
||||||
cmd += process.env.YARN_MUTEX_FILE
|
cmdExtras += process.env.YARN_MUTEX_FILE
|
||||||
? ` --mutex file:${process.env.YARN_MUTEX_FILE}`
|
? ` --mutex file:${process.env.YARN_MUTEX_FILE}`
|
||||||
: ' --mutex network:31879';
|
: ' --mutex network:31879';
|
||||||
|
const installCmd = cmd + ' install' + cmdExtras;
|
||||||
// TODO: Switch to native util.promisify once using only node 8
|
// TODO: Switch to native util.promisify once using only node 8
|
||||||
({ stdout, stderr } = await exec(cmd, {
|
({ stdout, stderr } = await exec(installCmd, {
|
||||||
cwd,
|
cwd,
|
||||||
shell: true,
|
shell: true,
|
||||||
env,
|
env,
|
||||||
}));
|
}));
|
||||||
logger.debug(`yarn stdout:\n${stdout}`);
|
logger.debug(`yarn stdout:\n${stdout}`);
|
||||||
logger.debug(`yarn stderr:\n${stderr}`);
|
logger.debug(`yarn stderr:\n${stderr}`);
|
||||||
|
const lockUpdates = upgrades
|
||||||
|
.filter(upgrade => upgrade.isLockfileUpdate)
|
||||||
|
.map(upgrade => upgrade.depName);
|
||||||
|
if (lockUpdates.length) {
|
||||||
|
const updateCmd =
|
||||||
|
cmd +
|
||||||
|
' upgrade' +
|
||||||
|
lockUpdates.map(depName => ` ${depName}`).join('') +
|
||||||
|
cmdExtras;
|
||||||
|
({ stdout, stderr } = await exec(updateCmd, {
|
||||||
|
cwd,
|
||||||
|
shell: true,
|
||||||
|
env,
|
||||||
|
}));
|
||||||
|
}
|
||||||
const duration = process.hrtime(startTime);
|
const duration = process.hrtime(startTime);
|
||||||
const seconds = Math.round(duration[0] + duration[1] / 1e9);
|
const seconds = Math.round(duration[0] + duration[1] / 1e9);
|
||||||
lockFile = await fs.readFile(upath.join(cwd, 'yarn.lock'), 'utf8');
|
lockFile = await fs.readFile(upath.join(cwd, 'yarn.lock'), 'utf8');
|
||||||
|
|
|
@ -4,6 +4,7 @@ const {
|
||||||
minor,
|
minor,
|
||||||
patch,
|
patch,
|
||||||
prerelease,
|
prerelease,
|
||||||
|
satisfies,
|
||||||
valid: isVersion,
|
valid: isVersion,
|
||||||
} = require('semver');
|
} = require('semver');
|
||||||
const { parseRange } = require('semver-utils');
|
const { parseRange } = require('semver-utils');
|
||||||
|
@ -16,6 +17,12 @@ function getNewValue(currentValue, rangeStrategy, fromVersion, toVersion) {
|
||||||
if (rangeStrategy === 'pin' || isVersion(currentValue)) {
|
if (rangeStrategy === 'pin' || isVersion(currentValue)) {
|
||||||
return toVersion;
|
return toVersion;
|
||||||
}
|
}
|
||||||
|
if (rangeStrategy === 'lockfile-update') {
|
||||||
|
if (satisfies(toVersion, currentValue)) {
|
||||||
|
return currentValue;
|
||||||
|
}
|
||||||
|
return getNewValue(currentValue, 'replace', fromVersion, toVersion);
|
||||||
|
}
|
||||||
const parsedRange = parseRange(currentValue);
|
const parsedRange = parseRange(currentValue);
|
||||||
const element = parsedRange[parsedRange.length - 1];
|
const element = parsedRange[parsedRange.length - 1];
|
||||||
if (rangeStrategy === 'widen') {
|
if (rangeStrategy === 'widen') {
|
||||||
|
|
|
@ -41,7 +41,9 @@ function getPrList(config, branches) {
|
||||||
} else {
|
} else {
|
||||||
text += upgrade.depName.replace(prTitleRe, '@​$1');
|
text += upgrade.depName.replace(prTitleRe, '@​$1');
|
||||||
}
|
}
|
||||||
text += ` to \`${upgrade.newDigest || upgrade.newValue}\``;
|
text += upgrade.isLockfileUpdate
|
||||||
|
? ` to \`${upgrade.toVersion}\``
|
||||||
|
: ` to \`${upgrade.newDigest || upgrade.newValue}\``;
|
||||||
text += '\n';
|
text += '\n';
|
||||||
}
|
}
|
||||||
if (!seen.includes(text)) {
|
if (!seen.includes(text)) {
|
||||||
|
|
|
@ -13,7 +13,7 @@ module.exports = {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function lookupUpdates(config) {
|
async function lookupUpdates(config) {
|
||||||
const { depName, currentValue } = config;
|
const { depName, currentValue, lockedVersion } = config;
|
||||||
logger.trace({ dependency: depName, currentValue }, 'lookupUpdates');
|
logger.trace({ dependency: depName, currentValue }, 'lookupUpdates');
|
||||||
const {
|
const {
|
||||||
equals,
|
equals,
|
||||||
|
@ -126,10 +126,15 @@ async function lookupUpdates(config) {
|
||||||
newMajor: getMajor(fromVersion),
|
newMajor: getMajor(fromVersion),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
let filterStart = fromVersion;
|
||||||
|
if (lockedVersion && rangeStrategy === 'lockfile-update') {
|
||||||
|
// Look for versions greater than the current locked version that still satisfy the package.json range
|
||||||
|
filterStart = lockedVersion;
|
||||||
|
}
|
||||||
// Filter latest, unstable, etc
|
// Filter latest, unstable, etc
|
||||||
const filteredVersions = filterVersions(
|
const filteredVersions = filterVersions(
|
||||||
config,
|
config,
|
||||||
fromVersion,
|
filterStart,
|
||||||
dependency.latestVersion,
|
dependency.latestVersion,
|
||||||
allVersions,
|
allVersions,
|
||||||
releases
|
releases
|
||||||
|
@ -147,12 +152,19 @@ async function lookupUpdates(config) {
|
||||||
toVersion
|
toVersion
|
||||||
);
|
);
|
||||||
if (!update.newValue || update.newValue === currentValue) {
|
if (!update.newValue || update.newValue === currentValue) {
|
||||||
continue; // eslint-disable-line no-continue
|
if (!config.lockedVersion) {
|
||||||
|
continue; // eslint-disable-line no-continue
|
||||||
|
}
|
||||||
|
update.updateType = 'lockfileUpdate';
|
||||||
|
update.fromVersion = lockedVersion;
|
||||||
|
update.isSingleVersion = true;
|
||||||
}
|
}
|
||||||
update.newMajor = getMajor(toVersion);
|
update.newMajor = getMajor(toVersion);
|
||||||
update.newMinor = getMinor(toVersion);
|
update.newMinor = getMinor(toVersion);
|
||||||
update.updateType = getType(config, fromVersion, toVersion);
|
update.updateType =
|
||||||
update.isSingleVersion = !!isSingleVersion(update.newValue);
|
update.updateType || getType(config, update.fromVersion, toVersion);
|
||||||
|
update.isSingleVersion =
|
||||||
|
update.isSingleVersion || !!isSingleVersion(update.newValue);
|
||||||
if (!isVersion(update.newValue)) {
|
if (!isVersion(update.newValue)) {
|
||||||
update.isRange = true;
|
update.isRange = true;
|
||||||
}
|
}
|
||||||
|
@ -186,7 +198,7 @@ async function lookupUpdates(config) {
|
||||||
release =>
|
release =>
|
||||||
filteredVersions.length &&
|
filteredVersions.length &&
|
||||||
(filteredVersions.includes(release.version) ||
|
(filteredVersions.includes(release.version) ||
|
||||||
release.version === fromVersion)
|
release.version === filterStart)
|
||||||
);
|
);
|
||||||
} else if (!currentValue) {
|
} else if (!currentValue) {
|
||||||
res.skipReason = 'unsupported-value';
|
res.skipReason = 'unsupported-value';
|
||||||
|
@ -245,8 +257,8 @@ async function lookupUpdates(config) {
|
||||||
}
|
}
|
||||||
for (const update of res.updates) {
|
for (const update of res.updates) {
|
||||||
const { updateType, fromVersion, toVersion } = update;
|
const { updateType, fromVersion, toVersion } = update;
|
||||||
if (updateType === 'bump') {
|
if (['bump', 'lockfileUpdate'].includes(updateType)) {
|
||||||
update.isBump = true;
|
update[updateType === 'bump' ? 'isBump' : 'isLockfileUpdate'] = true;
|
||||||
if (getMajor(toVersion) > getMajor(fromVersion)) {
|
if (getMajor(toVersion) > getMajor(fromVersion)) {
|
||||||
update.updateType = 'major';
|
update.updateType = 'major';
|
||||||
} else if (
|
} else if (
|
||||||
|
@ -265,6 +277,7 @@ async function lookupUpdates(config) {
|
||||||
.filter(
|
.filter(
|
||||||
update =>
|
update =>
|
||||||
update.newValue !== config.currentValue ||
|
update.newValue !== config.currentValue ||
|
||||||
|
update.isLockfileUpdate ||
|
||||||
(update.newDigest && !update.newDigest.startsWith(config.currentDigest))
|
(update.newDigest && !update.newDigest.startsWith(config.currentDigest))
|
||||||
);
|
);
|
||||||
if (res.updates.some(update => update.updateType === 'pin')) {
|
if (res.updates.some(update => update.updateType === 'pin')) {
|
||||||
|
@ -301,6 +314,9 @@ function getType(config, fromVersion, toVersion) {
|
||||||
function getBucket(config, update) {
|
function getBucket(config, update) {
|
||||||
const { separateMajorMinor, separateMultipleMajor } = config;
|
const { separateMajorMinor, separateMultipleMajor } = config;
|
||||||
const { updateType, newMajor } = update;
|
const { updateType, newMajor } = update;
|
||||||
|
if (updateType === 'lockfileUpdate') {
|
||||||
|
return updateType;
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
!separateMajorMinor ||
|
!separateMajorMinor ||
|
||||||
config.major.automerge === true ||
|
config.major.automerge === true ||
|
||||||
|
|
|
@ -29,6 +29,33 @@ describe('generateLockFile', () => {
|
||||||
expect(res.error).not.toBeDefined();
|
expect(res.error).not.toBeDefined();
|
||||||
expect(res.lockFile).toEqual('package-lock-contents');
|
expect(res.lockFile).toEqual('package-lock-contents');
|
||||||
});
|
});
|
||||||
|
it('performs lock file updates', async () => {
|
||||||
|
getInstalledPath.mockReturnValueOnce('node_modules/npm');
|
||||||
|
exec.mockReturnValueOnce({
|
||||||
|
stdout: '',
|
||||||
|
stderror: '',
|
||||||
|
});
|
||||||
|
exec.mockReturnValueOnce({
|
||||||
|
stdout: '',
|
||||||
|
stderror: '',
|
||||||
|
});
|
||||||
|
fs.readFile = jest.fn(() => 'package-lock-contents');
|
||||||
|
const skipInstalls = true;
|
||||||
|
const updates = [
|
||||||
|
{ depName: 'some-dep', toVersion: '1.0.1', isLockfileUpdate: true },
|
||||||
|
];
|
||||||
|
const res = await npmHelper.generateLockFile(
|
||||||
|
'some-dir',
|
||||||
|
{},
|
||||||
|
'package-lock.json',
|
||||||
|
skipInstalls,
|
||||||
|
null,
|
||||||
|
updates
|
||||||
|
);
|
||||||
|
expect(fs.readFile.mock.calls.length).toEqual(1);
|
||||||
|
expect(res.error).not.toBeDefined();
|
||||||
|
expect(res.lockFile).toEqual('package-lock-contents');
|
||||||
|
});
|
||||||
it('performs full install', async () => {
|
it('performs full install', async () => {
|
||||||
getInstalledPath.mockReturnValueOnce('node_modules/npm');
|
getInstalledPath.mockReturnValueOnce('node_modules/npm');
|
||||||
exec.mockReturnValueOnce({
|
exec.mockReturnValueOnce({
|
||||||
|
|
|
@ -22,6 +22,22 @@ describe('generateLockFile', () => {
|
||||||
expect(fs.readFile.mock.calls.length).toEqual(1);
|
expect(fs.readFile.mock.calls.length).toEqual(1);
|
||||||
expect(res.lockFile).toEqual('package-lock-contents');
|
expect(res.lockFile).toEqual('package-lock-contents');
|
||||||
});
|
});
|
||||||
|
it('performs lock file updates', async () => {
|
||||||
|
getInstalledPath.mockReturnValueOnce('node_modules/yarn');
|
||||||
|
exec.mockReturnValueOnce({
|
||||||
|
stdout: '',
|
||||||
|
stderror: '',
|
||||||
|
});
|
||||||
|
exec.mockReturnValueOnce({
|
||||||
|
stdout: '',
|
||||||
|
stderror: '',
|
||||||
|
});
|
||||||
|
fs.readFile = jest.fn(() => 'package-lock-contents');
|
||||||
|
const res = await yarnHelper.generateLockFile('some-dir', {}, {}, [
|
||||||
|
{ depName: 'some-dep', isLockfileUpdate: true },
|
||||||
|
]);
|
||||||
|
expect(res.lockFile).toEqual('package-lock-contents');
|
||||||
|
});
|
||||||
it('catches errors', async () => {
|
it('catches errors', async () => {
|
||||||
getInstalledPath.mockReturnValueOnce('node_modules/yarn');
|
getInstalledPath.mockReturnValueOnce('node_modules/yarn');
|
||||||
exec.mockReturnValueOnce({
|
exec.mockReturnValueOnce({
|
||||||
|
|
|
@ -1143,6 +1143,48 @@ Array [
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`workers/repository/process/lookup .lookupUpdates() supports lock file updates mixed with regular updates 1`] = `
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"canBeUnpublished": false,
|
||||||
|
"fromVersion": "0.4.0",
|
||||||
|
"isLockfileUpdate": true,
|
||||||
|
"isRange": true,
|
||||||
|
"isSingleVersion": true,
|
||||||
|
"newMajor": 0,
|
||||||
|
"newMinor": 4,
|
||||||
|
"newValue": "^0.4.0",
|
||||||
|
"releaseTimestamp": "2011-06-10T17:20:04.719Z",
|
||||||
|
"toVersion": "0.4.4",
|
||||||
|
"updateType": "minor",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"canBeUnpublished": false,
|
||||||
|
"fromVersion": "0.4.4",
|
||||||
|
"isRange": true,
|
||||||
|
"isSingleVersion": false,
|
||||||
|
"newMajor": 0,
|
||||||
|
"newMinor": 9,
|
||||||
|
"newValue": "^0.9.0",
|
||||||
|
"releaseTimestamp": "2013-09-04T17:07:22.948Z",
|
||||||
|
"toVersion": "0.9.7",
|
||||||
|
"updateType": "minor",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"canBeUnpublished": false,
|
||||||
|
"fromVersion": "0.4.4",
|
||||||
|
"isRange": true,
|
||||||
|
"isSingleVersion": false,
|
||||||
|
"newMajor": 1,
|
||||||
|
"newMinor": 4,
|
||||||
|
"newValue": "^1.0.0",
|
||||||
|
"releaseTimestamp": "2015-05-17T04:25:07.299Z",
|
||||||
|
"toVersion": "1.4.1",
|
||||||
|
"updateType": "major",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`workers/repository/process/lookup .lookupUpdates() supports majorgte updates 1`] = `
|
exports[`workers/repository/process/lookup .lookupUpdates() supports majorgte updates 1`] = `
|
||||||
Array [
|
Array [
|
||||||
Object {
|
Object {
|
||||||
|
|
|
@ -54,6 +54,17 @@ describe('workers/repository/process/lookup', () => {
|
||||||
.reply(200, qJson);
|
.reply(200, qJson);
|
||||||
expect((await lookup.lookupUpdates(config)).updates).toMatchSnapshot();
|
expect((await lookup.lookupUpdates(config)).updates).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
it('supports lock file updates mixed with regular updates', async () => {
|
||||||
|
config.currentValue = '^0.4.0';
|
||||||
|
config.rangeStrategy = 'lockfile-update';
|
||||||
|
config.depName = 'q';
|
||||||
|
config.purl = 'pkg:npm/q';
|
||||||
|
config.lockedVersion = '0.4.0';
|
||||||
|
nock('https://registry.npmjs.org')
|
||||||
|
.get('/q')
|
||||||
|
.reply(200, qJson);
|
||||||
|
expect((await lookup.lookupUpdates(config)).updates).toMatchSnapshot();
|
||||||
|
});
|
||||||
it('returns multiple updates if grouping but separateMajorMinor=true', async () => {
|
it('returns multiple updates if grouping but separateMajorMinor=true', async () => {
|
||||||
config.groupName = 'somegroup';
|
config.groupName = 'somegroup';
|
||||||
config.currentValue = '0.4.0';
|
config.currentValue = '0.4.0';
|
||||||
|
|
|
@ -10,7 +10,7 @@ Array [
|
||||||
"binarySource": "bundled",
|
"binarySource": "bundled",
|
||||||
"branchName": "{{{branchPrefix}}}{{{managerBranchPrefix}}}{{{branchTopic}}}",
|
"branchName": "{{{branchPrefix}}}{{{managerBranchPrefix}}}{{{branchTopic}}}",
|
||||||
"branchPrefix": "renovate/",
|
"branchPrefix": "renovate/",
|
||||||
"branchTopic": "{{{depNameSanitized}}}-{{{newMajor}}}{{#if isPatch}}.{{{newMinor}}}{{/if}}.x",
|
"branchTopic": "{{{depNameSanitized}}}-{{{newMajor}}}{{#if isPatch}}.{{{newMinor}}}{{/if}}.x{{#if isLockfileUpdate}}-lockfile{{/if}}",
|
||||||
"bumpVersion": null,
|
"bumpVersion": null,
|
||||||
"commitBody": null,
|
"commitBody": null,
|
||||||
"commitMessage": "{{{commitMessagePrefix}}} {{{commitMessageAction}}} {{{commitMessageTopic}}} {{{commitMessageExtra}}} {{{commitMessageSuffix}}}",
|
"commitMessage": "{{{commitMessagePrefix}}} {{{commitMessageAction}}} {{{commitMessageTopic}}} {{{commitMessageExtra}}} {{{commitMessageSuffix}}}",
|
||||||
|
@ -107,7 +107,7 @@ Array [
|
||||||
"binarySource": "bundled",
|
"binarySource": "bundled",
|
||||||
"branchName": "{{{branchPrefix}}}{{{managerBranchPrefix}}}{{{branchTopic}}}",
|
"branchName": "{{{branchPrefix}}}{{{managerBranchPrefix}}}{{{branchTopic}}}",
|
||||||
"branchPrefix": "renovate/",
|
"branchPrefix": "renovate/",
|
||||||
"branchTopic": "{{{depNameSanitized}}}-{{{newMajor}}}{{#if isPatch}}.{{{newMinor}}}{{/if}}.x",
|
"branchTopic": "{{{depNameSanitized}}}-{{{newMajor}}}{{#if isPatch}}.{{{newMinor}}}{{/if}}.x{{#if isLockfileUpdate}}-lockfile{{/if}}",
|
||||||
"bumpVersion": null,
|
"bumpVersion": null,
|
||||||
"commitBody": null,
|
"commitBody": null,
|
||||||
"commitMessage": "{{{commitMessagePrefix}}} {{{commitMessageAction}}} {{{commitMessageTopic}}} {{{commitMessageExtra}}} {{{commitMessageSuffix}}}",
|
"commitMessage": "{{{commitMessagePrefix}}} {{{commitMessageAction}}} {{{commitMessageTopic}}} {{{commitMessageExtra}}} {{{commitMessageSuffix}}}",
|
||||||
|
@ -301,7 +301,7 @@ Array [
|
||||||
"binarySource": "bundled",
|
"binarySource": "bundled",
|
||||||
"branchName": "{{{branchPrefix}}}{{{managerBranchPrefix}}}{{{branchTopic}}}",
|
"branchName": "{{{branchPrefix}}}{{{managerBranchPrefix}}}{{{branchTopic}}}",
|
||||||
"branchPrefix": "renovate/",
|
"branchPrefix": "renovate/",
|
||||||
"branchTopic": "{{{depNameSanitized}}}-{{{newMajor}}}{{#if isPatch}}.{{{newMinor}}}{{/if}}.x",
|
"branchTopic": "{{{depNameSanitized}}}-{{{newMajor}}}{{#if isPatch}}.{{{newMinor}}}{{/if}}.x{{#if isLockfileUpdate}}-lockfile{{/if}}",
|
||||||
"bumpVersion": null,
|
"bumpVersion": null,
|
||||||
"commitBody": null,
|
"commitBody": null,
|
||||||
"commitMessage": "{{{commitMessagePrefix}}} {{{commitMessageAction}}} {{{commitMessageTopic}}} {{{commitMessageExtra}}} {{{commitMessageSuffix}}}",
|
"commitMessage": "{{{commitMessagePrefix}}} {{{commitMessageAction}}} {{{commitMessageTopic}}} {{{commitMessageExtra}}} {{{commitMessageSuffix}}}",
|
||||||
|
@ -495,7 +495,7 @@ Array [
|
||||||
"binarySource": "bundled",
|
"binarySource": "bundled",
|
||||||
"branchName": "{{{branchPrefix}}}{{{managerBranchPrefix}}}{{{branchTopic}}}",
|
"branchName": "{{{branchPrefix}}}{{{managerBranchPrefix}}}{{{branchTopic}}}",
|
||||||
"branchPrefix": "renovate/",
|
"branchPrefix": "renovate/",
|
||||||
"branchTopic": "{{{depNameSanitized}}}-{{{newMajor}}}{{#if isPatch}}.{{{newMinor}}}{{/if}}.x",
|
"branchTopic": "{{{depNameSanitized}}}-{{{newMajor}}}{{#if isPatch}}.{{{newMinor}}}{{/if}}.x{{#if isLockfileUpdate}}-lockfile{{/if}}",
|
||||||
"bumpVersion": null,
|
"bumpVersion": null,
|
||||||
"commitBody": null,
|
"commitBody": null,
|
||||||
"commitMessage": "{{{commitMessagePrefix}}} {{{commitMessageAction}}} {{{commitMessageTopic}}} {{{commitMessageExtra}}} {{{commitMessageSuffix}}}",
|
"commitMessage": "{{{commitMessagePrefix}}} {{{commitMessageAction}}} {{{commitMessageTopic}}} {{{commitMessageExtra}}} {{{commitMessageSuffix}}}",
|
||||||
|
@ -592,7 +592,7 @@ Array [
|
||||||
"binarySource": "bundled",
|
"binarySource": "bundled",
|
||||||
"branchName": "{{{branchPrefix}}}{{{managerBranchPrefix}}}{{{branchTopic}}}",
|
"branchName": "{{{branchPrefix}}}{{{managerBranchPrefix}}}{{{branchTopic}}}",
|
||||||
"branchPrefix": "renovate/",
|
"branchPrefix": "renovate/",
|
||||||
"branchTopic": "{{{depNameSanitized}}}-{{{newMajor}}}{{#if isPatch}}.{{{newMinor}}}{{/if}}.x",
|
"branchTopic": "{{{depNameSanitized}}}-{{{newMajor}}}{{#if isPatch}}.{{{newMinor}}}{{/if}}.x{{#if isLockfileUpdate}}-lockfile{{/if}}",
|
||||||
"bumpVersion": null,
|
"bumpVersion": null,
|
||||||
"commitBody": null,
|
"commitBody": null,
|
||||||
"commitMessage": "{{{commitMessagePrefix}}} {{{commitMessageAction}}} {{{commitMessageTopic}}} {{{commitMessageExtra}}} {{{commitMessageSuffix}}}",
|
"commitMessage": "{{{commitMessagePrefix}}} {{{commitMessageAction}}} {{{commitMessageTopic}}} {{{commitMessageExtra}}} {{{commitMessageSuffix}}}",
|
||||||
|
@ -689,7 +689,7 @@ Array [
|
||||||
"binarySource": "bundled",
|
"binarySource": "bundled",
|
||||||
"branchName": "{{{branchPrefix}}}{{{managerBranchPrefix}}}{{{branchTopic}}}",
|
"branchName": "{{{branchPrefix}}}{{{managerBranchPrefix}}}{{{branchTopic}}}",
|
||||||
"branchPrefix": "renovate/",
|
"branchPrefix": "renovate/",
|
||||||
"branchTopic": "{{{depNameSanitized}}}-{{{newMajor}}}{{#if isPatch}}.{{{newMinor}}}{{/if}}.x",
|
"branchTopic": "{{{depNameSanitized}}}-{{{newMajor}}}{{#if isPatch}}.{{{newMinor}}}{{/if}}.x{{#if isLockfileUpdate}}-lockfile{{/if}}",
|
||||||
"bumpVersion": null,
|
"bumpVersion": null,
|
||||||
"commitBody": null,
|
"commitBody": null,
|
||||||
"commitMessage": "{{{commitMessagePrefix}}} {{{commitMessageAction}}} {{{commitMessageTopic}}} {{{commitMessageExtra}}} {{{commitMessageSuffix}}}",
|
"commitMessage": "{{{commitMessagePrefix}}} {{{commitMessageAction}}} {{{commitMessageTopic}}} {{{commitMessageExtra}}} {{{commitMessageSuffix}}}",
|
||||||
|
|
|
@ -758,6 +758,7 @@ Behaviour:
|
||||||
- `bump` = e.g. bump the range even if the new version satisifies the existing range, e.g. `^1.0.0` -> `^1.1.0`
|
- `bump` = e.g. bump the range even if the new version satisifies the existing range, e.g. `^1.0.0` -> `^1.1.0`
|
||||||
- `replace` = Replace the range with a newer one if the new version falls outside it, e.g. `^1.0.0` -> `^2.0.0`
|
- `replace` = Replace the range with a newer one if the new version falls outside it, e.g. `^1.0.0` -> `^2.0.0`
|
||||||
- `widen` = Widen the range with newer one, e.g. `^1.0.0` -> `^1.0.0 || ^2.0.0`
|
- `widen` = Widen the range with newer one, e.g. `^1.0.0` -> `^1.0.0 || ^2.0.0`
|
||||||
|
- `update-lockfile` = Update the lock file when in-range updates are available, otherwise 'replace' for updates out of range
|
||||||
|
|
||||||
Renovate's "auto" strategy works like this for npm:
|
Renovate's "auto" strategy works like this for npm:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue