Skip to content

Commit bf6b4fb

Browse files
committed
Improve sorting in tools.getSemverVersion
1 parent 8f81967 commit bf6b4fb

File tree

3 files changed

+57
-10
lines changed

3 files changed

+57
-10
lines changed

__tests__/tools.test.ts

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,15 @@ jest.mock('../src/fetch', () => ({
6161
} else if (!token || token === 'valid_token') {
6262
return {data: `[{"ref": "refs/tags/1.2.3", "url": "${url}"}]`};
6363
} else if (token === 'beta_token') {
64-
return {data: `[{"ref": "refs/tags/1.2.3-beta1", "url": "${url}"}]`};
64+
return {data: `[{"ref": "refs/tags/1.2.3beta1", "url": "${url}"}]`};
65+
} else if (token === 'rc_token') {
66+
return {
67+
data: `[{"ref":"refs/tags/3.0.0RC1"},{"ref":"refs/tags/3.0.0RC2"}]`
68+
};
69+
} else if (token === 'non_semver_tags') {
70+
return {
71+
data: `[{"ref":"refs/tags/release-2025-09-18"},{"ref":"refs/tags/release-2025-09-17"}]`
72+
};
6573
} else if (token === 'undefined_ref') {
6674
return {
6775
data: `[{"url":"${url}"},{"ref":"refs/tags/v1.2.4","url":"${url}"}]`
@@ -97,20 +105,41 @@ jest.mock('../src/packagist', () => ({
97105

98106
describe('Tools tests', () => {
99107
it.each`
100-
token | version
101-
${'invalid_token'} | ${'1.2'}
102-
${'valid_token'} | ${'1.2.3'}
103-
${'beta_token'} | ${'1.2.3-beta1'}
104-
${'undefined_ref'} | ${'1.2.4'}
105-
${'multi_refs'} | ${'1.2.4'}
106-
${''} | ${'1.2.3'}
108+
token | version
109+
${'invalid_token'} | ${'1.2'}
110+
${'valid_token'} | ${'1.2.3'}
111+
${'beta_token'} | ${'1.2.3beta1'}
112+
${'undefined_ref'} | ${'1.2.4'}
113+
${'multi_refs'} | ${'1.2.4'}
114+
${'non_semver_tags'} | ${'release-2025-09-18'}
115+
${''} | ${'1.2.3'}
107116
`('checking getSemverVersion: $token', async ({token, version}) => {
108117
process.env['GITHUB_TOKEN'] = token;
109118
expect(
110119
await tools.getSemverVersion(getData({tool: 'tool', version: '1.2'}))
111120
).toBe(version);
112121
});
113122

123+
it('checking getSemverVersion triggers ?? fallback via Map#get mock', async () => {
124+
process.env['GITHUB_TOKEN'] = 'rc_token';
125+
const spy = jest
126+
.spyOn(Map.prototype as Map<string, string>, 'get')
127+
.mockImplementation(function (
128+
this: Map<string, string>,
129+
key: string
130+
): string | undefined {
131+
if (key === '3.0.0-RC2') {
132+
return undefined;
133+
}
134+
return Map.prototype.get.call(this, key);
135+
});
136+
const result = await tools.getSemverVersion(
137+
getData({tool: 'tool', version: '3.0.0'})
138+
);
139+
expect(result).toBe('3.0.0-RC2');
140+
spy.mockRestore();
141+
});
142+
114143
it.each`
115144
tool | fetch_latest | version
116145
${'tool'} | ${'true'} | ${'3.2.1'}

dist/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/tools.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ interface IRef {
2121
* @param data
2222
*/
2323
export async function getSemverVersion(data: RS): Promise<string> {
24+
const fixSemver = (t: string): string => {
25+
if (/^\d+\.\d+\.\d+(-|$)/.test(t)) return t;
26+
const m = t.match(/^(\d+\.\d+\.\d+)([A-Za-z]+[0-9A-Za-z.]+)$/);
27+
return m ? `${m[1]}-${m[2]}` : t;
28+
};
2429
const search: string = data['version_prefix'] + data['version'];
2530
const url = `https://api.github.com/repos/${data['repository']}/git/matching-refs/tags%2F${search}.`;
2631
const github_token: string =
@@ -35,7 +40,20 @@ export async function getSemverVersion(data: RS): Promise<string> {
3540
const tags = refs
3641
.map((i: IRef) => (i.ref?.split('/').pop() ?? '').replace(/^v(?=\d)/, ''))
3742
.filter((t: string) => t.length > 0);
38-
return tags.sort((a: string, b: string) => cv.compareVersions(b, a))[0];
43+
const fixedToOriginal = new Map<string, string>();
44+
const fixed = tags.map(t => {
45+
const f = fixSemver(t);
46+
fixedToOriginal.set(f, t);
47+
return f;
48+
});
49+
fixed.sort((a, b) => {
50+
try {
51+
return cv.compareVersions(b, a);
52+
} catch {
53+
return b.localeCompare(a, 'en', {numeric: true, sensitivity: 'base'});
54+
}
55+
});
56+
return fixedToOriginal.get(fixed[0]) ?? fixed[0];
3957
}
4058
}
4159

0 commit comments

Comments
 (0)