Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
246 changes: 232 additions & 14 deletions __tests__/distributors/liberica-installer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type {
} from '../../src/distributions/liberica/models.js';
import {HttpClient} from '@actions/http-client';
import os from 'os';
import path from 'path';

import manifestData from '../data/liberica.json' with {type: 'json'};

Expand Down Expand Up @@ -253,35 +254,68 @@ describe('findPackageForDownload', () => {
expect(result.version).toBe(expected);
});

describe('compound build versions', () => {
describe.each([
[17, 20],
[25, 4]
])('patch releases for Java %s.0.%s', (featureVersion, updateVersion) => {
const mainVersion = `${featureVersion}.0.${updateVersion}`;

beforeEach(() => {
distribution['getAvailableVersions'] = async () =>
['1', '1.1', '1.2', '1.10'].map(build => ({
featureVersion: 25,
['+1', '+10', '.1+1', '.1+2', '.1+10', '.2+1', '.10+1'].map(suffix => ({
featureVersion,
interimVersion: 0,
updateVersion: 4,
buildVersion: 1,
version: `25.0.4+${build}`,
downloadUrl: `https://download.bell-sw.com/java/25.0.4+${build}/bellsoft-jdk25.0.4+${build}-macos-aarch64.tar.gz`
updateVersion,
buildVersion: Number(suffix.split('+')[1]),
version: `${mainVersion}${suffix}`,
downloadUrl: `https://download.bell-sw.com/java/${mainVersion}${suffix}/bellsoft-jdk${mainVersion}${suffix}-macos-aarch64.tar.gz`
}));
});

it.each([
['25.0.4+1.1', '25.0.4+1.1'],
['25.0.4+1', '25.0.4+1'],
['25.0.4', '25.0.4+1.10'],
['25', '25.0.4+1.10']
])('version is %s -> %s', async (input, expected) => {
[`${mainVersion}+1.1`, `${mainVersion}+1.1`, '.1+1'],
[`${mainVersion}+1.2`, `${mainVersion}+1.2`, '.1+2'],
[`${mainVersion}+1.10`, `${mainVersion}+1.10`, '.1+10'],
[`${mainVersion}+1`, `${mainVersion}+1`, '+1'],
[mainVersion, `${mainVersion}+10.1`, '.10+1'],
[`${featureVersion}`, `${mainVersion}+10.1`, '.10+1']
])('version is %s -> %s', async (input, expected, suffix) => {
const result = await distribution['findPackageForDownload'](input);
expect(result).toEqual({
version: expected,
url: `https://download.bell-sw.com/java/${expected}/bellsoft-jdk${expected}-macos-aarch64.tar.gz`
url: `https://download.bell-sw.com/java/${mainVersion}${suffix}/bellsoft-jdk${mainVersion}${suffix}-macos-aarch64.tar.gz`
});
});

it('sorts builds within the same patch numerically', async () => {
const versions = await distribution['getAvailableVersions']();
distribution['getAvailableVersions'] = async () =>
versions.filter(item => item.version.startsWith(`${mainVersion}.1+`));

const result = await distribution['findPackageForDownload'](mainVersion);
expect(result.version).toBe(`${mainVersion}+1.10`);
});

it('selects the newest build for a four-component patch-only request', async () => {
const patchDistribution = new LibericaDistributions({
version: `${mainVersion}.1`,
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
patchDistribution['getAvailableVersions'] =
distribution['getAvailableVersions'];

await expect(
patchDistribution['findPackageForDownload'](
patchDistribution['version']
)
).resolves.toMatchObject({version: `${mainVersion}+1.10`});
});

it('does not substitute a different compound build', async () => {
await expect(
distribution['findPackageForDownload']('25.0.4+1.3')
distribution['findPackageForDownload'](`${mainVersion}+1.3`)
).rejects.toThrow(/No matching version found for SemVer/);
});
});
Expand All @@ -293,6 +327,160 @@ describe('findPackageForDownload', () => {
});
});

describe('patch request resolution from the constructor', () => {
const releases: LibericaVersion[] = ['17.0.20+10', '17.0.20.1+1'].map(
version => ({
featureVersion: 17,
interimVersion: 0,
updateVersion: 20,
buildVersion: Number(version.split('+')[1]),
version,
downloadUrl: `https://download.bell-sw.com/java/${version}/jdk.tar.gz`
})
);
let cacheRoot: string;
let previousToolcache: string | undefined;

beforeEach(async () => {
previousToolcache = process.env['RUNNER_TOOL_CACHE'];
cacheRoot = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'liberica-'));
process.env['RUNNER_TOOL_CACHE'] = cacheRoot;
for (const version of ['17.0.20-10', '17.0.20-1.1']) {
const javaPath = path.join(
cacheRoot,
'Java_Liberica_jdk',
version,
'x64'
);
await fs.promises.mkdir(javaPath, {recursive: true});
await fs.promises.writeFile(`${javaPath}.complete`, '');
}
});

afterEach(async () => {
if (previousToolcache === undefined) {
delete process.env['RUNNER_TOOL_CACHE'];
} else {
process.env['RUNNER_TOOL_CACHE'] = previousToolcache;
}
await fs.promises.rm(cacheRoot, {recursive: true, force: true});
});

it.each([
['17', '17.0.20+1.1', '17.0.20.1+1'],
['17.0.20', '17.0.20+1.1', '17.0.20.1+1'],
['17.0.20+10', '17.0.20+10', '17.0.20+10'],
['17.0.20+1.1', '17.0.20+1.1', '17.0.20.1+1'],
['17.0.20.1', '17.0.20+1.1', '17.0.20.1+1'],
['17.0.20.1+1', '17.0.20+1.1', '17.0.20.1+1'],
['17.0.20.0', '17.0.20+10', '17.0.20+10']
])(
'resolves %s consistently remotely and in cache',
async (input, expected, apiVersion) => {
const distribution = new LibericaDistributions({
version: input,
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
distribution['getAvailableVersions'] = async () => releases;

await expect(
distribution['findPackageForDownload'](distribution['version'])
).resolves.toEqual({
version: expected,
url: `https://download.bell-sw.com/java/${apiVersion}/jdk.tar.gz`
});
expect(distribution['findInToolcache']()).toEqual({
version: expected,
path: path.join(
cacheRoot,
'Java_Liberica_jdk',
expected.replace('+', '-'),
'x64'
)
});
}
);

it.each(['17.0.20.2', '17.0.20+1.2'])(
'does not substitute a different patch or exact build for %s',
async version => {
const distribution = new LibericaDistributions({
version,
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
distribution['getAvailableVersions'] = async () => releases;

await expect(
distribution['findPackageForDownload'](distribution['version'])
).rejects.toThrow(/No matching version found/);
expect(distribution['findInToolcache']()).toBeNull();
}
);

it('keeps patch-only and exact-build resolution cache identities distinct', () => {
const distribution = new LibericaDistributions({
version: '17.0.20.1',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
expect(distribution['version']).toBe('17.0.20.1');
});

it('orders main versions, patches, and builds consistently in cache', async () => {
for (const version of ['17.0.20-1.2', '17.0.20-1.10', '17.0.21-1']) {
const javaPath = path.join(
cacheRoot,
'Java_Liberica_jdk',
version,
'x64'
);
await fs.promises.mkdir(javaPath, {recursive: true});
await fs.promises.writeFile(`${javaPath}.complete`, '');
}

for (const [version, expected] of [
['17', '17.0.21+1'],
['17.0.20', '17.0.20+1.10'],
['17.0.20.1', '17.0.20+1.10']
]) {
const distribution = new LibericaDistributions({
version,
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
expect(distribution['findInToolcache']()?.version).toBe(expected);
}
});

it('preserves early-access handling for patch-only requests', async () => {
const javaPath = path.join(
cacheRoot,
'Java_Liberica_jdk',
'17.0.20-ea.1.2',
'x64'
);
await fs.promises.mkdir(javaPath, {recursive: true});
await fs.promises.writeFile(`${javaPath}.complete`, '');
const distribution = new LibericaDistributions({
version: '17.0.20.1-ea',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
expect(distribution['stable']).toBe(false);
expect(distribution['findInToolcache']()).toEqual({
version: '17.0.20+1.2',
path: javaPath
});
});
});

describe('getPlatformOption', () => {
beforeEach(() => {
// The linux row below is glibc, so pin the Alpine probe rather than
Expand Down Expand Up @@ -369,6 +557,36 @@ describe('convertVersionToSemver', () => {
},
'11.0.0+13'
],
[
{
version: '17.0.20.1+1',
featureVersion: 17,
interimVersion: 0,
updateVersion: 20,
buildVersion: 1
},
'17.0.20+1.1'
],
[
{
version: '25.0.4.1+1',
featureVersion: 25,
interimVersion: 0,
updateVersion: 4,
buildVersion: 1
},
'25.0.4+1.1'
],
[
{
version: '17.0.20.1+2',
featureVersion: 17,
interimVersion: 0,
updateVersion: 20,
buildVersion: 2
},
'17.0.20+1.2'
],
[
{
version: '25.0.4+1.1',
Expand Down
14 changes: 10 additions & 4 deletions dist/setup/242.index.js
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ class JavaBase {
core/* info */.pq(`Java ${foundJava.version} was downloaded`);
if (javaRelease.floating) {
if (!semver_default().valid(foundJava.version) ||
!(0,util/* isVersionSatisfies */.y)(this.version, foundJava.version)) {
!this.isVersionSatisfied(this.version, foundJava.version)) {
throw new Error(`The downloaded ${this.distribution} artifact reported Java ${foundJava.version}, which does not satisfy '${this.version}'.`);
}
javaRelease = { ...javaRelease, version: foundJava.version };
Expand Down Expand Up @@ -501,7 +501,7 @@ class JavaBase {
return javaRelease;
}
if (!semver_default().valid(restored.release.version) ||
!(0,util/* isVersionSatisfies */.y)(this.version, restored.release.version)) {
!this.isVersionSatisfied(this.version, restored.release.version)) {
core/* debug */.Yz(`Ignoring the cached concrete version '${restored.release.version}' for ${this.distribution} ${this.version}.`);
return javaRelease;
}
Expand Down Expand Up @@ -684,10 +684,10 @@ class JavaBase {
})
.filter(item => item.stable === this.stable);
const satisfiedVersions = availableVersions
.filter(item => (0,util/* isVersionSatisfies */.y)(this.version, item.version))
.filter(item => this.isVersionSatisfied(this.version, item.version))
.filter(item => item.path)
.sort((a, b) => {
return -semver_default().compareBuild(a.version, b.version);
return -this.compareVersions(a.version, b.version);
});
if (!satisfiedVersions || satisfiedVersions.length === 0) {
return null;
Expand All @@ -697,6 +697,12 @@ class JavaBase {
path: satisfiedVersions[0].path
};
}
isVersionSatisfied(range, version) {
return (0,util/* isVersionSatisfies */.y)(range, version);
}
compareVersions(a, b) {
return semver_default().compareBuild(a, b);
}
normalizeVersion(version) {
let stable = true;
const latest = false;
Expand Down
40 changes: 38 additions & 2 deletions dist/setup/63.index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,46 @@ class LibericaDistributions extends _base_installer_js__WEBPACK_IMPORTED_MODULE_
version: this.convertVersionToSemver(item)
}));
const satisfiedVersion = availableVersions
.filter(item => (0,_util_js__WEBPACK_IMPORTED_MODULE_2__/* .isVersionSatisfies */ .y)(range, item.version))
.sort((a, b) => -semver__WEBPACK_IMPORTED_MODULE_1___default().compareBuild(a.version, b.version))[0];
.filter(item => this.isVersionSatisfied(range, item.version))
.sort((a, b) => -this.compareVersions(a.version, b.version))[0];
if (!satisfiedVersion) {
const availableVersionStrings = availableVersions.map(item => item.version);
throw this.createVersionNotFoundError(range, availableVersionStrings);
}
return satisfiedVersion;
}
normalizeVersion(version) {
const normalized = super.normalizeVersion(version);
if (/^\d+\.\d+\.\d+\.\d+(?:-ea)?$/.test(version)) {
// Keep patch-only requests distinct from exact SDKMAN build requests.
normalized.version = version.replace(/-ea$/, '');
}
return normalized;
}
isVersionSatisfied(range, version) {
const patchRequest = range.match(/^(\d+\.\d+\.\d+)\.(\d+)$/);
if (patchRequest) {
const candidate = semver__WEBPACK_IMPORTED_MODULE_1___default().parse(version);
if (!candidate || !semver__WEBPACK_IMPORTED_MODULE_1___default().eq(patchRequest[1], candidate)) {
return false;
}
const patch = candidate.build.length > 1 ? candidate.build[0] : '0';
return patch === patchRequest[2];
}
return super.isVersionSatisfied(range, version);
}
compareVersions(a, b) {
const mainComparison = semver__WEBPACK_IMPORTED_MODULE_1___default().compare(a, b);
if (mainComparison !== 0) {
return mainComparison;
}
// SDKMAN encodes patch.build, but unpatched releases contain only build.
const patchAndBuild = (version) => {
const build = new (semver__WEBPACK_IMPORTED_MODULE_1___default().SemVer)(version).build;
return (build.length > 1 ? build : ['0', ...build]).join('.');
};
return semver__WEBPACK_IMPORTED_MODULE_1___default().compareBuild(`0.0.0+${patchAndBuild(a)}`, `0.0.0+${patchAndBuild(b)}`);
}
async getAvailableVersions() {
if (_actions_core__WEBPACK_IMPORTED_MODULE_3__/* .isDebug */ ._o()) {
console.time('Retrieving available versions for Liberica took'); // eslint-disable-line no-console
Expand Down Expand Up @@ -131,6 +163,10 @@ class LibericaDistributions extends _base_installer_js__WEBPACK_IMPORTED_MODULE_
const { featureVersion, interimVersion, updateVersion } = version;
const buildVersion = version.version.split('+')[1] || version.buildVersion;
const mainVersion = [featureVersion, interimVersion, updateVersion].join('.');
const patchVersion = version.version.split('+')[0].split('.')[3];
if (patchVersion) {
return `${mainVersion}+${patchVersion}.${buildVersion}`;
}
if (buildVersion != 0) {
return `${mainVersion}+${buildVersion}`;
}
Expand Down
Loading
Loading