From 6d0d45b0d2dc3592dba6cde8d005676ca4b2d218 Mon Sep 17 00:00:00 2001 From: Lukasz <106734180+lukaszgyg@users.noreply.github.com> Date: Sat, 24 Jan 2026 11:12:58 +0100 Subject: [PATCH 1/4] feat: Add distribution detection support to .sdkmanrc file Extends .sdkmanrc support to automatically detect Java distribution from SDKMAN identifiers (e.g., java=21.0.5-tem maps to temurin distribution). Makes distribution input optional when using .sdkmanrc with distribution suffix. --- __tests__/data/sdkman-java-versions.csv | 20 ++--- __tests__/util.test.ts | 44 ++++++++-- action.yml | 4 +- dist/cleanup/index.js | 50 ++++++++++-- dist/setup/index.js | 104 ++++++++++++++++++------ src/setup-java.ts | 60 +++++++++----- src/util.ts | 60 ++++++++++++-- 7 files changed, 265 insertions(+), 77 deletions(-) diff --git a/__tests__/data/sdkman-java-versions.csv b/__tests__/data/sdkman-java-versions.csv index 5c75a44c9..edbdc265c 100644 --- a/__tests__/data/sdkman-java-versions.csv +++ b/__tests__/data/sdkman-java-versions.csv @@ -2,7 +2,7 @@ 7.0.352-zulu, 7.0.352 8.0.282-trava, 8.0.282 8.0.432-albba, 8.0.432 -8.0.432-amzn, 8.0.432 +8.0.432-amzn, 8 8.0.432-kona, 8.0.432 8.0.432-librca, 8.0.432 8.0.432-sem, 8.0.432 @@ -10,7 +10,7 @@ 8.0.432-zulu, 8.0.432 8.0.432.fx-librca, 8.0.432 8.0.432.fx-zulu, 8.0.432 -8.0.442-amzn, 8.0.442 +8.0.442-amzn, 8 8.0.442-librca, 8.0.442 8.0.442-tem, 8.0.442 8.0.442-zulu, 8.0.442 @@ -19,7 +19,7 @@ 11.0.14.1-jbr, 11.0.14 11.0.15-trava, 11.0.15 11.0.25-albba, 11.0.25 -11.0.25-amzn, 11.0.25 +11.0.25-amzn, 11 11.0.25-kona, 11.0.25 11.0.25-librca, 11.0.25 11.0.25-ms, 11.0.25 @@ -29,7 +29,7 @@ 11.0.25-zulu, 11.0.25 11.0.25.fx-librca, 11.0.25 11.0.25.fx-zulu, 11.0.25 -11.0.26-amzn, 11.0.26 +11.0.26-amzn, 11 11.0.26-librca, 11.0.26 11.0.26-ms, 11.0.26 11.0.26-sapmchn, 11.0.26 @@ -40,7 +40,7 @@ 17.0.12-jbr, 17.0.12 17.0.12-oracle, 17.0.12 17.0.13-albba, 17.0.13 -17.0.13-amzn, 17.0.13 +17.0.13-amzn, 17 17.0.13-kona, 17.0.13 17.0.13-librca, 17.0.13 17.0.13-ms, 17.0.13 @@ -52,7 +52,7 @@ 17.0.13.crac-zulu, 17.0.13 17.0.13.fx-librca, 17.0.13 17.0.13.fx-zulu, 17.0.13 -17.0.14-amzn, 17.0.14 +17.0.14-amzn, 17 17.0.14-librca, 17.0.14 17.0.14-ms, 17.0.14 17.0.14-sapmchn, 17.0.14 @@ -62,7 +62,7 @@ 17.0.9-graalce, 17.0.9 21.0.2-graalce, 21.0.2 21.0.2-open, 21.0.2 -21.0.5-amzn, 21.0.5 +21.0.5-amzn, 21 21.0.5-graal, 21.0.5 21.0.5-jbr, 21.0.5 21.0.5-kona, 21.0.5 @@ -77,7 +77,7 @@ 21.0.5.crac-zulu, 21.0.5 21.0.5.fx-librca, 21.0.5 21.0.5.fx-zulu, 21.0.5 -21.0.6-amzn, 21.0.6 +21.0.6-amzn, 21 21.0.6-graal, 21.0.6 21.0.6-librca, 21.0.6 21.0.6-ms, 21.0.6 @@ -94,7 +94,7 @@ 22.3.5.r17-mandrel, 22.3.5 22.3.5.r17-nik, 22.3.5 23-open, 23 -23.0.1-amzn, 23.0.1 +23.0.1-amzn, 23 23.0.1-graal, 23.0.1 23.0.1-graalce, 23.0.1 23.0.1-librca, 23.0.1 @@ -106,7 +106,7 @@ 23.0.1.crac-zulu, 23.0.1 23.0.1.fx-librca, 23.0.1 23.0.1.fx-zulu, 23.0.1 -23.0.2-amzn, 23.0.2 +23.0.2-amzn, 23 23.0.2-graal, 23.0.2 23.0.2-graalce, 23.0.2 23.0.2-librca, 23.0.2 diff --git a/__tests__/util.test.ts b/__tests__/util.test.ts index 310a180ac..259d2171b 100644 --- a/__tests__/util.test.ts +++ b/__tests__/util.test.ts @@ -166,15 +166,41 @@ describe('validatePaginationUrl', () => { describe('getVersionFromFileContent', () => { describe('.sdkmanrc', () => { it.each([ - ['java=11.0.20.1-tem', '11.0.20'], - ['java = 11.0.20.1-tem', '11.0.20'], - ['java=11.0.20.1-tem # a comment in sdkmanrc', '11.0.20'], - ['java=11.0.20.1-tem\n#java=21.0.20.1-tem\n', '11.0.20'], // choose first match - ['java=11.0.20.1-tem\njava=21.0.20.1-tem\n', '11.0.20'], // choose first match - ['#java=11.0.20.1-tem\njava=21.0.20.1-tem\n', '21.0.20'] // first one is 'commented' in .sdkmanrc - ])('parsing %s should return %s', (content: string, expected: string) => { + ['java=11.0.20.1-tem', '11.0.20', 'temurin'], + ['java = 11.0.20.1-tem', '11.0.20', 'temurin'], + ['java=11.0.20.1-tem # a comment in sdkmanrc', '11.0.20', 'temurin'], + ['java=11.0.20.1-tem\n#java=21.0.20.1-tem\n', '11.0.20', 'temurin'], // choose first match + ['java=11.0.20.1-tem\njava=21.0.20.1-tem\n', '11.0.20', 'temurin'], // choose first match + ['#java=11.0.20.1-tem\njava=21.0.20.1-tem\n', '21.0.20', 'temurin'], // first one is 'commented' in .sdkmanrc + ['java=21.0.5-zulu', '21.0.5', 'zulu'], + ['java=17.0.13-amzn', '17', 'corretto'], + ['java=21.0.5-graal', '21.0.5', 'graalvm'], + ['java=17.0.9-graalce', '17.0.9', 'graalvm'], + ['java=11.0.25-librca', '11.0.25', 'liberica'], + ['java=11.0.25-ms', '11.0.25', 'microsoft'], + ['java=21.0.5-oracle', '21.0.5', 'oracle'], + ['java=11.0.25-sapmchn', '11.0.25', 'sapmachine'], + ['java=21.0.5-jbr', '21.0.5', 'jetbrains'], + ['java=11.0.25-sem', '11.0.25', 'temurin'], + ['java=17.0.13-dragonwell', '17.0.13', 'dragonwell'] + ])('parsing %s should return version %s and distribution %s', (content: string, expectedVersion: string, expectedDist: string) => { const actual = getVersionFromFileContent(content, 'openjdk', '.sdkmanrc'); - expect(actual).toBe(expected); + expect(actual?.version).toBe(expectedVersion); + expect(actual?.distribution).toBe(expectedDist); + }); + + it('should warn and return undefined distribution for unknown identifier', () => { + const warnSpy = jest.spyOn(require('@actions/core'), 'warning'); + const actual = getVersionFromFileContent('java=21.0.5-unknown', 'temurin', '.sdkmanrc'); + expect(actual?.version).toBe('21.0.5'); + expect(actual?.distribution).toBeUndefined(); + expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('Unknown SDKMAN distribution identifier')); + }); + + it('should return version without distribution when no suffix provided', () => { + const actual = getVersionFromFileContent('java=11.0.20', 'temurin', '.sdkmanrc'); + expect(actual?.version).toBe('11.0.20'); + expect(actual?.distribution).toBeUndefined(); }); describe('known versions', () => { @@ -193,7 +219,7 @@ describe('getVersionFromFileContent', () => { 'openjdk', '.sdkmanrc' ); - expect(actual).toBe(expected); + expect(actual?.version).toBe(expected); } ); }); diff --git a/action.yml b/action.yml index d5f46bbed..c64a8c158 100644 --- a/action.yml +++ b/action.yml @@ -10,8 +10,8 @@ inputs: description: 'The path to a file containing the Java version to set up (.java-version, .tool-versions, .sdkmanrc). Used when java-version is not set. See examples of supported syntax in README file' required: false distribution: - description: 'Java distribution. See the list of supported distributions in README file' - required: true + description: 'Java distribution. See the list of supported distributions in README file. When using .sdkmanrc with a distribution suffix (e.g., java=21.0.5-tem), this input is optional.' + required: false java-package: description: 'The package type (jdk, jre, jdk+fx, jre+fx)' required: false diff --git a/dist/cleanup/index.js b/dist/cleanup/index.js index 5a1db9633..afd634347 100644 --- a/dist/cleanup/index.js +++ b/dist/cleanup/index.js @@ -52314,8 +52314,9 @@ function isCacheFeatureAvailable() { } exports.isCacheFeatureAvailable = isCacheFeatureAvailable; function getVersionFromFileContent(content, distributionName, versionFile) { - var _a, _b, _c, _d, _e; + var _a, _b, _c; let javaVersionRegExp; + let extractedDistribution; function getFileName(versionFile) { return path_1.default.basename(versionFile); } @@ -52325,14 +52326,22 @@ function getVersionFromFileContent(content, distributionName, versionFile) { /^java\s+(?:\S*-)?(?\d+(?:\.\d+)*([+_.-](?:openj9[-._]?\d[\w.-]*|java\d+|jre[-_\w]*|OpenJDK\d+[\w_.-]*|[a-z0-9]+))*)/im; } else if (versionFileName == '.sdkmanrc') { - javaVersionRegExp = /^java\s*=\s*(?[^-]+)/m; + // Match both version and optional distribution identifier + javaVersionRegExp = /^java\s*=\s*(?[^-\s]+)(?:-(?[a-z0-9]+))?/m; } else { javaVersionRegExp = /(?(?<=(^|\s|-))(\d+\S*))(\s|$)/; } - const capturedVersion = ((_b = (_a = content.match(javaVersionRegExp)) === null || _a === void 0 ? void 0 : _a.groups) === null || _b === void 0 ? void 0 : _b.version) - ? (_d = (_c = content.match(javaVersionRegExp)) === null || _c === void 0 ? void 0 : _c.groups) === null || _d === void 0 ? void 0 : _d.version + const match = content.match(javaVersionRegExp); + const capturedVersion = ((_a = match === null || match === void 0 ? void 0 : match.groups) === null || _a === void 0 ? void 0 : _a.version) + ? match.groups.version : ''; + // Extract distribution from .sdkmanrc file + if (versionFileName == '.sdkmanrc' && ((_b = match === null || match === void 0 ? void 0 : match.groups) === null || _b === void 0 ? void 0 : _b.distribution)) { + const sdkmanDist = match.groups.distribution; + extractedDistribution = mapSdkmanDistribution(sdkmanDist); + core.debug(`Parsed distribution '${extractedDistribution}' from SDKMAN identifier '${sdkmanDist}'`); + } core.debug(`Parsed version '${capturedVersion}' from file '${versionFileName}'`); if (!capturedVersion) { return null; @@ -52346,13 +52355,40 @@ function getVersionFromFileContent(content, distributionName, versionFile) { if (!version) { return null; } - if (constants_1.DISTRIBUTIONS_ONLY_MAJOR_VERSION.includes(distributionName)) { - const coerceVersion = (_e = semver.coerce(version)) !== null && _e !== void 0 ? _e : version; + // Apply DISTRIBUTIONS_ONLY_MAJOR_VERSION logic whenever the effective distribution + // (either explicitly provided or extracted from the version file) is in the list. + if (constants_1.DISTRIBUTIONS_ONLY_MAJOR_VERSION.includes(extractedDistribution || distributionName)) { + const coerceVersion = (_c = semver.coerce(version)) !== null && _c !== void 0 ? _c : version; version = semver.major(coerceVersion).toString(); } - return version.toString(); + return { + version: version.toString(), + distribution: extractedDistribution + }; } exports.getVersionFromFileContent = getVersionFromFileContent; +// Map SDKMAN distribution identifiers to setup-java distribution names +function mapSdkmanDistribution(sdkmanDist) { + const distributionMap = { + 'tem': 'temurin', + 'sem': 'temurin', + 'zulu': 'zulu', + 'amzn': 'corretto', + 'graal': 'graalvm', + 'graalce': 'graalvm', + 'librca': 'liberica', + 'ms': 'microsoft', + 'oracle': 'oracle', + 'sapmchn': 'sapmachine', + 'jbr': 'jetbrains', + 'dragonwell': 'dragonwell' + }; + const mapped = distributionMap[sdkmanDist.toLowerCase()]; + if (!mapped) { + core.warning(`Unknown SDKMAN distribution identifier '${sdkmanDist}'. Please specify the distribution explicitly.`); + } + return mapped; +} // By convention, action expects version 8 in the format `8.*` instead of `1.8` function avoidOldNotation(content) { return content.startsWith('1.') ? content.substring(2) : content; diff --git a/dist/setup/index.js b/dist/setup/index.js index 434039045..6e1a98753 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -80750,9 +80750,7 @@ function run() { return __awaiter(this, void 0, void 0, function* () { try { const versions = core.getMultilineInput(constants.INPUT_JAVA_VERSION); - const distributionName = core.getInput(constants.INPUT_DISTRIBUTION, { - required: true - }); + let distributionName = core.getInput(constants.INPUT_DISTRIBUTION); const versionFile = core.getInput(constants.INPUT_JAVA_VERSION_FILE); const architecture = core.getInput(constants.INPUT_ARCHITECTURE); const packageType = core.getInput(constants.INPUT_JAVA_PACKAGE); @@ -80768,26 +80766,48 @@ function run() { if (!versions.length && !versionFile) { throw new Error('java-version or java-version-file input expected'); } - const installerInputsOptions = { - architecture, - packageType, - checkLatest, - distributionName, - jdkFile, - toolchainIds - }; if (!versions.length) { core.debug('java-version input is empty, looking for java-version-file input'); const content = fs_1.default.readFileSync(versionFile).toString().trim(); - const version = (0, util_1.getVersionFromFileContent)(content, distributionName, versionFile); - core.debug(`Parsed version from file '${version}'`); - if (!version) { + const versionInfo = (0, util_1.getVersionFromFileContent)(content, distributionName, versionFile); + core.debug(`Parsed version from file '${versionInfo === null || versionInfo === void 0 ? void 0 : versionInfo.version}'`); + if (!versionInfo) { throw new Error(`No supported version was found in file ${versionFile}`); } - yield installVersion(version, installerInputsOptions); + // Use distribution from file if available, otherwise use the input + if (versionInfo.distribution) { + core.info(`Using distribution '${versionInfo.distribution}' from ${versionFile}`); + distributionName = versionInfo.distribution; + } + else if (!distributionName) { + throw new Error('distribution input is required when not specified in the version file'); + } + const installerInputsOptions = { + architecture, + packageType, + checkLatest, + distributionName, + jdkFile, + toolchainIds + }; + yield installVersion(versionInfo.version, installerInputsOptions); } - for (const [index, version] of versions.entries()) { - yield installVersion(version, installerInputsOptions, index); + else { + // When using java-version input, distribution is still required + if (!distributionName) { + throw new Error('distribution input is required'); + } + const installerInputsOptions = { + architecture, + packageType, + checkLatest, + distributionName, + jdkFile, + toolchainIds + }; + for (const [index, version] of versions.entries()) { + yield installVersion(version, installerInputsOptions, index); + } } core.endGroup(); const matchersPath = path.join(__dirname, '..', '..', '.github'); @@ -81145,8 +81165,9 @@ function isCacheFeatureAvailable() { } exports.isCacheFeatureAvailable = isCacheFeatureAvailable; function getVersionFromFileContent(content, distributionName, versionFile) { - var _a, _b, _c, _d, _e; + var _a, _b, _c; let javaVersionRegExp; + let extractedDistribution; function getFileName(versionFile) { return path_1.default.basename(versionFile); } @@ -81156,14 +81177,22 @@ function getVersionFromFileContent(content, distributionName, versionFile) { /^java\s+(?:\S*-)?(?\d+(?:\.\d+)*([+_.-](?:openj9[-._]?\d[\w.-]*|java\d+|jre[-_\w]*|OpenJDK\d+[\w_.-]*|[a-z0-9]+))*)/im; } else if (versionFileName == '.sdkmanrc') { - javaVersionRegExp = /^java\s*=\s*(?[^-]+)/m; + // Match both version and optional distribution identifier + javaVersionRegExp = /^java\s*=\s*(?[^-\s]+)(?:-(?[a-z0-9]+))?/m; } else { javaVersionRegExp = /(?(?<=(^|\s|-))(\d+\S*))(\s|$)/; } - const capturedVersion = ((_b = (_a = content.match(javaVersionRegExp)) === null || _a === void 0 ? void 0 : _a.groups) === null || _b === void 0 ? void 0 : _b.version) - ? (_d = (_c = content.match(javaVersionRegExp)) === null || _c === void 0 ? void 0 : _c.groups) === null || _d === void 0 ? void 0 : _d.version + const match = content.match(javaVersionRegExp); + const capturedVersion = ((_a = match === null || match === void 0 ? void 0 : match.groups) === null || _a === void 0 ? void 0 : _a.version) + ? match.groups.version : ''; + // Extract distribution from .sdkmanrc file + if (versionFileName == '.sdkmanrc' && ((_b = match === null || match === void 0 ? void 0 : match.groups) === null || _b === void 0 ? void 0 : _b.distribution)) { + const sdkmanDist = match.groups.distribution; + extractedDistribution = mapSdkmanDistribution(sdkmanDist); + core.debug(`Parsed distribution '${extractedDistribution}' from SDKMAN identifier '${sdkmanDist}'`); + } core.debug(`Parsed version '${capturedVersion}' from file '${versionFileName}'`); if (!capturedVersion) { return null; @@ -81177,13 +81206,40 @@ function getVersionFromFileContent(content, distributionName, versionFile) { if (!version) { return null; } - if (constants_1.DISTRIBUTIONS_ONLY_MAJOR_VERSION.includes(distributionName)) { - const coerceVersion = (_e = semver.coerce(version)) !== null && _e !== void 0 ? _e : version; + // Apply DISTRIBUTIONS_ONLY_MAJOR_VERSION logic whenever the effective distribution + // (either explicitly provided or extracted from the version file) is in the list. + if (constants_1.DISTRIBUTIONS_ONLY_MAJOR_VERSION.includes(extractedDistribution || distributionName)) { + const coerceVersion = (_c = semver.coerce(version)) !== null && _c !== void 0 ? _c : version; version = semver.major(coerceVersion).toString(); } - return version.toString(); + return { + version: version.toString(), + distribution: extractedDistribution + }; } exports.getVersionFromFileContent = getVersionFromFileContent; +// Map SDKMAN distribution identifiers to setup-java distribution names +function mapSdkmanDistribution(sdkmanDist) { + const distributionMap = { + 'tem': 'temurin', + 'sem': 'temurin', + 'zulu': 'zulu', + 'amzn': 'corretto', + 'graal': 'graalvm', + 'graalce': 'graalvm', + 'librca': 'liberica', + 'ms': 'microsoft', + 'oracle': 'oracle', + 'sapmchn': 'sapmachine', + 'jbr': 'jetbrains', + 'dragonwell': 'dragonwell' + }; + const mapped = distributionMap[sdkmanDist.toLowerCase()]; + if (!mapped) { + core.warning(`Unknown SDKMAN distribution identifier '${sdkmanDist}'. Please specify the distribution explicitly.`); + } + return mapped; +} // By convention, action expects version 8 in the format `8.*` instead of `1.8` function avoidOldNotation(content) { return content.startsWith('1.') ? content.substring(2) : content; diff --git a/src/setup-java.ts b/src/setup-java.ts index 73baf33a7..413f47782 100644 --- a/src/setup-java.ts +++ b/src/setup-java.ts @@ -16,9 +16,7 @@ import {JavaInstallerOptions} from './distributions/base-models'; async function run() { try { const versions = core.getMultilineInput(constants.INPUT_JAVA_VERSION); - const distributionName = core.getInput(constants.INPUT_DISTRIBUTION, { - required: true - }); + let distributionName = core.getInput(constants.INPUT_DISTRIBUTION); const versionFile = core.getInput(constants.INPUT_JAVA_VERSION_FILE); const architecture = core.getInput(constants.INPUT_ARCHITECTURE); const packageType = core.getInput(constants.INPUT_JAVA_PACKAGE); @@ -40,39 +38,63 @@ async function run() { throw new Error('java-version or java-version-file input expected'); } - const installerInputsOptions: installerInputsOptions = { - architecture, - packageType, - checkLatest, - distributionName, - jdkFile, - toolchainIds - }; - if (!versions.length) { core.debug( 'java-version input is empty, looking for java-version-file input' ); const content = fs.readFileSync(versionFile).toString().trim(); - const version = getVersionFromFileContent( + const versionInfo = getVersionFromFileContent( content, distributionName, versionFile ); - core.debug(`Parsed version from file '${version}'`); + core.debug(`Parsed version from file '${versionInfo?.version}'`); - if (!version) { + if (!versionInfo) { throw new Error( `No supported version was found in file ${versionFile}` ); } - await installVersion(version, installerInputsOptions); - } + // Use distribution from file if available, otherwise use the input + if (versionInfo.distribution) { + core.info(`Using distribution '${versionInfo.distribution}' from ${versionFile}`); + distributionName = versionInfo.distribution; + } else if (!distributionName) { + throw new Error( + 'distribution input is required when not specified in the version file' + ); + } - for (const [index, version] of versions.entries()) { - await installVersion(version, installerInputsOptions, index); + const installerInputsOptions: installerInputsOptions = { + architecture, + packageType, + checkLatest, + distributionName, + jdkFile, + toolchainIds + }; + + await installVersion(versionInfo.version, installerInputsOptions); + } else { + // When using java-version input, distribution is still required + if (!distributionName) { + throw new Error('distribution input is required'); + } + + const installerInputsOptions: installerInputsOptions = { + architecture, + packageType, + checkLatest, + distributionName, + jdkFile, + toolchainIds + }; + + for (const [index, version] of versions.entries()) { + await installVersion(version, installerInputsOptions, index); + } } core.endGroup(); const matchersPath = path.join(__dirname, '..', '..', '.github'); diff --git a/src/util.ts b/src/util.ts index 679c9fe34..8fa08a7a7 100644 --- a/src/util.ts +++ b/src/util.ts @@ -127,12 +127,18 @@ export function isCacheFeatureAvailable(): boolean { return false; } +export interface VersionInfo { + version: string; + distribution?: string; +} + export function getVersionFromFileContent( content: string, distributionName: string, versionFile: string -): string | null { +): VersionInfo | null { let javaVersionRegExp: RegExp; + let extractedDistribution: string | undefined; function getFileName(versionFile: string) { return path.basename(versionFile); @@ -143,15 +149,26 @@ export function getVersionFromFileContent( javaVersionRegExp = /^java\s+(?:\S*-)?(?\d+(?:\.\d+)*([+_.-](?:openj9[-._]?\d[\w.-]*|java\d+|jre[-_\w]*|OpenJDK\d+[\w_.-]*|[a-z0-9]+))*)/im; } else if (versionFileName == '.sdkmanrc') { - javaVersionRegExp = /^java\s*=\s*(?[^-]+)/m; + // Match both version and optional distribution identifier + javaVersionRegExp = /^java\s*=\s*(?[^-\s]+)(?:-(?[a-z0-9]+))?/m; } else { javaVersionRegExp = /(?(?<=(^|\s|-))(\d+\S*))(\s|$)/; } - const capturedVersion = content.match(javaVersionRegExp)?.groups?.version - ? (content.match(javaVersionRegExp)?.groups?.version as string) + const match = content.match(javaVersionRegExp); + const capturedVersion = match?.groups?.version + ? (match.groups.version as string) : ''; + // Extract distribution from .sdkmanrc file + if (versionFileName == '.sdkmanrc' && match?.groups?.distribution) { + const sdkmanDist = match.groups.distribution; + extractedDistribution = mapSdkmanDistribution(sdkmanDist); + core.debug( + `Parsed distribution '${extractedDistribution}' from SDKMAN identifier '${sdkmanDist}'` + ); + } + core.debug( `Parsed version '${capturedVersion}' from file '${versionFileName}'` ); @@ -172,12 +189,43 @@ export function getVersionFromFileContent( return null; } - if (DISTRIBUTIONS_ONLY_MAJOR_VERSION.includes(distributionName)) { + // Apply DISTRIBUTIONS_ONLY_MAJOR_VERSION logic whenever the effective distribution + // (either explicitly provided or extracted from the version file) is in the list. + if (DISTRIBUTIONS_ONLY_MAJOR_VERSION.includes(extractedDistribution || distributionName)) { const coerceVersion = semver.coerce(version) ?? version; version = semver.major(coerceVersion).toString(); } - return version.toString(); + return { + version: version.toString(), + distribution: extractedDistribution + }; +} + +// Map SDKMAN distribution identifiers to setup-java distribution names +function mapSdkmanDistribution(sdkmanDist: string): string | undefined { + const distributionMap: Record = { + 'tem': 'temurin', + 'sem': 'temurin', + 'zulu': 'zulu', + 'amzn': 'corretto', + 'graal': 'graalvm', + 'graalce': 'graalvm', + 'librca': 'liberica', + 'ms': 'microsoft', + 'oracle': 'oracle', + 'sapmchn': 'sapmachine', + 'jbr': 'jetbrains', + 'dragonwell': 'dragonwell' + }; + + const mapped = distributionMap[sdkmanDist.toLowerCase()]; + if (!mapped) { + core.warning( + `Unknown SDKMAN distribution identifier '${sdkmanDist}'. Please specify the distribution explicitly.` + ); + } + return mapped; } // By convention, action expects version 8 in the format `8.*` instead of `1.8` From 433b953ac81d90b2234ca1fc6283e8a5d535e042 Mon Sep 17 00:00:00 2001 From: lukaszgyg Date: Tue, 24 Mar 2026 19:40:06 +0100 Subject: [PATCH 2/4] fix: align SDKMAN sem identifier mapping --- __tests__/util.test.ts | 4 ++-- dist/cleanup/index.js | 2 +- dist/setup/index.js | 2 +- src/util.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/__tests__/util.test.ts b/__tests__/util.test.ts index 259d2171b..890b17286 100644 --- a/__tests__/util.test.ts +++ b/__tests__/util.test.ts @@ -181,7 +181,7 @@ describe('getVersionFromFileContent', () => { ['java=21.0.5-oracle', '21.0.5', 'oracle'], ['java=11.0.25-sapmchn', '11.0.25', 'sapmachine'], ['java=21.0.5-jbr', '21.0.5', 'jetbrains'], - ['java=11.0.25-sem', '11.0.25', 'temurin'], + ['java=11.0.25-sem', '11.0.25', 'semeru'], ['java=17.0.13-dragonwell', '17.0.13', 'dragonwell'] ])('parsing %s should return version %s and distribution %s', (content: string, expectedVersion: string, expectedDist: string) => { const actual = getVersionFromFileContent(content, 'openjdk', '.sdkmanrc'); @@ -190,7 +190,7 @@ describe('getVersionFromFileContent', () => { }); it('should warn and return undefined distribution for unknown identifier', () => { - const warnSpy = jest.spyOn(require('@actions/core'), 'warning'); + const warnSpy = jest.spyOn(core, 'warning'); const actual = getVersionFromFileContent('java=21.0.5-unknown', 'temurin', '.sdkmanrc'); expect(actual?.version).toBe('21.0.5'); expect(actual?.distribution).toBeUndefined(); diff --git a/dist/cleanup/index.js b/dist/cleanup/index.js index afd634347..a6192d3cb 100644 --- a/dist/cleanup/index.js +++ b/dist/cleanup/index.js @@ -52371,7 +52371,7 @@ exports.getVersionFromFileContent = getVersionFromFileContent; function mapSdkmanDistribution(sdkmanDist) { const distributionMap = { 'tem': 'temurin', - 'sem': 'temurin', + 'sem': 'semeru', 'zulu': 'zulu', 'amzn': 'corretto', 'graal': 'graalvm', diff --git a/dist/setup/index.js b/dist/setup/index.js index 6e1a98753..ab6723cd5 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -81222,7 +81222,7 @@ exports.getVersionFromFileContent = getVersionFromFileContent; function mapSdkmanDistribution(sdkmanDist) { const distributionMap = { 'tem': 'temurin', - 'sem': 'temurin', + 'sem': 'semeru', 'zulu': 'zulu', 'amzn': 'corretto', 'graal': 'graalvm', diff --git a/src/util.ts b/src/util.ts index 8fa08a7a7..fa1d88822 100644 --- a/src/util.ts +++ b/src/util.ts @@ -206,7 +206,7 @@ export function getVersionFromFileContent( function mapSdkmanDistribution(sdkmanDist: string): string | undefined { const distributionMap: Record = { 'tem': 'temurin', - 'sem': 'temurin', + 'sem': 'semeru', 'zulu': 'zulu', 'amzn': 'corretto', 'graal': 'graalvm', From bdc498b5039b20e64b53ceee848c82a089d45989 Mon Sep 17 00:00:00 2001 From: lukaszgyg Date: Tue, 24 Mar 2026 19:49:56 +0100 Subject: [PATCH 3/4] fix: support SDKMAN albba identifier --- __tests__/util.test.ts | 34 ++++++++++++++++++++++++++-------- dist/cleanup/index.js | 28 +++++++++++++++------------- dist/setup/index.js | 28 +++++++++++++++------------- src/setup-java.ts | 4 +++- src/util.ts | 34 ++++++++++++++++++++-------------- 5 files changed, 79 insertions(+), 49 deletions(-) diff --git a/__tests__/util.test.ts b/__tests__/util.test.ts index 890b17286..48f598d44 100644 --- a/__tests__/util.test.ts +++ b/__tests__/util.test.ts @@ -173,6 +173,7 @@ describe('getVersionFromFileContent', () => { ['java=11.0.20.1-tem\njava=21.0.20.1-tem\n', '11.0.20', 'temurin'], // choose first match ['#java=11.0.20.1-tem\njava=21.0.20.1-tem\n', '21.0.20', 'temurin'], // first one is 'commented' in .sdkmanrc ['java=21.0.5-zulu', '21.0.5', 'zulu'], + ['java=17.0.13-albba', '17.0.13', 'dragonwell'], ['java=17.0.13-amzn', '17', 'corretto'], ['java=21.0.5-graal', '21.0.5', 'graalvm'], ['java=17.0.9-graalce', '17.0.9', 'graalvm'], @@ -183,22 +184,39 @@ describe('getVersionFromFileContent', () => { ['java=21.0.5-jbr', '21.0.5', 'jetbrains'], ['java=11.0.25-sem', '11.0.25', 'semeru'], ['java=17.0.13-dragonwell', '17.0.13', 'dragonwell'] - ])('parsing %s should return version %s and distribution %s', (content: string, expectedVersion: string, expectedDist: string) => { - const actual = getVersionFromFileContent(content, 'openjdk', '.sdkmanrc'); - expect(actual?.version).toBe(expectedVersion); - expect(actual?.distribution).toBe(expectedDist); - }); + ])( + 'parsing %s should return version %s and distribution %s', + (content: string, expectedVersion: string, expectedDist: string) => { + const actual = getVersionFromFileContent( + content, + 'openjdk', + '.sdkmanrc' + ); + expect(actual?.version).toBe(expectedVersion); + expect(actual?.distribution).toBe(expectedDist); + } + ); it('should warn and return undefined distribution for unknown identifier', () => { const warnSpy = jest.spyOn(core, 'warning'); - const actual = getVersionFromFileContent('java=21.0.5-unknown', 'temurin', '.sdkmanrc'); + const actual = getVersionFromFileContent( + 'java=21.0.5-unknown', + 'temurin', + '.sdkmanrc' + ); expect(actual?.version).toBe('21.0.5'); expect(actual?.distribution).toBeUndefined(); - expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('Unknown SDKMAN distribution identifier')); + expect(warnSpy).toHaveBeenCalledWith( + expect.stringContaining('Unknown SDKMAN distribution identifier') + ); }); it('should return version without distribution when no suffix provided', () => { - const actual = getVersionFromFileContent('java=11.0.20', 'temurin', '.sdkmanrc'); + const actual = getVersionFromFileContent( + 'java=11.0.20', + 'temurin', + '.sdkmanrc' + ); expect(actual?.version).toBe('11.0.20'); expect(actual?.distribution).toBeUndefined(); }); diff --git a/dist/cleanup/index.js b/dist/cleanup/index.js index a6192d3cb..07ac1d67e 100644 --- a/dist/cleanup/index.js +++ b/dist/cleanup/index.js @@ -52327,7 +52327,8 @@ function getVersionFromFileContent(content, distributionName, versionFile) { } else if (versionFileName == '.sdkmanrc') { // Match both version and optional distribution identifier - javaVersionRegExp = /^java\s*=\s*(?[^-\s]+)(?:-(?[a-z0-9]+))?/m; + javaVersionRegExp = + /^java\s*=\s*(?[^-\s]+)(?:-(?[a-z0-9]+))?/m; } else { javaVersionRegExp = /(?(?<=(^|\s|-))(\d+\S*))(\s|$)/; @@ -52370,18 +52371,19 @@ exports.getVersionFromFileContent = getVersionFromFileContent; // Map SDKMAN distribution identifiers to setup-java distribution names function mapSdkmanDistribution(sdkmanDist) { const distributionMap = { - 'tem': 'temurin', - 'sem': 'semeru', - 'zulu': 'zulu', - 'amzn': 'corretto', - 'graal': 'graalvm', - 'graalce': 'graalvm', - 'librca': 'liberica', - 'ms': 'microsoft', - 'oracle': 'oracle', - 'sapmchn': 'sapmachine', - 'jbr': 'jetbrains', - 'dragonwell': 'dragonwell' + tem: 'temurin', + sem: 'semeru', + albba: 'dragonwell', + zulu: 'zulu', + amzn: 'corretto', + graal: 'graalvm', + graalce: 'graalvm', + librca: 'liberica', + ms: 'microsoft', + oracle: 'oracle', + sapmchn: 'sapmachine', + jbr: 'jetbrains', + dragonwell: 'dragonwell' }; const mapped = distributionMap[sdkmanDist.toLowerCase()]; if (!mapped) { diff --git a/dist/setup/index.js b/dist/setup/index.js index ab6723cd5..1f480a413 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -81178,7 +81178,8 @@ function getVersionFromFileContent(content, distributionName, versionFile) { } else if (versionFileName == '.sdkmanrc') { // Match both version and optional distribution identifier - javaVersionRegExp = /^java\s*=\s*(?[^-\s]+)(?:-(?[a-z0-9]+))?/m; + javaVersionRegExp = + /^java\s*=\s*(?[^-\s]+)(?:-(?[a-z0-9]+))?/m; } else { javaVersionRegExp = /(?(?<=(^|\s|-))(\d+\S*))(\s|$)/; @@ -81221,18 +81222,19 @@ exports.getVersionFromFileContent = getVersionFromFileContent; // Map SDKMAN distribution identifiers to setup-java distribution names function mapSdkmanDistribution(sdkmanDist) { const distributionMap = { - 'tem': 'temurin', - 'sem': 'semeru', - 'zulu': 'zulu', - 'amzn': 'corretto', - 'graal': 'graalvm', - 'graalce': 'graalvm', - 'librca': 'liberica', - 'ms': 'microsoft', - 'oracle': 'oracle', - 'sapmchn': 'sapmachine', - 'jbr': 'jetbrains', - 'dragonwell': 'dragonwell' + tem: 'temurin', + sem: 'semeru', + albba: 'dragonwell', + zulu: 'zulu', + amzn: 'corretto', + graal: 'graalvm', + graalce: 'graalvm', + librca: 'liberica', + ms: 'microsoft', + oracle: 'oracle', + sapmchn: 'sapmachine', + jbr: 'jetbrains', + dragonwell: 'dragonwell' }; const mapped = distributionMap[sdkmanDist.toLowerCase()]; if (!mapped) { diff --git a/src/setup-java.ts b/src/setup-java.ts index 413f47782..de0f5abd9 100644 --- a/src/setup-java.ts +++ b/src/setup-java.ts @@ -59,7 +59,9 @@ async function run() { // Use distribution from file if available, otherwise use the input if (versionInfo.distribution) { - core.info(`Using distribution '${versionInfo.distribution}' from ${versionFile}`); + core.info( + `Using distribution '${versionInfo.distribution}' from ${versionFile}` + ); distributionName = versionInfo.distribution; } else if (!distributionName) { throw new Error( diff --git a/src/util.ts b/src/util.ts index fa1d88822..19bbbf04b 100644 --- a/src/util.ts +++ b/src/util.ts @@ -150,7 +150,8 @@ export function getVersionFromFileContent( /^java\s+(?:\S*-)?(?\d+(?:\.\d+)*([+_.-](?:openj9[-._]?\d[\w.-]*|java\d+|jre[-_\w]*|OpenJDK\d+[\w_.-]*|[a-z0-9]+))*)/im; } else if (versionFileName == '.sdkmanrc') { // Match both version and optional distribution identifier - javaVersionRegExp = /^java\s*=\s*(?[^-\s]+)(?:-(?[a-z0-9]+))?/m; + javaVersionRegExp = + /^java\s*=\s*(?[^-\s]+)(?:-(?[a-z0-9]+))?/m; } else { javaVersionRegExp = /(?(?<=(^|\s|-))(\d+\S*))(\s|$)/; } @@ -191,7 +192,11 @@ export function getVersionFromFileContent( // Apply DISTRIBUTIONS_ONLY_MAJOR_VERSION logic whenever the effective distribution // (either explicitly provided or extracted from the version file) is in the list. - if (DISTRIBUTIONS_ONLY_MAJOR_VERSION.includes(extractedDistribution || distributionName)) { + if ( + DISTRIBUTIONS_ONLY_MAJOR_VERSION.includes( + extractedDistribution || distributionName + ) + ) { const coerceVersion = semver.coerce(version) ?? version; version = semver.major(coerceVersion).toString(); } @@ -205,18 +210,19 @@ export function getVersionFromFileContent( // Map SDKMAN distribution identifiers to setup-java distribution names function mapSdkmanDistribution(sdkmanDist: string): string | undefined { const distributionMap: Record = { - 'tem': 'temurin', - 'sem': 'semeru', - 'zulu': 'zulu', - 'amzn': 'corretto', - 'graal': 'graalvm', - 'graalce': 'graalvm', - 'librca': 'liberica', - 'ms': 'microsoft', - 'oracle': 'oracle', - 'sapmchn': 'sapmachine', - 'jbr': 'jetbrains', - 'dragonwell': 'dragonwell' + tem: 'temurin', + sem: 'semeru', + albba: 'dragonwell', + zulu: 'zulu', + amzn: 'corretto', + graal: 'graalvm', + graalce: 'graalvm', + librca: 'liberica', + ms: 'microsoft', + oracle: 'oracle', + sapmchn: 'sapmachine', + jbr: 'jetbrains', + dragonwell: 'dragonwell' }; const mapped = distributionMap[sdkmanDist.toLowerCase()]; From 02f9c1e7ddf63b93c57a289a2c09eae68e084cdd Mon Sep 17 00:00:00 2001 From: Bruno Borges Date: Mon, 22 Jun 2026 12:43:54 -0400 Subject: [PATCH 4/4] docs: clarify sdkmanrc distribution inference scope Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- README.md | 4 ++-- action.yml | 2 +- docs/advanced-usage.md | 5 ++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 50147b5a9..410f7c2f4 100644 --- a/README.md +++ b/README.md @@ -36,9 +36,9 @@ For information about the latest releases, recent updates, and newly supported d - `java-version`: The Java version that is going to be set up. Takes a whole or [semver](#supported-version-syntax) Java version. If not specified, the action will expect `java-version-file` input to be specified. - - `java-version-file`: The path to a file containing java version. Supported file types are `.java-version` and `.tool-versions`. See more details in [about .java-version-file](docs/advanced-usage.md#Java-version-file). + - `java-version-file`: The path to a file containing java version. Supported file types are `.java-version`, `.tool-versions`, and `.sdkmanrc`. See more details in [about .java-version-file](docs/advanced-usage.md#Java-version-file). - - `distribution`: _(required)_ Java [distribution](#supported-distributions). + - `distribution`: Java [distribution](#supported-distributions). Required unless `java-version-file` points to `.sdkmanrc` with a recognized distribution suffix (for example `java=21.0.5-tem`). - `java-package`: The packaging variant of the chosen distribution. Possible values: `jdk`, `jre`, `jdk+fx`, `jre+fx`. Default value: `jdk`. diff --git a/action.yml b/action.yml index c64a8c158..adb233b01 100644 --- a/action.yml +++ b/action.yml @@ -10,7 +10,7 @@ inputs: description: 'The path to a file containing the Java version to set up (.java-version, .tool-versions, .sdkmanrc). Used when java-version is not set. See examples of supported syntax in README file' required: false distribution: - description: 'Java distribution. See the list of supported distributions in README file. When using .sdkmanrc with a distribution suffix (e.g., java=21.0.5-tem), this input is optional.' + description: 'Java distribution. See the list of supported distributions in README file. This input is required except when java-version-file points to .sdkmanrc with a recognized distribution suffix (e.g., java=21.0.5-tem).' required: false java-package: description: 'The package type (jdk, jre, jdk+fx, jre+fx)' diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index 1b1e4feea..dac034735 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -604,18 +604,17 @@ steps: Supported files are `.java-version`, `.tool-versions` and `.sdkmanrc`. * In `.java-version` file, only the version should be specified (e.g., 17.0.7). The `.java-version` file recognizes all variants of the version description according to [jenv](https://github.com/jenv/jenv). * In `.tool-versions` file, java version should be preceded by the java keyword (e.g., java 17.0.7). The `.tool-versions` file supports version specifications in accordance with [asdf](https://github.com/asdf-vm/asdf) standards, adhering to Semantic Versioning ([semver](https://semver.org/)). - * In `.sdkmanrc` file, java version should be preceded by the `java=` prefix (e.g., java=17.0.7-tem) and include the distribution. The `.sdkmanrc` file supports version specifications in accordance with [file format](https://sdkman.io/usage#env-command), see [Sdkman! documentation](https://sdkman.io/jdks) for more information. + * In `.sdkmanrc` file, java version should be preceded by the `java=` prefix (e.g., `java=17.0.7-tem`). When a recognized SDKMAN distribution suffix is present, setup-java can infer the `distribution` input automatically. Supported suffix mappings are: `tem` -> `temurin`, `sem` -> `semeru`, `albba`/`dragonwell` -> `dragonwell`, `zulu` -> `zulu`, `amzn` -> `corretto`, `graal`/`graalce` -> `graalvm`, `librca` -> `liberica`, `ms` -> `microsoft`, `oracle` -> `oracle`, `sapmchn` -> `sapmachine`, `jbr` -> `jetbrains`. Unrecognized suffixes require setting `distribution` explicitly. The `.sdkmanrc` file supports version specifications in accordance with [file format](https://sdkman.io/usage#env-command), see [Sdkman! documentation](https://sdkman.io/jdks) for more information. If both `java-version` and `java-version-file` **inputs** are provided, the `java-version` input will be used. -**Example step using `Sdkman!`**: +**Example step using `Sdkman!`** (distribution inferred from `.sdkmanrc`): ```yml - name: Setup java uses: actions/setup-java@v5 with: java-version-file: '.sdkmanrc' - distribution: 'temurin' ``` **Example `.sdkmanrc`**: