From 1df8dbefe2a8cbc99770194893dd902763bee34b Mon Sep 17 00:00:00 2001 From: Evgenii Korolevskii <102794661+e-korolevskii@users.noreply.github.com> Date: Tue, 13 Dec 2022 12:45:14 +0100 Subject: [PATCH] Add support for java.version file (#426) --- .github/workflows/e2e-versions.yml | 97 +++++++++++++++++++- README.md | 4 +- action.yml | 3 +- dist/cleanup/index.js | 34 ++++++- dist/setup/index.js | 111 ++++++++++++++++++----- docs/advanced-usage.md | 13 +++ src/constants.ts | 3 + src/distributions/microsoft/installer.ts | 2 +- src/setup-java.ts | 111 +++++++++++++++++------ src/util.ts | 40 +++++++- 10 files changed, 360 insertions(+), 58 deletions(-) diff --git a/.github/workflows/e2e-versions.yml b/.github/workflows/e2e-versions.yml index b0454f3e4..efc4e7408 100644 --- a/.github/workflows/e2e-versions.yml +++ b/.github/workflows/e2e-versions.yml @@ -240,4 +240,99 @@ jobs: run: bash __tests__/verify-java.sh "${{ matrix.version }}" "${{ steps.setup-java.outputs.path }}" shell: bash - # Only Microsoft provides AArch64. However, GitHub-hosted runners do not support this architecture. \ No newline at end of file + setup-java-version-both-version-inputs-presents: + name: ${{ matrix.distribution }} version (should be from input) - ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [macos-latest, windows-latest, ubuntu-latest] + distribution: ['temurin', 'microsoft', 'corretto' ] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Create .java-version file + shell: bash + run: echo "8" > .java-version + - name: setup-java + uses: ./ + id: setup-java + with: + distribution: ${{ matrix.distribution }} + java-version: 11 + java-version-file: '.java-version' + - name: Verify Java + run: bash __tests__/verify-java.sh "11" "${{ steps.setup-java.outputs.path }}" + shell: bash + + setup-java-version-from-file-major-notation: + name: ${{ matrix.distribution }} version from file X - ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [macos-latest, windows-latest, ubuntu-latest] + distribution: ['temurin', 'zulu', 'liberica', 'microsoft', 'corretto' ] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Create .java-version file + shell: bash + run: echo "11" > .java-version + - name: setup-java + uses: ./ + id: setup-java + with: + distribution: ${{ matrix.distribution }} + java-version-file: '.java-version' + - name: Verify Java + run: bash __tests__/verify-java.sh "11" "${{ steps.setup-java.outputs.path }}" + shell: bash + + setup-java-version-from-file-major-minor-patch-notation: + name: ${{ matrix.distribution }} version from file X.Y.Z - ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [macos-latest, windows-latest, ubuntu-latest] + distribution: [ 'adopt', 'adopt-openj9', 'zulu' ] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Create .java-version file + shell: bash + run: echo "11.0.2" > .java-version + - name: setup-java + uses: ./ + id: setup-java + with: + distribution: ${{ matrix.distribution }} + java-version-file: '.java-version' + - name: Verify Java + run: bash __tests__/verify-java.sh "11.0.2" "${{ steps.setup-java.outputs.path }}" + shell: bash + + setup-java-version-from-file-major-minor-patch-with-dist: + name: ${{ matrix.distribution }} version from file 'openjdk64-11.0.2' - ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [macos-latest, windows-latest, ubuntu-latest] + distribution: ['adopt', 'zulu', 'liberica' ] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Create .java-version file + shell: bash + run: echo "openjdk64-11.0.2" > .java-version + - name: setup-java + uses: ./ + id: setup-java + with: + distribution: ${{ matrix.distribution }} + java-version-file: '.java-version' + - name: Verify Java + run: bash __tests__/verify-java.sh "11.0.2" "${{ steps.setup-java.outputs.path }}" + shell: bash diff --git a/README.md b/README.md index 3812f6cf9..8ae5055bc 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,9 @@ This action allows you to work with Java and Scala projects. ## Usage - - `java-version`: _(required)_ The Java version to set up. Takes a whole or [semver](#supported-version-syntax) Java version. + - `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 the `.java-version` file. See more details in [about `.java-version` file](docs/advanced-usage.md#Java-version-file). - `distribution`: _(required)_ Java [distribution](#supported-distributions). diff --git a/action.yml b/action.yml index f67c642d3..2c0f7aba3 100644 --- a/action.yml +++ b/action.yml @@ -5,7 +5,8 @@ author: 'GitHub' inputs: java-version: description: 'The Java version to set up. Takes a whole or semver Java version. See examples of supported syntax in README file' - required: true + java-version-file: + description: 'The path to the `.java-version` file. See examples of supported syntax in README file' distribution: description: 'Java distribution. See the list of supported distributions in README file' required: true diff --git a/dist/cleanup/index.js b/dist/cleanup/index.js index 169ba9f36..2d9cede8e 100644 --- a/dist/cleanup/index.js +++ b/dist/cleanup/index.js @@ -68480,9 +68480,10 @@ else { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.INPUT_MVN_TOOLCHAIN_VENDOR = exports.INPUT_MVN_TOOLCHAIN_ID = exports.MVN_TOOLCHAINS_FILE = exports.MVN_SETTINGS_FILE = exports.M2_DIR = exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_JOB_STATUS = exports.INPUT_CACHE = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0; +exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = exports.INPUT_MVN_TOOLCHAIN_VENDOR = exports.INPUT_MVN_TOOLCHAIN_ID = exports.MVN_TOOLCHAINS_FILE = exports.MVN_SETTINGS_FILE = exports.M2_DIR = exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_JOB_STATUS = exports.INPUT_CACHE = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION_FILE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0; exports.MACOS_JAVA_CONTENT_POSTFIX = 'Contents/Home'; exports.INPUT_JAVA_VERSION = 'java-version'; +exports.INPUT_JAVA_VERSION_FILE = 'java-version-file'; exports.INPUT_ARCHITECTURE = 'architecture'; exports.INPUT_JAVA_PACKAGE = 'java-package'; exports.INPUT_DISTRIBUTION = 'distribution'; @@ -68505,6 +68506,7 @@ exports.MVN_SETTINGS_FILE = 'settings.xml'; exports.MVN_TOOLCHAINS_FILE = 'toolchains.xml'; exports.INPUT_MVN_TOOLCHAIN_ID = 'mvn-toolchain-id'; exports.INPUT_MVN_TOOLCHAIN_VENDOR = 'mvn-toolchain-vendor'; +exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = ['corretto']; /***/ }), @@ -68622,7 +68624,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.isCacheFeatureAvailable = exports.isGhes = exports.isJobStatusSuccess = exports.getToolcachePath = exports.isVersionSatisfies = exports.getDownloadArchiveExtension = exports.extractJdkFile = exports.getVersionFromToolcachePath = exports.getBooleanInput = exports.getTempDir = void 0; +exports.getVersionFromFileContent = exports.isCacheFeatureAvailable = exports.isGhes = exports.isJobStatusSuccess = exports.getToolcachePath = exports.isVersionSatisfies = exports.getDownloadArchiveExtension = exports.extractJdkFile = exports.getVersionFromToolcachePath = exports.getBooleanInput = exports.getTempDir = void 0; const os_1 = __importDefault(__nccwpck_require__(2037)); const path_1 = __importDefault(__nccwpck_require__(1017)); const fs = __importStar(__nccwpck_require__(7147)); @@ -68718,6 +68720,34 @@ function isCacheFeatureAvailable() { return true; } exports.isCacheFeatureAvailable = isCacheFeatureAvailable; +function getVersionFromFileContent(content, distributionName) { + var _a, _b, _c, _d, _e; + const javaVersionRegExp = /(?(?<=(^|\s|\-))(\d+\S*))(\s|$)/; + const fileContent = ((_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 + : ''; + if (!fileContent) { + return null; + } + core.debug(`Version from file '${fileContent}'`); + const tentativeVersion = avoidOldNotation(fileContent); + const rawVersion = tentativeVersion.split('-')[0]; + let version = semver.validRange(rawVersion) ? tentativeVersion : semver.coerce(tentativeVersion); + core.debug(`Range version from file is '${version}'`); + 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; + version = semver.major(coerceVersion).toString(); + } + return version.toString(); +} +exports.getVersionFromFileContent = getVersionFromFileContent; +// 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 63cf6543a..e19da8dd0 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -103582,9 +103582,10 @@ function isProbablyGradleDaemonProblem(packageManager, error) { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.INPUT_MVN_TOOLCHAIN_VENDOR = exports.INPUT_MVN_TOOLCHAIN_ID = exports.MVN_TOOLCHAINS_FILE = exports.MVN_SETTINGS_FILE = exports.M2_DIR = exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_JOB_STATUS = exports.INPUT_CACHE = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0; +exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = exports.INPUT_MVN_TOOLCHAIN_VENDOR = exports.INPUT_MVN_TOOLCHAIN_ID = exports.MVN_TOOLCHAINS_FILE = exports.MVN_SETTINGS_FILE = exports.M2_DIR = exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_JOB_STATUS = exports.INPUT_CACHE = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION_FILE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0; exports.MACOS_JAVA_CONTENT_POSTFIX = 'Contents/Home'; exports.INPUT_JAVA_VERSION = 'java-version'; +exports.INPUT_JAVA_VERSION_FILE = 'java-version-file'; exports.INPUT_ARCHITECTURE = 'architecture'; exports.INPUT_JAVA_PACKAGE = 'java-package'; exports.INPUT_DISTRIBUTION = 'distribution'; @@ -103607,6 +103608,7 @@ exports.MVN_SETTINGS_FILE = 'settings.xml'; exports.MVN_TOOLCHAINS_FILE = 'toolchains.xml'; exports.INPUT_MVN_TOOLCHAIN_ID = 'mvn-toolchain-id'; exports.INPUT_MVN_TOOLCHAIN_VENDOR = 'mvn-toolchain-vendor'; +exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = ['corretto']; /***/ }), @@ -104551,7 +104553,7 @@ class MicrosoftDistributions extends base_installer_1.JavaBase { } const foundRelease = yield tc.findFromManifest(range, true, manifest, arch); if (!foundRelease) { - throw new Error(`Could not find satisfied version for SemVer ${range}. ${manifest + throw new Error(`Could not find satisfied version for SemVer ${range}.\nAvailable versions: ${manifest .map(item => item.version) .join(', ')}`); } @@ -105056,7 +105058,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", ({ value: true })); +const fs_1 = __importDefault(__nccwpck_require__(7147)); const core = __importStar(__nccwpck_require__(2186)); const auth = __importStar(__nccwpck_require__(3497)); const util_1 = __nccwpck_require__(2629); @@ -105068,37 +105074,45 @@ const distribution_factory_1 = __nccwpck_require__(924); function run() { return __awaiter(this, void 0, void 0, function* () { try { - const versions = core.getMultilineInput(constants.INPUT_JAVA_VERSION, { required: true }); + const versions = core.getMultilineInput(constants.INPUT_JAVA_VERSION); const distributionName = core.getInput(constants.INPUT_DISTRIBUTION, { required: true }); + const versionFile = core.getInput(constants.INPUT_JAVA_VERSION_FILE); const architecture = core.getInput(constants.INPUT_ARCHITECTURE); const packageType = core.getInput(constants.INPUT_JAVA_PACKAGE); const jdkFile = core.getInput(constants.INPUT_JDK_FILE); const cache = core.getInput(constants.INPUT_CACHE); const checkLatest = util_1.getBooleanInput(constants.INPUT_CHECK_LATEST, false); let toolchainIds = core.getMultilineInput(constants.INPUT_MVN_TOOLCHAIN_ID); + core.startGroup('Installed distributions'); if (versions.length !== toolchainIds.length) { toolchainIds = []; } - core.startGroup('Installed distributions'); + 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 = util_1.getVersionFromFileContent(content, distributionName); + core.debug(`Parsed version from file '${version}'`); + if (!version) { + throw new Error(`No supported version was found in file ${versionFile}`); + } + yield installVersion(version, installerInputsOptions); + } for (const [index, version] of versions.entries()) { - const installerOptions = { - architecture, - packageType, - version, - checkLatest - }; - const distribution = distribution_factory_1.getJavaDistribution(distributionName, installerOptions, jdkFile); - if (!distribution) { - throw new Error(`No supported distribution was found for input ${distributionName}`); - } - const result = yield distribution.setupJava(); - yield toolchains.configureToolchains(version, distributionName, result.path, toolchainIds[index]); - core.info(''); - core.info('Java configuration:'); - core.info(` Distribution: ${distributionName}`); - core.info(` Version: ${result.version}`); - core.info(` Path: ${result.path}`); - core.info(''); + yield installVersion(version, installerInputsOptions, index); } core.endGroup(); const matchersPath = path.join(__dirname, '..', '..', '.github'); @@ -105114,6 +105128,29 @@ function run() { }); } run(); +function installVersion(version, options, toolchainId = 0) { + return __awaiter(this, void 0, void 0, function* () { + const { distributionName, jdkFile, architecture, packageType, checkLatest, toolchainIds } = options; + const installerOptions = { + architecture, + packageType, + checkLatest, + version + }; + const distribution = distribution_factory_1.getJavaDistribution(distributionName, installerOptions, jdkFile); + if (!distribution) { + throw new Error(`No supported distribution was found for input ${distributionName}`); + } + const result = yield distribution.setupJava(); + yield toolchains.configureToolchains(version, distributionName, result.path, toolchainIds[toolchainId]); + core.info(''); + core.info('Java configuration:'); + core.info(` Distribution: ${distributionName}`); + core.info(` Version: ${result.version}`); + core.info(` Path: ${result.path}`); + core.info(''); + }); +} /***/ }), @@ -105315,7 +105352,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.isCacheFeatureAvailable = exports.isGhes = exports.isJobStatusSuccess = exports.getToolcachePath = exports.isVersionSatisfies = exports.getDownloadArchiveExtension = exports.extractJdkFile = exports.getVersionFromToolcachePath = exports.getBooleanInput = exports.getTempDir = void 0; +exports.getVersionFromFileContent = exports.isCacheFeatureAvailable = exports.isGhes = exports.isJobStatusSuccess = exports.getToolcachePath = exports.isVersionSatisfies = exports.getDownloadArchiveExtension = exports.extractJdkFile = exports.getVersionFromToolcachePath = exports.getBooleanInput = exports.getTempDir = void 0; const os_1 = __importDefault(__nccwpck_require__(2037)); const path_1 = __importDefault(__nccwpck_require__(1017)); const fs = __importStar(__nccwpck_require__(7147)); @@ -105411,6 +105448,34 @@ function isCacheFeatureAvailable() { return true; } exports.isCacheFeatureAvailable = isCacheFeatureAvailable; +function getVersionFromFileContent(content, distributionName) { + var _a, _b, _c, _d, _e; + const javaVersionRegExp = /(?(?<=(^|\s|\-))(\d+\S*))(\s|$)/; + const fileContent = ((_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 + : ''; + if (!fileContent) { + return null; + } + core.debug(`Version from file '${fileContent}'`); + const tentativeVersion = avoidOldNotation(fileContent); + const rawVersion = tentativeVersion.split('-')[0]; + let version = semver.validRange(rawVersion) ? tentativeVersion : semver.coerce(tentativeVersion); + core.debug(`Range version from file is '${version}'`); + 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; + version = semver.major(coerceVersion).toString(); + } + return version.toString(); +} +exports.getVersionFromFileContent = getVersionFromFileContent; +// 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/docs/advanced-usage.md b/docs/advanced-usage.md index 58f6bc572..f5463bb77 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -15,6 +15,7 @@ - [Publishing using Gradle](#Publishing-using-Gradle) - [Hosted Tool Cache](#Hosted-Tool-Cache) - [Modifying Maven Toolchains](#Modifying-Maven-Toolchains) +- [Java-version file](#Java-version-file) See [action.yml](../action.yml) for more details on task inputs. @@ -464,3 +465,15 @@ steps: something_else something_other ``` + +## Java-version file +If the `java-version-file` input is specified, the action will try to extract the version from the file and install it. +Action is able to recognize all variants of the version description according to [jenv](https://github.com/jenv/jenv). +Valid entry options: +``` +major versions: 8, 11, 16, 17 +more specific versions: 1.8.0.2, 17.0, 11.0, 11.0.4, 8.0.232, 8.0.282+8 +early access (EA) versions: 15-ea, 15.0.0-ea, 15.0.0-ea.2, 15.0.0+2-ea +versions with specified distribution: openjdk64-11.0.2 +``` +If the file contains multiple versions, only the first one will be recognized. diff --git a/src/constants.ts b/src/constants.ts index ad8709e7a..9aa213fa9 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,5 +1,6 @@ export const MACOS_JAVA_CONTENT_POSTFIX = 'Contents/Home'; export const INPUT_JAVA_VERSION = 'java-version'; +export const INPUT_JAVA_VERSION_FILE = 'java-version-file'; export const INPUT_ARCHITECTURE = 'architecture'; export const INPUT_JAVA_PACKAGE = 'java-package'; export const INPUT_DISTRIBUTION = 'distribution'; @@ -26,3 +27,5 @@ export const MVN_SETTINGS_FILE = 'settings.xml'; export const MVN_TOOLCHAINS_FILE = 'toolchains.xml'; export const INPUT_MVN_TOOLCHAIN_ID = 'mvn-toolchain-id'; export const INPUT_MVN_TOOLCHAIN_VENDOR = 'mvn-toolchain-vendor'; + +export const DISTRIBUTIONS_ONLY_MAJOR_VERSION = ['corretto']; diff --git a/src/distributions/microsoft/installer.ts b/src/distributions/microsoft/installer.ts index 6929fb2ee..8625fb423 100644 --- a/src/distributions/microsoft/installer.ts +++ b/src/distributions/microsoft/installer.ts @@ -60,7 +60,7 @@ export class MicrosoftDistributions extends JavaBase { if (!foundRelease) { throw new Error( - `Could not find satisfied version for SemVer ${range}. ${manifest + `Could not find satisfied version for SemVer ${range}.\nAvailable versions: ${manifest .map(item => item.version) .join(', ')}` ); diff --git a/src/setup-java.ts b/src/setup-java.ts index 048c5dd6b..1d6dc15b4 100644 --- a/src/setup-java.ts +++ b/src/setup-java.ts @@ -1,6 +1,7 @@ +import fs from 'fs'; import * as core from '@actions/core'; import * as auth from './auth'; -import { getBooleanInput, isCacheFeatureAvailable } from './util'; +import { getBooleanInput, isCacheFeatureAvailable, getVersionFromFileContent } from './util'; import * as toolchains from './toolchains'; import * as constants from './constants'; import { restore } from './cache'; @@ -10,8 +11,9 @@ import { JavaInstallerOptions } from './distributions/base-models'; async function run() { try { - const versions = core.getMultilineInput(constants.INPUT_JAVA_VERSION, { required: true }); + const versions = core.getMultilineInput(constants.INPUT_JAVA_VERSION); const distributionName = core.getInput(constants.INPUT_DISTRIBUTION, { required: true }); + const versionFile = core.getInput(constants.INPUT_JAVA_VERSION_FILE); const architecture = core.getInput(constants.INPUT_ARCHITECTURE); const packageType = core.getInput(constants.INPUT_JAVA_PACKAGE); const jdkFile = core.getInput(constants.INPUT_JDK_FILE); @@ -19,38 +21,44 @@ async function run() { const checkLatest = getBooleanInput(constants.INPUT_CHECK_LATEST, false); let toolchainIds = core.getMultilineInput(constants.INPUT_MVN_TOOLCHAIN_ID); + core.startGroup('Installed distributions'); + if (versions.length !== toolchainIds.length) { toolchainIds = []; } - core.startGroup('Installed distributions'); - for (const [index, version] of versions.entries()) { - const installerOptions: JavaInstallerOptions = { - architecture, - packageType, - version, - checkLatest - }; - - const distribution = getJavaDistribution(distributionName, installerOptions, jdkFile); - if (!distribution) { - throw new Error(`No supported distribution was found for input ${distributionName}`); + if (!versions.length && !versionFile) { + 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(content, distributionName); + core.debug(`Parsed version from file '${version}'`); + + if (!version) { + throw new Error(`No supported version was found in file ${versionFile}`); } - const result = await distribution.setupJava(); - await toolchains.configureToolchains( - version, - distributionName, - result.path, - toolchainIds[index] - ); - - core.info(''); - core.info('Java configuration:'); - core.info(` Distribution: ${distributionName}`); - core.info(` Version: ${result.version}`); - core.info(` Path: ${result.path}`); - core.info(''); + await installVersion(version, installerInputsOptions); + } + + for (const [index, version] of versions.entries()) { + await installVersion(version, installerInputsOptions, index); } core.endGroup(); const matchersPath = path.join(__dirname, '..', '..', '.github'); @@ -66,3 +74,50 @@ async function run() { } run(); + +async function installVersion(version: string, options: installerInputsOptions, toolchainId = 0) { + const { + distributionName, + jdkFile, + architecture, + packageType, + checkLatest, + toolchainIds + } = options; + + const installerOptions: JavaInstallerOptions = { + architecture, + packageType, + checkLatest, + version + }; + + const distribution = getJavaDistribution(distributionName, installerOptions, jdkFile); + if (!distribution) { + throw new Error(`No supported distribution was found for input ${distributionName}`); + } + + const result = await distribution.setupJava(); + await toolchains.configureToolchains( + version, + distributionName, + result.path, + toolchainIds[toolchainId] + ); + + core.info(''); + core.info('Java configuration:'); + core.info(` Distribution: ${distributionName}`); + core.info(` Version: ${result.version}`); + core.info(` Path: ${result.path}`); + core.info(''); +} + +interface installerInputsOptions { + architecture: string; + packageType: string; + checkLatest: boolean; + distributionName: string; + jdkFile: string; + toolchainIds: Array; +} diff --git a/src/util.ts b/src/util.ts index 10f18c5fe..960760360 100644 --- a/src/util.ts +++ b/src/util.ts @@ -6,7 +6,7 @@ import * as cache from '@actions/cache'; import * as core from '@actions/core'; import * as tc from '@actions/tool-cache'; -import { INPUT_JOB_STATUS } from './constants'; +import { INPUT_JOB_STATUS, DISTRIBUTIONS_ONLY_MAJOR_VERSION } from './constants'; export function getTempDir() { let tempDirectory = process.env['RUNNER_TEMP'] || os.tmpdir(); @@ -99,3 +99,41 @@ export function isCacheFeatureAvailable(): boolean { return true; } + +export function getVersionFromFileContent( + content: string, + distributionName: string +): string | null { + const javaVersionRegExp = /(?(?<=(^|\s|\-))(\d+\S*))(\s|$)/; + const fileContent = content.match(javaVersionRegExp)?.groups?.version + ? (content.match(javaVersionRegExp)?.groups?.version as string) + : ''; + if (!fileContent) { + return null; + } + + core.debug(`Version from file '${fileContent}'`); + + const tentativeVersion = avoidOldNotation(fileContent); + const rawVersion = tentativeVersion.split('-')[0]; + + let version = semver.validRange(rawVersion) ? tentativeVersion : semver.coerce(tentativeVersion); + + core.debug(`Range version from file is '${version}'`); + + if (!version) { + return null; + } + + if (DISTRIBUTIONS_ONLY_MAJOR_VERSION.includes(distributionName)) { + const coerceVersion = semver.coerce(version) ?? version; + version = semver.major(coerceVersion).toString(); + } + + return version.toString(); +} + +// By convention, action expects version 8 in the format `8.*` instead of `1.8` +function avoidOldNotation(content: string): string { + return content.startsWith('1.') ? content.substring(2) : content; +}