2017-03-26 04:08:01 +00:00
|
|
|
const _ = require('lodash');
|
2018-04-10 03:20:46 +00:00
|
|
|
const {
|
|
|
|
getMajor,
|
|
|
|
getMinor,
|
|
|
|
getPatch,
|
|
|
|
isGreaterThan,
|
|
|
|
isRange,
|
|
|
|
isStable,
|
|
|
|
isUnstable,
|
|
|
|
isPinnedVersion,
|
|
|
|
matchesSemver,
|
|
|
|
maxSatisfyingVersion,
|
|
|
|
minSatisfyingVersion,
|
|
|
|
parseRange,
|
|
|
|
parseVersion,
|
|
|
|
stringifyRange,
|
|
|
|
} = require('../../util/semver');
|
2017-08-06 13:38:10 +00:00
|
|
|
const moment = require('moment');
|
2017-01-07 07:22:48 +00:00
|
|
|
|
2017-01-11 13:33:32 +00:00
|
|
|
module.exports = {
|
2017-01-15 22:56:09 +00:00
|
|
|
determineUpgrades,
|
2017-01-17 11:46:32 +00:00
|
|
|
isPastLatest,
|
2017-01-11 12:19:59 +00:00
|
|
|
};
|
|
|
|
|
2017-06-27 11:44:03 +00:00
|
|
|
function determineUpgrades(npmDep, config) {
|
2018-01-28 13:51:55 +00:00
|
|
|
const dependency = npmDep.name;
|
|
|
|
logger.debug({ dependency }, `determineUpgrades()`);
|
2017-12-04 14:07:35 +00:00
|
|
|
logger.trace({ npmDep, config });
|
2017-07-04 10:39:28 +00:00
|
|
|
const result = {
|
2017-07-05 05:12:25 +00:00
|
|
|
type: 'warning',
|
2017-07-04 10:39:28 +00:00
|
|
|
};
|
2018-03-07 06:41:10 +00:00
|
|
|
const { lockedVersion, pinVersions, allowedVersions } = config;
|
2017-09-15 17:46:25 +00:00
|
|
|
const { versions } = npmDep;
|
2017-01-17 11:46:32 +00:00
|
|
|
if (!versions || Object.keys(versions).length === 0) {
|
2017-07-04 10:39:28 +00:00
|
|
|
result.message = `No versions returned from registry for this package`;
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.warn({ dependency }, result.message);
|
2017-07-04 10:39:28 +00:00
|
|
|
return [result];
|
2017-01-12 16:04:25 +00:00
|
|
|
}
|
2018-03-30 07:38:17 +00:00
|
|
|
let versionList = Object.keys(versions);
|
2017-01-12 16:04:25 +00:00
|
|
|
const allUpgrades = {};
|
2018-03-07 06:41:10 +00:00
|
|
|
let { currentVersion } = config;
|
2018-03-30 07:38:17 +00:00
|
|
|
// filter out versions past latest
|
|
|
|
const currentIsPastLatest = isPastLatest(
|
|
|
|
npmDep,
|
2018-04-10 03:20:46 +00:00
|
|
|
minSatisfyingVersion(versionList, currentVersion)
|
2018-03-30 07:38:17 +00:00
|
|
|
);
|
|
|
|
if (currentIsPastLatest) {
|
|
|
|
logger.debug({ name: npmDep.name, currentVersion }, 'currentIsPastLatest');
|
|
|
|
}
|
|
|
|
versionList = versionList.filter(
|
|
|
|
version =>
|
|
|
|
currentIsPastLatest || // if current is past latest then don't filter any
|
|
|
|
config.respectLatest === false || // if user has configured respectLatest to false
|
|
|
|
isPastLatest(npmDep, version) === false // if the version is less than or equal to latest
|
|
|
|
);
|
2018-03-07 06:41:10 +00:00
|
|
|
let rangeOperator;
|
2018-04-10 03:20:46 +00:00
|
|
|
if (config.upgradeInRange && isRange(currentVersion)) {
|
2018-03-07 06:41:10 +00:00
|
|
|
logger.debug({ currentVersion }, 'upgradeInRange is true');
|
2018-04-10 03:20:46 +00:00
|
|
|
const parsedRange = parseRange(currentVersion);
|
2018-03-07 06:41:10 +00:00
|
|
|
if (parsedRange && parsedRange.length === 1) {
|
|
|
|
const [range] = parsedRange;
|
|
|
|
if (range.major && range.minor && range.patch) {
|
|
|
|
if (range.operator === '^' || range.operator === '~') {
|
|
|
|
logger.debug('Applying upgradeInRange');
|
|
|
|
currentVersion = `${range.major}.${range.minor}.${range.patch}`;
|
2018-03-20 06:20:14 +00:00
|
|
|
currentVersion += range.release ? `-${range.release}` : '';
|
|
|
|
logger.debug({ currentVersion }, 'upgradeInRange currentVersion');
|
2018-03-07 06:41:10 +00:00
|
|
|
rangeOperator = range.operator;
|
|
|
|
} else {
|
|
|
|
logger.debug({ currentVersion }, 'Unsupported range type');
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
logger.debug({ currentVersion }, 'Range is not fully specified');
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
logger.debug({ currentVersion }, 'Skipping complex range');
|
|
|
|
}
|
|
|
|
}
|
2017-04-13 10:44:34 +00:00
|
|
|
let changeLogFromVersion = currentVersion;
|
2017-01-12 16:04:25 +00:00
|
|
|
// Check for a current range and pin it
|
|
|
|
if (isRange(currentVersion)) {
|
2018-01-26 09:13:21 +00:00
|
|
|
let newVersion;
|
2018-04-10 03:20:46 +00:00
|
|
|
if (pinVersions && lockedVersion && isPinnedVersion(lockedVersion)) {
|
2018-01-26 09:13:21 +00:00
|
|
|
newVersion = lockedVersion;
|
|
|
|
} else {
|
|
|
|
// Pin ranges to their maximum satisfying version
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.debug({ dependency }, 'currentVersion is range, not locked');
|
2018-04-10 03:20:46 +00:00
|
|
|
const maxSatisfying = maxSatisfyingVersion(versionList, currentVersion);
|
2018-01-26 09:13:21 +00:00
|
|
|
if (!maxSatisfying) {
|
|
|
|
result.message = `No satisfying version found for existing dependency range "${currentVersion}"`;
|
|
|
|
logger.info(
|
2018-01-28 13:51:55 +00:00
|
|
|
{ dependency, currentVersion },
|
2018-01-26 09:13:21 +00:00
|
|
|
`Warning: ${result.message}`
|
|
|
|
);
|
|
|
|
return [result];
|
|
|
|
}
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.debug({ dependency, maxSatisfying });
|
2018-01-26 09:13:21 +00:00
|
|
|
newVersion = maxSatisfying;
|
2017-12-06 17:53:55 +00:00
|
|
|
}
|
2018-01-26 09:13:21 +00:00
|
|
|
|
2017-01-13 09:06:38 +00:00
|
|
|
allUpgrades.pin = {
|
2017-07-05 05:12:25 +00:00
|
|
|
type: 'pin',
|
2017-06-25 05:36:13 +00:00
|
|
|
isPin: true,
|
2018-01-26 09:13:21 +00:00
|
|
|
newVersion,
|
2018-04-10 03:20:46 +00:00
|
|
|
newVersionMajor: getMajor(newVersion),
|
2017-01-13 09:06:38 +00:00
|
|
|
};
|
2018-01-26 09:13:21 +00:00
|
|
|
changeLogFromVersion = newVersion;
|
2018-03-07 06:41:10 +00:00
|
|
|
} else if (versionList.indexOf(currentVersion) === -1 && !rangeOperator) {
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.debug({ dependency }, 'Cannot find currentVersion');
|
2017-12-04 14:07:35 +00:00
|
|
|
try {
|
2018-04-10 03:20:46 +00:00
|
|
|
const rollbackVersion = maxSatisfyingVersion(
|
2017-12-04 14:07:35 +00:00
|
|
|
versionList,
|
|
|
|
`<${currentVersion}`
|
|
|
|
);
|
|
|
|
allUpgrades.rollback = {
|
|
|
|
type: 'rollback',
|
|
|
|
isRollback: true,
|
|
|
|
newVersion: rollbackVersion,
|
2018-04-10 03:20:46 +00:00
|
|
|
newVersionMajor: getMajor(rollbackVersion),
|
2017-12-04 14:07:35 +00:00
|
|
|
semanticCommitType: 'fix',
|
2018-04-17 06:39:26 +00:00
|
|
|
commitMessageAction: 'Roll back',
|
2017-12-04 14:07:35 +00:00
|
|
|
branchName:
|
2018-01-24 06:18:11 +00:00
|
|
|
'{{{branchPrefix}}}rollback-{{{depNameSanitized}}}-{{{newVersionMajor}}}.x',
|
2017-12-04 14:07:35 +00:00
|
|
|
};
|
|
|
|
} catch (err) /* istanbul ignore next */ {
|
|
|
|
logger.info(
|
2018-01-28 13:51:55 +00:00
|
|
|
{ dependency, currentVersion },
|
2017-12-04 14:07:35 +00:00
|
|
|
'Warning: current version is missing from npm registry and cannot roll back'
|
|
|
|
);
|
|
|
|
}
|
2017-01-12 16:04:25 +00:00
|
|
|
}
|
2017-03-26 04:08:01 +00:00
|
|
|
_(versionList)
|
|
|
|
// Filter out older versions as we can't upgrade to those
|
2018-04-10 03:20:46 +00:00
|
|
|
.filter(version => isGreaterThan(version, changeLogFromVersion))
|
2018-03-02 22:10:42 +00:00
|
|
|
// fillter out non-allowed versions if preference is set
|
|
|
|
.reject(
|
2018-04-10 03:20:46 +00:00
|
|
|
version => allowedVersions && !matchesSemver(version, allowedVersions)
|
2018-03-02 22:10:42 +00:00
|
|
|
)
|
2017-03-26 04:08:01 +00:00
|
|
|
// Ignore unstable versions, unless the current version is unstable
|
2017-04-21 08:12:41 +00:00
|
|
|
.reject(
|
|
|
|
version =>
|
|
|
|
config.ignoreUnstable &&
|
2018-04-10 03:20:46 +00:00
|
|
|
isStable(changeLogFromVersion) &&
|
|
|
|
isUnstable(version)
|
2017-04-21 08:12:41 +00:00
|
|
|
)
|
2018-01-27 15:18:18 +00:00
|
|
|
// Do not jump to a new major unstable just because the current is unstable
|
|
|
|
.reject(
|
|
|
|
version =>
|
|
|
|
config.ignoreUnstable &&
|
2018-04-10 03:20:46 +00:00
|
|
|
isUnstable(version) &&
|
|
|
|
getMajor(version) > getMajor(changeLogFromVersion)
|
2018-01-27 15:18:18 +00:00
|
|
|
)
|
2017-03-26 04:08:01 +00:00
|
|
|
// Loop through all possible versions
|
2017-04-21 08:12:41 +00:00
|
|
|
.forEach(newVersion => {
|
2017-01-12 16:04:25 +00:00
|
|
|
// Group by major versions
|
2018-04-10 03:20:46 +00:00
|
|
|
const newVersionMajor = getMajor(newVersion);
|
|
|
|
const newVersionMinor = getMinor(newVersion);
|
2018-02-27 13:50:09 +00:00
|
|
|
const hasPatchOnlyAutomerge =
|
|
|
|
config.patch &&
|
|
|
|
config.patch.automerge === true &&
|
|
|
|
(config.minor && config.minor.automerge !== true);
|
2017-08-01 15:10:53 +00:00
|
|
|
let type;
|
2018-04-10 03:20:46 +00:00
|
|
|
if (newVersionMajor > getMajor(changeLogFromVersion)) {
|
2017-08-01 15:10:53 +00:00
|
|
|
type = 'major';
|
|
|
|
} else if (
|
2018-04-10 03:20:46 +00:00
|
|
|
newVersionMinor === getMinor(changeLogFromVersion) &&
|
2018-02-27 13:50:09 +00:00
|
|
|
(config.separatePatchReleases || hasPatchOnlyAutomerge)
|
2017-08-01 15:10:53 +00:00
|
|
|
) {
|
|
|
|
// Only use patch if configured to
|
|
|
|
type = 'patch';
|
|
|
|
} else {
|
|
|
|
type = 'minor';
|
|
|
|
}
|
|
|
|
let upgradeKey;
|
|
|
|
if (
|
|
|
|
!config.separateMajorReleases ||
|
|
|
|
config.groupName ||
|
2017-08-24 10:39:23 +00:00
|
|
|
config.major.automerge === true
|
2017-08-01 15:10:53 +00:00
|
|
|
) {
|
|
|
|
// If we're not separating releases then we use a common lookup key
|
|
|
|
upgradeKey = 'latest';
|
2017-11-10 03:57:07 +00:00
|
|
|
} else if (!config.multipleMajorPrs && type === 'major') {
|
|
|
|
upgradeKey = 'major';
|
2017-08-01 15:10:53 +00:00
|
|
|
} else if (type === 'patch') {
|
2018-01-24 06:18:11 +00:00
|
|
|
upgradeKey = `{{{newVersionMajor}}}.{{{newVersionMinor}}}`;
|
2017-08-01 15:10:53 +00:00
|
|
|
} else {
|
|
|
|
// Use major version as lookup key
|
|
|
|
upgradeKey = newVersionMajor;
|
|
|
|
}
|
2017-01-12 16:04:25 +00:00
|
|
|
// Save this, if it's a new major version or greater than the previous greatest
|
2017-04-21 08:12:41 +00:00
|
|
|
if (
|
|
|
|
!allUpgrades[upgradeKey] ||
|
2018-04-10 03:20:46 +00:00
|
|
|
isGreaterThan(newVersion, allUpgrades[upgradeKey].newVersion)
|
2017-04-21 08:12:41 +00:00
|
|
|
) {
|
2017-04-13 10:44:34 +00:00
|
|
|
const changeLogToVersion = newVersion;
|
2017-04-15 10:44:50 +00:00
|
|
|
allUpgrades[upgradeKey] = {
|
2017-07-05 05:12:25 +00:00
|
|
|
type,
|
2017-01-12 16:04:25 +00:00
|
|
|
newVersion,
|
|
|
|
newVersionMajor,
|
2017-07-27 20:17:28 +00:00
|
|
|
newVersionMinor,
|
2017-04-13 10:44:34 +00:00
|
|
|
changeLogFromVersion,
|
|
|
|
changeLogToVersion,
|
2017-01-12 16:04:25 +00:00
|
|
|
};
|
2017-07-05 05:12:25 +00:00
|
|
|
if (type === 'major') {
|
2017-06-25 05:36:13 +00:00
|
|
|
allUpgrades[upgradeKey].isMajor = true;
|
2017-07-05 05:12:25 +00:00
|
|
|
} else if (type === 'minor') {
|
2017-06-25 05:36:13 +00:00
|
|
|
allUpgrades[upgradeKey].isMinor = true;
|
2017-07-27 20:17:28 +00:00
|
|
|
} else if (type === 'patch') {
|
|
|
|
allUpgrades[upgradeKey].isPatch = true;
|
2017-06-25 05:36:13 +00:00
|
|
|
}
|
2017-01-07 21:00:32 +00:00
|
|
|
}
|
2017-03-26 04:08:01 +00:00
|
|
|
});
|
2017-01-12 16:04:25 +00:00
|
|
|
// Return only the values - we don't need the keys anymore
|
2018-01-24 07:43:27 +00:00
|
|
|
let upgrades = Object.keys(allUpgrades).map(key => allUpgrades[key]);
|
2017-08-06 13:38:10 +00:00
|
|
|
for (const upgrade of upgrades) {
|
2018-02-08 05:50:10 +00:00
|
|
|
const version = versions[upgrade.newVersion];
|
|
|
|
const elapsed = version ? moment().diff(moment(version.time), 'days') : 999;
|
2017-08-06 13:38:10 +00:00
|
|
|
upgrade.unpublishable = elapsed > 0;
|
|
|
|
}
|
2017-04-13 19:22:24 +00:00
|
|
|
|
|
|
|
// Return now if array is empty, or we can keep pinned version upgrades
|
|
|
|
if (upgrades.length === 0 || config.pinVersions || !isRange(currentVersion)) {
|
2018-03-07 06:41:10 +00:00
|
|
|
return rangeOperator
|
|
|
|
? upgrades.map(upgrade => ({
|
|
|
|
...upgrade,
|
|
|
|
newVersion: `${rangeOperator}${upgrade.newVersion}`,
|
|
|
|
isRange: true,
|
|
|
|
}))
|
|
|
|
: upgrades;
|
2017-04-13 19:22:24 +00:00
|
|
|
}
|
|
|
|
|
2018-03-27 19:57:02 +00:00
|
|
|
logger.debug({ dependency }, 'User wants ranges - filtering out pins');
|
2018-01-24 07:43:27 +00:00
|
|
|
upgrades = upgrades.filter(upgrade => upgrade.type !== 'pin');
|
|
|
|
|
|
|
|
// Return empty if all results were pins
|
|
|
|
if (!upgrades.length) {
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.debug({ dependency }, 'No upgrades left - returning');
|
2018-01-24 07:43:27 +00:00
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if it's a range type we support
|
2018-04-10 03:20:46 +00:00
|
|
|
const semverParsed = parseRange(currentVersion);
|
2018-01-24 07:43:27 +00:00
|
|
|
// Check the "last" part, which is also the first and only if it's a simple semver
|
2018-01-24 08:44:38 +00:00
|
|
|
const [lastSemver] = semverParsed.slice(-1);
|
|
|
|
const secondLastSemver = semverParsed[semverParsed.length - 2];
|
2017-04-13 19:22:24 +00:00
|
|
|
if (semverParsed.length > 1) {
|
2018-01-24 08:44:38 +00:00
|
|
|
if (lastSemver.operator === '<' || lastSemver.operator === '<=') {
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.debug({ dependency }, 'Found less than range');
|
2018-01-24 08:44:38 +00:00
|
|
|
} else if (secondLastSemver.operator === '||') {
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.debug({ dependency }, 'Found an OR range');
|
2018-01-24 10:23:59 +00:00
|
|
|
} else if (secondLastSemver.operator === '-') {
|
|
|
|
logger.info(
|
2018-01-28 13:51:55 +00:00
|
|
|
{ dependency, currentVersion, upgrades, semverParsed },
|
2018-01-24 10:23:59 +00:00
|
|
|
'Found a hyphen range'
|
|
|
|
);
|
2018-01-24 08:44:38 +00:00
|
|
|
} else {
|
2018-01-24 07:43:27 +00:00
|
|
|
// We don't know how to support complex semver ranges, so don't upgrade
|
|
|
|
result.message = `Complex semver ranges such as "${currentVersion}" are not yet supported so will be skipped`;
|
|
|
|
logger.info(
|
2018-01-28 13:51:55 +00:00
|
|
|
{ dependency, upgrades, semverParsed },
|
2018-01-24 07:43:27 +00:00
|
|
|
'Semver warning: ' + result.message
|
|
|
|
);
|
|
|
|
return [result];
|
|
|
|
}
|
2017-04-13 19:22:24 +00:00
|
|
|
}
|
|
|
|
// Loop through all upgrades and convert to ranges
|
2017-07-04 10:39:28 +00:00
|
|
|
const rangedUpgrades = _(upgrades)
|
2017-08-03 06:01:20 +00:00
|
|
|
.map(upgrade => ({ ...upgrade, ...{ isRange: true } }))
|
2017-04-21 08:12:41 +00:00
|
|
|
.map(upgrade => {
|
2018-04-10 03:20:46 +00:00
|
|
|
const { major, minor } = parseVersion(upgrade.newVersion);
|
2018-01-24 14:26:37 +00:00
|
|
|
const canReplace = config.versionStrategy !== 'widen';
|
|
|
|
const forceReplace = config.versionStrategy === 'replace';
|
|
|
|
const canWiden = config.versionStrategy !== 'replace';
|
|
|
|
const forceWiden = config.versionStrategy === 'widen';
|
|
|
|
if (
|
|
|
|
lastSemver.operator === '~' &&
|
|
|
|
canReplace &&
|
|
|
|
(semverParsed.length === 1 || forceReplace)
|
|
|
|
) {
|
2017-04-21 08:12:41 +00:00
|
|
|
// Utilise that a.b is the same as ~a.b.0
|
2018-04-10 03:20:46 +00:00
|
|
|
const minSatisfying = minSatisfyingVersion(
|
2017-04-21 08:12:41 +00:00
|
|
|
versionList,
|
2017-04-21 08:25:49 +00:00
|
|
|
`${major}.${minor}`
|
2017-04-21 08:12:41 +00:00
|
|
|
);
|
|
|
|
// Add a tilde before that version number
|
2017-08-03 06:01:20 +00:00
|
|
|
return { ...upgrade, ...{ newVersion: `~${minSatisfying}` } };
|
2018-01-24 14:26:37 +00:00
|
|
|
} else if (
|
|
|
|
lastSemver.operator === '~' &&
|
|
|
|
canWiden &&
|
|
|
|
(semverParsed.length > 1 || forceWiden)
|
|
|
|
) {
|
2018-01-24 08:44:38 +00:00
|
|
|
// Utilise that a.b is the same as ~a.b.0
|
2018-04-10 03:20:46 +00:00
|
|
|
const minSatisfying = minSatisfyingVersion(
|
2018-01-24 08:44:38 +00:00
|
|
|
versionList,
|
|
|
|
`${major}.${minor}`
|
|
|
|
);
|
|
|
|
// Add a tilde before that version number
|
2018-01-24 14:26:37 +00:00
|
|
|
const newVersion = `${currentVersion} || ~${minSatisfying}`;
|
2018-01-24 08:44:38 +00:00
|
|
|
return {
|
|
|
|
...upgrade,
|
2018-01-24 14:26:37 +00:00
|
|
|
newVersion,
|
2018-01-24 08:44:38 +00:00
|
|
|
};
|
2018-01-24 14:26:37 +00:00
|
|
|
} else if (
|
|
|
|
lastSemver.operator === '^' &&
|
|
|
|
canReplace &&
|
|
|
|
(semverParsed.length === 1 || forceReplace)
|
|
|
|
) {
|
2018-01-24 08:44:38 +00:00
|
|
|
let newVersion;
|
2017-04-28 19:55:14 +00:00
|
|
|
// Special case where major and minor are 0
|
|
|
|
if (major === '0' && minor === '0') {
|
2018-01-24 08:44:38 +00:00
|
|
|
newVersion = `^${upgrade.newVersion}`;
|
|
|
|
} else {
|
|
|
|
// If version is < 1, then semver treats ^ same as ~
|
|
|
|
const newRange = major === '0' ? `${major}.${minor}` : `${major}`;
|
2018-04-10 03:20:46 +00:00
|
|
|
const minSatisfying = minSatisfyingVersion(versionList, newRange);
|
2018-01-24 08:44:38 +00:00
|
|
|
// Add in the caret
|
|
|
|
newVersion = `^${minSatisfying}`;
|
2017-04-28 19:55:14 +00:00
|
|
|
}
|
2018-01-24 08:44:38 +00:00
|
|
|
return { ...upgrade, newVersion };
|
2018-01-24 14:26:37 +00:00
|
|
|
} else if (
|
|
|
|
lastSemver.operator === '^' &&
|
|
|
|
canWiden &&
|
|
|
|
(semverParsed.length > 1 || forceWiden)
|
|
|
|
) {
|
2017-04-21 08:12:41 +00:00
|
|
|
// If version is < 1, then semver treats ^ same as ~
|
|
|
|
const newRange = major === '0' ? `${major}.${minor}` : `${major}`;
|
2018-04-10 03:20:46 +00:00
|
|
|
const minSatisfying = minSatisfyingVersion(versionList, newRange);
|
2017-04-21 08:12:41 +00:00
|
|
|
// Add in the caret
|
2018-01-24 08:44:38 +00:00
|
|
|
const newVersion = `${currentVersion} || ^${minSatisfying}`;
|
|
|
|
return {
|
|
|
|
...upgrade,
|
|
|
|
newVersion,
|
|
|
|
};
|
|
|
|
} else if (lastSemver.operator === '<=') {
|
|
|
|
const minorZero = !lastSemver.minor || lastSemver.minor === '0';
|
|
|
|
const patchZero = !lastSemver.patch || lastSemver.patch === '0';
|
2018-01-24 07:43:27 +00:00
|
|
|
const newRange = [...semverParsed];
|
|
|
|
if (minorZero && patchZero) {
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.debug({ dependency }, 'Found a less than major');
|
2018-01-24 07:43:27 +00:00
|
|
|
newRange[newRange.length - 1].major = String(
|
|
|
|
upgrade.newVersionMajor + 1
|
|
|
|
);
|
|
|
|
} else if (patchZero) {
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.debug({ dependency }, 'Found a less than minor');
|
2018-01-24 07:43:27 +00:00
|
|
|
newRange[newRange.length - 1].major = String(upgrade.newVersionMajor);
|
|
|
|
newRange[newRange.length - 1].minor = String(
|
|
|
|
upgrade.newVersionMinor + 1
|
|
|
|
);
|
|
|
|
} else {
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.debug({ dependency }, 'Found a less than full semver');
|
2018-01-24 07:43:27 +00:00
|
|
|
newRange[newRange.length - 1].major = String(upgrade.newVersionMajor);
|
|
|
|
newRange[newRange.length - 1].minor = String(upgrade.newVersionMinor);
|
|
|
|
newRange[newRange.length - 1].patch = String(
|
2018-04-10 03:20:46 +00:00
|
|
|
getPatch(upgrade.newVersion)
|
2018-01-24 07:43:27 +00:00
|
|
|
);
|
|
|
|
}
|
2018-04-10 03:20:46 +00:00
|
|
|
let newVersion = stringifyRange(newRange);
|
2018-02-01 07:25:52 +00:00
|
|
|
newVersion = fixRange(newVersion, lastSemver, currentVersion);
|
2018-01-24 07:43:27 +00:00
|
|
|
return { ...upgrade, newVersion };
|
2018-01-24 08:44:38 +00:00
|
|
|
} else if (lastSemver.operator === '<') {
|
|
|
|
const minorZero = !lastSemver.minor || lastSemver.minor === '0';
|
|
|
|
const patchZero = !lastSemver.patch || lastSemver.patch === '0';
|
2018-01-24 07:43:27 +00:00
|
|
|
const newRange = [...semverParsed];
|
|
|
|
if (minorZero && patchZero) {
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.debug({ dependency }, 'Found a less than major');
|
2018-01-24 07:43:27 +00:00
|
|
|
newRange[newRange.length - 1].major = String(
|
|
|
|
upgrade.newVersionMajor + 1
|
|
|
|
);
|
|
|
|
} else if (patchZero) {
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.debug({ dependency }, 'Found a less than minor');
|
2018-01-24 07:43:27 +00:00
|
|
|
newRange[newRange.length - 1].major = String(upgrade.newVersionMajor);
|
|
|
|
newRange[newRange.length - 1].minor = String(
|
|
|
|
upgrade.newVersionMinor + 1
|
|
|
|
);
|
|
|
|
} else {
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.debug({ dependency }, 'Found full semver minor');
|
2018-01-24 07:43:27 +00:00
|
|
|
newRange[newRange.length - 1].major = String(upgrade.newVersionMajor);
|
|
|
|
newRange[newRange.length - 1].minor = String(upgrade.newVersionMinor);
|
|
|
|
newRange[newRange.length - 1].patch = String(
|
2018-04-10 03:20:46 +00:00
|
|
|
getPatch(upgrade.newVersion) + 1
|
2018-01-24 07:43:27 +00:00
|
|
|
);
|
|
|
|
}
|
2018-04-10 03:20:46 +00:00
|
|
|
let newVersion = stringifyRange(newRange);
|
2018-02-01 07:25:52 +00:00
|
|
|
newVersion = fixRange(newVersion, lastSemver, currentVersion);
|
2018-01-24 07:43:27 +00:00
|
|
|
return { ...upgrade, newVersion };
|
2018-01-24 08:44:38 +00:00
|
|
|
} else if (lastSemver.minor === undefined) {
|
2017-04-21 08:12:41 +00:00
|
|
|
// Example: 1
|
2018-01-24 10:23:59 +00:00
|
|
|
const newRange = [...semverParsed];
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.debug({ dependency }, 'Found a standalone major');
|
2018-01-24 10:23:59 +00:00
|
|
|
newRange[newRange.length - 1].major = String(upgrade.newVersionMajor);
|
|
|
|
let newVersion;
|
|
|
|
if (secondLastSemver && secondLastSemver.operator === '||') {
|
|
|
|
newVersion = `${currentVersion} || ${upgrade.newVersionMajor}`;
|
|
|
|
} else {
|
2018-04-10 03:20:46 +00:00
|
|
|
newVersion = stringifyRange(newRange);
|
|
|
|
// Fixes a bug with stringifyRange
|
2018-01-24 10:23:59 +00:00
|
|
|
newVersion = newVersion.replace(/\.0/g, '');
|
|
|
|
}
|
|
|
|
return { ...upgrade, newVersion };
|
2018-01-24 08:44:38 +00:00
|
|
|
} else if (lastSemver.minor === 'x') {
|
2017-04-21 08:12:41 +00:00
|
|
|
// Example: 1.x
|
2018-01-24 10:23:59 +00:00
|
|
|
const newRange = [...semverParsed];
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.debug({ dependency }, 'Found a .x');
|
2018-01-24 10:23:59 +00:00
|
|
|
newRange[newRange.length - 1].major = String(upgrade.newVersionMajor);
|
|
|
|
let newVersion;
|
|
|
|
if (secondLastSemver && secondLastSemver.operator === '||') {
|
|
|
|
newVersion = `${currentVersion} || ${upgrade.newVersionMajor}.x`;
|
|
|
|
} else {
|
2018-04-10 03:20:46 +00:00
|
|
|
newVersion = stringifyRange(newRange);
|
|
|
|
// Fixes a bug with stringifyRange
|
2018-01-24 10:23:59 +00:00
|
|
|
newVersion = newVersion.replace(/\.0/g, '');
|
|
|
|
}
|
|
|
|
return { ...upgrade, newVersion };
|
2018-01-24 08:44:38 +00:00
|
|
|
} else if (lastSemver.patch === undefined) {
|
2017-04-21 08:12:41 +00:00
|
|
|
// Example: 1.2
|
2017-08-03 06:01:20 +00:00
|
|
|
return { ...upgrade, ...{ newVersion: `${major}.${minor}` } };
|
2018-01-24 10:23:59 +00:00
|
|
|
} else if (lastSemver.patch === 'x' && semverParsed.length === 1) {
|
2017-04-21 08:12:41 +00:00
|
|
|
// Example: 1.2.x
|
2017-08-03 06:01:20 +00:00
|
|
|
return { ...upgrade, ...{ newVersion: `${major}.${minor}.x` } };
|
2017-04-21 08:12:41 +00:00
|
|
|
}
|
2018-01-24 07:43:27 +00:00
|
|
|
// istanbul ignore next
|
2017-12-05 10:50:16 +00:00
|
|
|
result.message = `The current semver range "${currentVersion}" is not supported so won't ever be upgraded`;
|
2018-01-24 07:43:27 +00:00
|
|
|
// istanbul ignore next
|
2018-01-28 13:51:55 +00:00
|
|
|
logger.warn({ dependency }, result.message);
|
2018-01-24 07:43:27 +00:00
|
|
|
// istanbul ignore next
|
2017-04-21 08:12:41 +00:00
|
|
|
return null;
|
|
|
|
})
|
|
|
|
.compact()
|
|
|
|
.value();
|
2018-01-24 07:43:27 +00:00
|
|
|
// istanbul ignore if
|
2017-07-04 10:39:28 +00:00
|
|
|
if (result.message) {
|
|
|
|
// There must have been an error converting to ranges
|
|
|
|
return [result];
|
|
|
|
}
|
|
|
|
return rangedUpgrades;
|
2017-01-07 21:00:32 +00:00
|
|
|
}
|
2017-01-09 21:44:36 +00:00
|
|
|
|
2018-02-01 07:25:52 +00:00
|
|
|
function fixRange(version, lastSemver, currentVersion) {
|
|
|
|
let newVersion = version;
|
|
|
|
if (!lastSemver.patch) {
|
|
|
|
newVersion = newVersion.replace(/\.0$/, '');
|
|
|
|
}
|
|
|
|
if (!currentVersion.includes('< ')) {
|
|
|
|
newVersion = newVersion.replace(/< /g, '<');
|
|
|
|
}
|
|
|
|
if (!currentVersion.includes('> ')) {
|
|
|
|
newVersion = newVersion.replace(/> /g, '>');
|
|
|
|
}
|
|
|
|
if (!currentVersion.includes('>= ')) {
|
|
|
|
newVersion = newVersion.replace(/>= /g, '>=');
|
|
|
|
}
|
|
|
|
if (!currentVersion.includes('<= ')) {
|
|
|
|
newVersion = newVersion.replace(/<= /g, '<=');
|
|
|
|
}
|
|
|
|
return newVersion;
|
|
|
|
}
|
|
|
|
|
2017-06-27 11:44:03 +00:00
|
|
|
function isPastLatest(npmDep, version) {
|
2018-03-30 07:38:17 +00:00
|
|
|
if (!version) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-06-27 11:44:03 +00:00
|
|
|
if (npmDep['dist-tags'] && npmDep['dist-tags'].latest) {
|
2018-04-10 03:20:46 +00:00
|
|
|
return isGreaterThan(version, npmDep['dist-tags'].latest);
|
2017-01-17 11:46:32 +00:00
|
|
|
}
|
2017-06-27 11:44:03 +00:00
|
|
|
logger.warn(`No dist-tags.latest for ${npmDep.name}`);
|
2017-01-17 11:46:32 +00:00
|
|
|
return false;
|
|
|
|
}
|