mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-11 22:46:27 +00:00
fix(ivy): Make the versioning implementation more precise (#8363)
This commit is contained in:
parent
d0531f52fb
commit
6e84bb1780
4 changed files with 131 additions and 37 deletions
|
@ -21,16 +21,6 @@ export const presets: Record<string, Preset> = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
ignoreSbtLatestIntegration: {
|
|
||||||
description: 'Do not upgrade sbt latest.integration',
|
|
||||||
packageRules: [
|
|
||||||
{
|
|
||||||
managers: ['sbt'],
|
|
||||||
matchCurrentVersion: '/^latest\\.integration$/',
|
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
ignoreSpringCloudNumeric: {
|
ignoreSpringCloudNumeric: {
|
||||||
description: 'Ignore spring cloud 1.x releases',
|
description: 'Ignore spring cloud 1.x releases',
|
||||||
packageRules: [
|
packageRules: [
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
} from './parse';
|
} from './parse';
|
||||||
import ivy from '.';
|
import ivy from '.';
|
||||||
|
|
||||||
const { isVersion, matches } = ivy;
|
const { getNewValue, isValid, isVersion, matches } = ivy;
|
||||||
|
|
||||||
describe('versioning/ivy/match', () => {
|
describe('versioning/ivy/match', () => {
|
||||||
it('parses dynamic revisions', () => {
|
it('parses dynamic revisions', () => {
|
||||||
|
@ -61,7 +61,32 @@ describe('versioning/ivy/match', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('versioning/ivy/index', () => {
|
describe('versioning/ivy/index', () => {
|
||||||
it('validates version string', () => {
|
it('isValid', () => {
|
||||||
|
expect(isValid('')).toBe(false);
|
||||||
|
expect(isValid('1.0.0')).toBe(true);
|
||||||
|
expect(isValid('0')).toBe(true);
|
||||||
|
expect(isValid('0.1-2-sp')).toBe(true);
|
||||||
|
expect(isValid('1-final')).toBe(true);
|
||||||
|
expect(isValid('v1.0.0')).toBe(true);
|
||||||
|
expect(isValid('x1.0.0')).toBe(true);
|
||||||
|
expect(isValid('2.1.1.RELEASE')).toBe(true);
|
||||||
|
expect(isValid('Greenwich.SR1')).toBe(true);
|
||||||
|
expect(isValid('.1')).toBe(false);
|
||||||
|
expect(isValid('1.')).toBe(false);
|
||||||
|
expect(isValid('-1')).toBe(false);
|
||||||
|
expect(isValid('1-')).toBe(false);
|
||||||
|
|
||||||
|
expect(isValid('latest')).toBe(true);
|
||||||
|
expect(isValid('latest.release')).toBe(true);
|
||||||
|
expect(isValid('latest.milestone')).toBe(true);
|
||||||
|
expect(isValid('latest.integration')).toBe(true);
|
||||||
|
expect(isValid('1.0.+')).toBe(true);
|
||||||
|
expect(isValid('1.0+')).toBe(false);
|
||||||
|
expect(isValid(']0,1[')).toBe(true);
|
||||||
|
expect(isValid('[0,1]')).toBe(true);
|
||||||
|
expect(isValid('[0,1),(1,2]')).toBe(false);
|
||||||
|
});
|
||||||
|
it('isVersion', () => {
|
||||||
expect(isVersion('')).toBe(false);
|
expect(isVersion('')).toBe(false);
|
||||||
expect(isVersion('1.0.0')).toBe(true);
|
expect(isVersion('1.0.0')).toBe(true);
|
||||||
expect(isVersion('0')).toBe(true);
|
expect(isVersion('0')).toBe(true);
|
||||||
|
@ -76,17 +101,17 @@ describe('versioning/ivy/index', () => {
|
||||||
expect(isVersion('-1')).toBe(false);
|
expect(isVersion('-1')).toBe(false);
|
||||||
expect(isVersion('1-')).toBe(false);
|
expect(isVersion('1-')).toBe(false);
|
||||||
|
|
||||||
expect(isVersion('latest')).toBe(true);
|
expect(isVersion('latest')).toBe(false);
|
||||||
expect(isVersion('latest.release')).toBe(true);
|
expect(isVersion('latest.release')).toBe(false);
|
||||||
expect(isVersion('latest.milestone')).toBe(true);
|
expect(isVersion('latest.milestone')).toBe(false);
|
||||||
expect(isVersion('latest.integration')).toBe(true);
|
expect(isVersion('latest.integration')).toBe(false);
|
||||||
expect(isVersion('1.0.+')).toBe(true);
|
expect(isVersion('1.0.+')).toBe(false);
|
||||||
expect(isVersion('1.0+')).toBe(false);
|
expect(isVersion('1.0+')).toBe(false);
|
||||||
expect(isVersion(']0,1[')).toBe(true);
|
expect(isVersion(']0,1[')).toBe(false);
|
||||||
expect(isVersion('[0,1]')).toBe(true);
|
expect(isVersion('[0,1]')).toBe(false);
|
||||||
expect(isVersion('[0,1),(1,2]')).toBe(false);
|
expect(isVersion('[0,1),(1,2]')).toBe(false);
|
||||||
});
|
});
|
||||||
it('matches against dynamic revisions', () => {
|
it('matches', () => {
|
||||||
expect(matches('', 'latest')).toBe(false);
|
expect(matches('', 'latest')).toBe(false);
|
||||||
expect(matches('0', '')).toBe(false);
|
expect(matches('0', '')).toBe(false);
|
||||||
expect(matches('0', 'latest')).toBe(true);
|
expect(matches('0', 'latest')).toBe(true);
|
||||||
|
@ -126,4 +151,51 @@ describe('versioning/ivy/index', () => {
|
||||||
expect(matches('1', '[1,)')).toBe(true);
|
expect(matches('1', '[1,)')).toBe(true);
|
||||||
expect(matches('1', '(1,)')).toBe(false);
|
expect(matches('1', '(1,)')).toBe(false);
|
||||||
});
|
});
|
||||||
|
it('api', () => {
|
||||||
|
expect(ivy.isGreaterThan('1.1', '1')).toBe(true);
|
||||||
|
expect(ivy.getSatisfyingVersion(['0', '1', '2'], '(,2)')).toBe('1');
|
||||||
|
expect(
|
||||||
|
ivy.getNewValue({
|
||||||
|
currentValue: '1',
|
||||||
|
rangeStrategy: 'auto',
|
||||||
|
fromVersion: '1',
|
||||||
|
toVersion: '1.1',
|
||||||
|
})
|
||||||
|
).toBe('1.1');
|
||||||
|
expect(
|
||||||
|
ivy.getNewValue({
|
||||||
|
currentValue: '[1.2.3,]',
|
||||||
|
rangeStrategy: 'auto',
|
||||||
|
fromVersion: '1.2.3',
|
||||||
|
toVersion: '1.2.4',
|
||||||
|
})
|
||||||
|
).toBe('[1.2.3,]');
|
||||||
|
});
|
||||||
|
it('pin', () => {
|
||||||
|
const sample = [
|
||||||
|
['[1.2.3]', '1.2.3', '1.2.4'],
|
||||||
|
['[1.0.0,1.2.3]', '1.0.0', '1.2.4'],
|
||||||
|
['[1.0.0,1.2.23]', '1.0.0', '1.2.23'],
|
||||||
|
['(,1.0]', '0.0.1', '2.0'],
|
||||||
|
['],1.0]', '0.0.1', '2.0'],
|
||||||
|
['(,1.0)', '0.1', '2.0'],
|
||||||
|
['],1.0[', '2.0', '],2.0['],
|
||||||
|
['[1.0,1.2],[1.3,1.5)', '1.0', '1.2.4'],
|
||||||
|
['[1.0,1.2],[1.3,1.5[', '1.0', '1.2.4'],
|
||||||
|
['[1.2.3,)', '1.2.3', '1.2.4'],
|
||||||
|
['[1.2.3,[', '1.2.3', '1.2.4'],
|
||||||
|
['latest.integration', '1.0', '2.0'],
|
||||||
|
['latest', '1.0', '2.0'],
|
||||||
|
];
|
||||||
|
sample.forEach(([currentValue, fromVersion, toVersion]) => {
|
||||||
|
expect(
|
||||||
|
getNewValue({
|
||||||
|
currentValue,
|
||||||
|
rangeStrategy: 'pin',
|
||||||
|
fromVersion,
|
||||||
|
toVersion,
|
||||||
|
})
|
||||||
|
).toEqual(toVersion);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
import { VersioningApi } from '../common';
|
import { NewValueConfig, VersioningApi } from '../common';
|
||||||
import maven from '../maven';
|
import maven from '../maven';
|
||||||
import { TYPE_QUALIFIER, isSubversion, tokenize } from '../maven/compare';
|
|
||||||
import {
|
import {
|
||||||
|
TYPE_QUALIFIER,
|
||||||
|
autoExtendMavenRange,
|
||||||
|
isSubversion,
|
||||||
|
tokenize,
|
||||||
|
} from '../maven/compare';
|
||||||
|
import {
|
||||||
|
LATEST_REGEX,
|
||||||
REV_TYPE_LATEST,
|
REV_TYPE_LATEST,
|
||||||
REV_TYPE_SUBREV,
|
REV_TYPE_SUBREV,
|
||||||
parseDynamicRevision,
|
parseDynamicRevision,
|
||||||
|
@ -20,27 +26,27 @@ const {
|
||||||
getMinor,
|
getMinor,
|
||||||
getPatch,
|
getPatch,
|
||||||
isGreaterThan,
|
isGreaterThan,
|
||||||
isSingleVersion,
|
|
||||||
isStable,
|
isStable,
|
||||||
matches: mavenMatches,
|
matches: mavenMatches,
|
||||||
getSatisfyingVersion,
|
|
||||||
minSatisfyingVersion,
|
|
||||||
getNewValue,
|
|
||||||
sortVersions,
|
sortVersions,
|
||||||
} = maven;
|
} = maven;
|
||||||
|
|
||||||
function isVersion(str: string): string | boolean {
|
function isValid(str: string): string | boolean {
|
||||||
if (!str) {
|
if (!str) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return isSingleVersion(str) || !!parseDynamicRevision(str);
|
return maven.isVersion(str) || !!parseDynamicRevision(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isVersion(str: string): string | boolean {
|
||||||
|
if (!str || LATEST_REGEX.test(str)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return maven.isVersion(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
function matches(a: string, b: string): boolean {
|
function matches(a: string, b: string): boolean {
|
||||||
if (!a) {
|
if (!a || !b) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!b) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const dynamicRevision = parseDynamicRevision(b);
|
const dynamicRevision = parseDynamicRevision(b);
|
||||||
|
@ -70,6 +76,31 @@ function matches(a: string, b: string): boolean {
|
||||||
return mavenMatches(a, value);
|
return mavenMatches(a, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSatisfyingVersion(versions: string[], range: string): string {
|
||||||
|
return versions.reduce((result, version) => {
|
||||||
|
if (matches(version, range)) {
|
||||||
|
if (!result) {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
if (isGreaterThan(version, result)) {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNewValue({
|
||||||
|
currentValue,
|
||||||
|
rangeStrategy,
|
||||||
|
toVersion,
|
||||||
|
}: NewValueConfig): string | null {
|
||||||
|
if (isVersion(currentValue) || rangeStrategy === 'pin') {
|
||||||
|
return toVersion;
|
||||||
|
}
|
||||||
|
return autoExtendMavenRange(currentValue, toVersion);
|
||||||
|
}
|
||||||
|
|
||||||
export const api: VersioningApi = {
|
export const api: VersioningApi = {
|
||||||
equals,
|
equals,
|
||||||
getMajor,
|
getMajor,
|
||||||
|
@ -77,13 +108,13 @@ export const api: VersioningApi = {
|
||||||
getPatch,
|
getPatch,
|
||||||
isCompatible: isVersion,
|
isCompatible: isVersion,
|
||||||
isGreaterThan,
|
isGreaterThan,
|
||||||
isSingleVersion,
|
isSingleVersion: isVersion,
|
||||||
isStable,
|
isStable,
|
||||||
isValid: isVersion,
|
isValid,
|
||||||
isVersion,
|
isVersion,
|
||||||
matches,
|
matches,
|
||||||
getSatisfyingVersion,
|
getSatisfyingVersion,
|
||||||
minSatisfyingVersion,
|
minSatisfyingVersion: getSatisfyingVersion,
|
||||||
getNewValue,
|
getNewValue,
|
||||||
sortVersions,
|
sortVersions,
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,12 +10,13 @@ export interface Revision {
|
||||||
value: string;
|
value: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseDynamicRevision(str: string): Revision {
|
export const LATEST_REGEX = /^latest\.|^latest$/i;
|
||||||
|
|
||||||
|
function parseDynamicRevision(str: string): Revision | null {
|
||||||
if (!str) {
|
if (!str) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LATEST_REGEX = /^latest\.|^latest$/i;
|
|
||||||
if (LATEST_REGEX.test(str)) {
|
if (LATEST_REGEX.test(str)) {
|
||||||
const value = str.replace(LATEST_REGEX, '').toLowerCase() || null;
|
const value = str.replace(LATEST_REGEX, '').toLowerCase() || null;
|
||||||
return {
|
return {
|
||||||
|
|
Loading…
Reference in a new issue