Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(versioning): same major #28418

Merged
merged 27 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
029c372
init same-major versioning
RahulGautamSingh Apr 11, 2024
bb9dfeb
implementation
RahulGautamSingh Apr 11, 2024
9f0749d
add tests and docs
RahulGautamSingh Apr 15, 2024
8db1874
add urls
RahulGautamSingh Apr 15, 2024
0abd3e7
fix coverage
RahulGautamSingh Apr 15, 2024
b6c1b67
fix test
RahulGautamSingh Apr 15, 2024
d5a2b1f
refactor
RahulGautamSingh Apr 16, 2024
8ec34aa
fix tests
RahulGautamSingh Apr 16, 2024
3008147
fix coverage
RahulGautamSingh Apr 16, 2024
cfb8edd
apply suggestions
RahulGautamSingh Apr 18, 2024
9b299d5
Update lib/modules/versioning/same-major/readme.md
RahulGautamSingh Apr 21, 2024
f92d2e0
Apply suggestions from code review
RahulGautamSingh Apr 24, 2024
024d3bf
Apply suggestions from code review
RahulGautamSingh May 1, 2024
e2600ec
modify isGreaterThan
RahulGautamSingh Jun 3, 2024
6c1ad3c
update documentation
RahulGautamSingh Jun 3, 2024
0dda6c8
add tests
RahulGautamSingh Jun 3, 2024
05341de
Revert "modify isGreaterThan"
RahulGautamSingh Jun 3, 2024
d762ba4
modify isGreaterThan
RahulGautamSingh Jun 3, 2024
367b2bd
fix failing test
RahulGautamSingh Jun 3, 2024
0504960
fix failing test
RahulGautamSingh Jun 3, 2024
150320f
fix coverage
RahulGautamSingh Jun 3, 2024
da9b344
Merge branch 'main' into feat/versioning-same-major
RahulGautamSingh Jun 3, 2024
7eaa716
apply suggestions
RahulGautamSingh Jun 5, 2024
3c7cb04
fix coverage
RahulGautamSingh Jun 5, 2024
9922237
Update lib/modules/versioning/same-major/readme.md
RahulGautamSingh Jun 24, 2024
a90a6da
add warning
RahulGautamSingh Jun 24, 2024
dc38082
replace test with istanbul ignore statement
RahulGautamSingh Jun 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/modules/versioning/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import * as regex from './regex';
import * as rez from './rez';
import * as rpm from './rpm';
import * as ruby from './ruby';
import * as sameMajor from './same-major';
import * as semver from './semver';
import * as semverCoerced from './semver-coerced';
import * as swift from './swift';
Expand Down Expand Up @@ -74,6 +75,7 @@ api.set(regex.id, regex.api);
api.set(rez.id, rez.api);
api.set(rpm.id, rpm.api);
api.set(ruby.id, ruby.api);
api.set(sameMajor.id, sameMajor.api);
api.set(semver.id, semver.api);
api.set(semverCoerced.id, semverCoerced.api);
api.set(swift.id, swift.api);
Expand Down
57 changes: 57 additions & 0 deletions lib/modules/versioning/same-major/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import sameMajor from '.';

