Support Temurin JEP 322 patch versions like 26.0.2.1+1 (#1270) (#1279)

Accept 4-part versions with build metadata (X.Y.Z.P+B -> X.Y.Z+P.B) and
match exact Temurin requests against OpenJDK-derived version keys, since the
Adoptium API semver folds the patch into the build number (26.0.2+101) and
adds LTS metadata (25.0.4+7.0.LTS).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Bruno Borges
2026-10-02 00:09:56 -04:00
committed by GitHub
parent 74920aab4a
commit 47b36480ae
14 changed files with 243 additions and 39 deletions
@@ -1758,6 +1758,8 @@ describe('normalizeVersion', () => {
['11.0.9.1', {version: '11.0.9+1', stable: true, latest: false}],
['12.0.2.1.0', {version: '12.0.2+1.0', stable: true, latest: false}],
['18.0.1.1-ea', {version: '18.0.1+1', stable: false, latest: false}],
['26.0.2.1+1', {version: '26.0.2+1.1', stable: true, latest: false}],
['25.0.4.1+1', {version: '25.0.4+1.1', stable: true, latest: false}],
['latest', {version: 'x', stable: true, latest: true}],
['LATEST', {version: 'x', stable: true, latest: true}],
[' Latest ', {version: 'x', stable: true, latest: true}]
@@ -82,7 +82,7 @@ describe('getJavaDistribution', () => {
);
});
it.each(['8', '23.x', '23.0.1.1', '<24'])(
it.each(['8', '23.x', '23.0.1.1', '23.0.1.1+1', '<24'])(
"rejects Temurin java-package 'jdk+jmods' for version %s",
async version => {
await expect(
@@ -96,7 +96,7 @@ describe('getJavaDistribution', () => {
}
);
it.each(['24', '24.0.1.1', '25-ea', '>=21', 'latest'])(
it.each(['24', '24.0.1.1', '25.0.4.1+1', '25-ea', '>=21', 'latest'])(
"accepts Temurin java-package 'jdk+jmods' for version %s",
async version => {
expect(
@@ -378,6 +378,97 @@ describe('findPackageForDownload', () => {
expect(resolvedVersion.version).toBe('16.0.2+7');
});
describe('OpenJDK patch (respin) versions', () => {
const makeRelease = (
semverVersion: string,
openjdkVersion: string,
versionData: Record<string, number>
) => ({
binaries: [
{
package: {
link: `https://example.com/${openjdkVersion}.tar.gz`,
checksum: `checksum-${openjdkVersion}`,
checksum_link: `https://example.com/${openjdkVersion}.sha256.txt`
}
}
],
version_data: {
semver: semverVersion,
openjdk_version: openjdkVersion,
minor: 0,
...versionData
}
});
const respinManifest = [
makeRelease('26.0.2+101', '26.0.2.1+1', {
major: 26,
security: 2,
patch: 1,
build: 1
}),
makeRelease('26.0.2+10', '26.0.2+10', {
major: 26,
security: 2,
build: 10
}),
makeRelease('25.0.4+101.0.LTS', '25.0.4.1+1-LTS', {
major: 25,
security: 4,
patch: 1,
build: 1
}),
makeRelease('25.0.4+7.0.LTS', '25.0.4+7-LTS', {
major: 25,
security: 4,
build: 7
})
];
it.each([
['26.0.2.1+1', '26.0.2+101'],
['26.0.2+10', '26.0.2+10'],
['26', '26.0.2+101'],
['26.0.2', '26.0.2+101'],
['25.0.4.1+1', '25.0.4+101.0.LTS'],
['25.0.4+7', '25.0.4+7.0.LTS'],
['25.0.4', '25.0.4+101.0.LTS']
])('%s resolves to %s', async (input, expected) => {
const distribution = new TemurinDistribution(
{
version: input,
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
},
TemurinImplementation.Hotspot
);
distribution['getAvailableVersions'] = async () => respinManifest as any;
const resolvedVersion = await distribution['findPackageForDownload'](
distribution['version']
);
expect(resolvedVersion.version).toBe(expected);
expect(resolvedVersion).not.toHaveProperty('openjdkVersion');
});
it('does not match a non-existent respin', async () => {
const distribution = new TemurinDistribution(
{
version: '26.0.2.2+1',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
},
TemurinImplementation.Hotspot
);
distribution['getAvailableVersions'] = async () => respinManifest as any;
await expect(
distribution['findPackageForDownload'](distribution['version'])
).rejects.toThrow(/No matching version found for SemVer '26.0.2\+2.1'/);
});
});
it('version is found but binaries list is empty', async () => {
const distribution = new TemurinDistribution(
{