describe('modules/versioning/same-major/index', () => {
describe('.matches(version, range)', () => {
it('should return true when version has same major', () => {
expect(sameMajor.matches('1.0.1', '1.0.0')).toBeTrue();
expect(sameMajor.matches('1.0.1', '^1.0.0')).toBeTrue(); // coverage for when ranges are passed to the function
RahulGautamSingh marked this conversation as resolved.
Show resolved Hide resolved
});

it('should return false when version has different major', () => {
expect(sameMajor.matches('2.0.1', '1.0.0')).toBeFalse();
});

it('should return false when version is out of range', () => {
expect(sameMajor.matches('1.2.3', '1.2.4')).toBeFalse();
expect(sameMajor.matches('2.0.0', '1.2.4')).toBeFalse();
expect(sameMajor.matches('3.2.4', '1.2.4')).toBeFalse();
});

it('should return false when version is invalid', () => {
expect(sameMajor.matches('1.0.0', 'xxx')).toBeFalse();
});
});

describe('.getSatisfyingVersion(versions, range)', () => {
it('should return max satisfying version in range', () => {
expect(
sameMajor.getSatisfyingVersion(
['1.0.0', '1.0.4', '1.3.0', '2.0.0'],
'1.0.3',
),
).toBe('1.3.0');
});
});

describe('.minSatisfyingVersion(versions, range)', () => {
it('should return min satisfying version in range', () => {
expect(
sameMajor.minSatisfyingVersion(
['1.0.0', '1.0.4', '1.3.0', '2.0.0'],
'1.0.3',
),
).toBe('1.0.4');
});
});

describe('.isLessThanRange(version, range)', () => {
it('should return true', () => {
expect(sameMajor.isLessThanRange('2.0.2', '3.0.0')).toBeTrue();

Check failure on line 49 in lib/modules/versioning/same-major/index.spec.ts

View workflow job for this annotation

GitHub Actions / lint-other

Cannot invoke an object which is possibly 'undefined'.
});

it('should return false', () => {
expect(sameMajor.isLessThanRange('4.0.0', '3.0.0')).toBeFalse();

Check failure on line 53 in lib/modules/versioning/same-major/index.spec.ts

View workflow job for this annotation

GitHub Actions / lint-other

Cannot invoke an object which is possibly 'undefined'.
expect(sameMajor.isLessThanRange('3.1.0', '3.0.0')).toBeFalse();

Check failure on line 54 in lib/modules/versioning/same-major/index.spec.ts

View workflow job for this annotation

GitHub Actions / lint-other

Cannot invoke an object which is possibly 'undefined'.
});
});
});
54 changes: 54 additions & 0 deletions lib/modules/versioning/same-major/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { api as semverCoerced } from '../semver-coerced';
import type { VersioningApi } from '../types';

export const id = 'same-major';
export const displayName = 'Same Major Versioning';
export const urls = [];
export const supportsRanges = false;

/**
*
* Converts input to range if it's a version. eg. X.Y.Z -> '>=X.Y.Z <X+1'
* If the input is already a range, it returns the input.
*/
function massageVersion(input: string): string {
// return the input if it is a range
if (!semverCoerced.isSingleVersion(input)) {
return input;
}

// we are sure to get a major because of the isSingleVersion check
const major = semverCoerced.getMajor(input)!;
return `>=${input} <${major + 1}`;
}

function matches(version: string, range: string): boolean {
return semverCoerced.matches(version, massageVersion(range));
}

function getSatisfyingVersion(
versions: string[],
range: string,
): string | null {
return semverCoerced.getSatisfyingVersion(versions, massageVersion(range));
}

function minSatisfyingVersion(
versions: string[],
range: string,
): string | null {
return semverCoerced.minSatisfyingVersion(versions, massageVersion(range));
}

function isLessThanRange(version: string, range: string): boolean {
return semverCoerced.isLessThanRange!(version, massageVersion(range));
}

export const api: VersioningApi = {
...semverCoerced,
matches,
getSatisfyingVersion,
minSatisfyingVersion,
isLessThanRange,
};
export default api;
8 changes: 8 additions & 0 deletions lib/modules/versioning/same-major/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Renovate's 'Same Major' versioning is specifically designed to address scenarios where version specifications, denoted as X.Y.Z, signify a range of compatibility from greater than or equal to X.Y.Z to less than X+1.
RahulGautamSingh marked this conversation as resolved.
Show resolved Hide resolved
In essence, each individual version is to be treated as a constraint.

This method is handy when managing dependencies like dotnet-sdk's rollForward settings.
Let's say a project uses dotnet-sdk version 3.1.0.
RahulGautamSingh marked this conversation as resolved.
Show resolved Hide resolved
It needs to be compatible with any version in the 3.x.x range but not with versions in the next major version, like 4.x.x.
RahulGautamSingh marked this conversation as resolved.
Show resolved Hide resolved

This process employs Semver-Coerced versioning beneath the surface, wherein single versions (e.g., `X.Y.Z`) are converted to a range like `X+1` and then passed to the corresponding semver-coerced method.
RahulGautamSingh marked this conversation as resolved.
Show resolved Hide resolved
Loading