From 9871695637a253fbd6cc716a05d26641f7a32c0a Mon Sep 17 00:00:00 2001 From: John Jiang Date: Wed, 14 Aug 2024 10:35:43 +0800 Subject: [PATCH] Support Tencent Kona JDK (#671) --- .github/workflows/e2e-versions.yml | 5 +- README.md | 2 + __tests__/data/kona.json | 122 +++++++++++ __tests__/distributors/kona-installer.test.ts | 189 ++++++++++++++++++ dist/setup/index.js | 180 ++++++++++++++++- docs/advanced-usage.md | 20 +- src/distributions/distribution-factory.ts | 6 +- src/distributions/kona/installer.ts | 183 +++++++++++++++++ src/distributions/kona/models.ts | 25 +++ 9 files changed, 726 insertions(+), 6 deletions(-) create mode 100644 __tests__/data/kona.json create mode 100644 __tests__/distributors/kona-installer.test.ts create mode 100644 src/distributions/kona/installer.ts create mode 100644 src/distributions/kona/models.ts diff --git a/.github/workflows/e2e-versions.yml b/.github/workflows/e2e-versions.yml index 0553d91a8..94f7d7312 100644 --- a/.github/workflows/e2e-versions.yml +++ b/.github/workflows/e2e-versions.yml @@ -30,7 +30,8 @@ jobs: 'microsoft', 'semeru', 'corretto', - 'dragonwell' + 'dragonwell', + 'kona' ] # internally 'adopt-hotspot' is the same as 'adopt' version: ['21', '11', '17'] exclude: @@ -38,6 +39,8 @@ jobs: version: 8 - distribution: dragonwell os: macos-13 + - distribution: kona + version: 21 include: - distribution: oracle os: macos-13 diff --git a/README.md b/README.md index 7702e6f1c..cc478028f 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ Currently, the following distributions are supported: | `semeru` | IBM Semeru Runtime Open Edition | [Link](https://developer.ibm.com/languages/java/semeru-runtimes/downloads/) | [Link](https://openjdk.java.net/legal/gplv2+ce.html) | | `oracle` | Oracle JDK | [Link](https://www.oracle.com/java/technologies/downloads/) | [Link](https://java.com/freeuselicense) | `dragonwell` | Alibaba Dragonwell JDK | [Link](https://dragonwell-jdk.io/) | [Link](https://www.aliyun.com/product/dragonwell/) +| `kona` | Tencent Kona JDK | [Link](https://tencent.github.io/konajdk/) | [Link](https://tencent.github.io/konajdk/LICENSE.txt) **NOTE:** The different distributors can provide discrepant list of available versions / supported configurations. Please refer to the official documentation to see the list of supported versions. @@ -257,6 +258,7 @@ In the example above multiple JDKs are installed for the same job. The result af - [Amazon Corretto](docs/advanced-usage.md#Amazon-Corretto) - [Oracle](docs/advanced-usage.md#Oracle) - [Alibaba Dragonwell](docs/advanced-usage.md#Alibaba-Dragonwell) + - [Tencent Kona](docs/advanced-usage.md#Tencent-Kona) - [Installing custom Java package type](docs/advanced-usage.md#Installing-custom-Java-package-type) - [Installing custom Java architecture](docs/advanced-usage.md#Installing-custom-Java-architecture) - [Installing custom Java distribution from local file](docs/advanced-usage.md#Installing-Java-from-local-file) diff --git a/__tests__/data/kona.json b/__tests__/data/kona.json new file mode 100644 index 000000000..4e775470b --- /dev/null +++ b/__tests__/data/kona.json @@ -0,0 +1,122 @@ +{ + "8": [ + { + "version": "8.0.19", + "jdkVersion": "8u422", + "latest": true, + "baseUrl": "https://github.com/Tencent/TencentKona-8/releases/download/8.0.19-GA/", + "files": [ + { + "os": "linux", + "arch": "aarch64", + "filename": "TencentKona8.0.19.b1_jdk_linux-aarch64_8u422.tar.gz", + "checksum": "ef031cc28012413ee771c318c6986bfb1dd80b16962ae073d775e269397f6580" + }, + { + "os": "linux", + "arch": "x86_64", + "filename": "TencentKona8.0.19.b1_jdk_linux-x86_64_8u422.tar.gz", + "checksum": "57866cb132fc551028257dd1a6ad65650ca0436a1811f30c53ad67844e35c781" + }, + { + "os": "macos", + "arch": "aarch64", + "filename": "TencentKona8.0.19.b1_jdk_macosx-aarch64_8u422_notarized.tar.gz", + "checksum": "4c9c169b983fc0b1fd2bbcdd40daa410c72c10ad360d6a61957270c9bdbd96d9" + }, + { + "os": "macos", + "arch": "x86_64", + "filename": "TencentKona8.0.19.b1_jdk_macosx-x86_64_8u422_notarized.tar.gz", + "checksum": "9f9be00fb2259bc6ea0b117cb96041b12b39fdf537991af75e9e475e73c6b40f" + }, + { + "os": "windows", + "arch": "x86_64", + "filename": "TencentKona8.0.19.b1_jdk_windows-x86_64_8u422_signed.zip", + "checksum": "afc16c4d048f6c90099841e16ad50314ae710340ec057ef19c845f5d43b6ee9e" + } + ] + } + ], + "11": [ + { + "version": "11.0.24", + "jdkVersion": "11.0.24", + "latest": true, + "baseUrl": "https://github.com/Tencent/TencentKona-11/releases/download/kona11.0.24/", + "files": [ + { + "os": "linux", + "arch": "aarch64", + "filename": "TencentKona-11.0.24.b1-jdk_linux-aarch64.tar.gz", + "checksum": "505aa9e39c6fd9dab20443c0b4ed8fb1fedb40109c52b00edeaa7774c6fe9de9" + }, + { + "os": "linux", + "arch": "x86_64", + "filename": "TencentKona-11.0.24.b1-jdk_linux-x86_64.tar.gz", + "checksum": "63ff8d821a2b0eef02aa257a959e53150e02865f8eb143feca1b40179d94a3f3" + }, + { + "os": "macos", + "arch": "aarch64", + "filename": "TencentKona-11.0.24.b1_jdk_macosx-aarch64_notarized.tar.gz", + "checksum": "e8a6c493a9922fbabc712fa70a50260f001d9202e3370224eabc27adfcf008de" + }, + { + "os": "macos", + "arch": "x86_64", + "filename": "TencentKona-11.0.24.b1_jdk_macosx-x86_64_notarized.tar.gz", + "checksum": "c8316cc8388faaa3d898f412a63ef42efbad243a01eaef37f6a19d77e4cd7956" + }, + { + "os": "windows", + "arch": "x86_64", + "filename": "TencentKona-11.0.24.b1_jdk_windows-x86_64_signed.zip", + "checksum": "222b135f637af85e3092921a9c9bfc45a743944c179e4170d93e4eea82165858" + } + ] + } + ], + "17": [ + { + "version": "17.0.12", + "jdkVersion": "17.0.12", + "latest": true, + "baseUrl": "https://github.com/Tencent/TencentKona-17/releases/download/TencentKona-17.0.12/", + "files": [ + { + "os": "linux", + "arch": "aarch64", + "filename": "TencentKona-17.0.12.b1-jdk_linux-aarch64.tar.gz", + "checksum": "bf65e9b3ab5781a5bb9ddfe5a6032efa8f099f48d85b5dcec686e5a4c0647fea" + }, + { + "os": "linux", + "arch": "x86_64", + "filename": "TencentKona-17.0.12.b1-jdk_linux-x86_64.tar.gz", + "checksum": "b8b6706c3710777240696c672168c8065d7a77c2199238ace7caffe353deab27" + }, + { + "os": "macos", + "arch": "aarch64", + "filename": "TencentKona-17.0.12.b1_jdk_macosx-aarch64_notarized.tar.gz", + "checksum": "d1f5653e2e8c7a0febeeadd13d7f4270076c0b4bde3785d4a93a9444c69800b5" + }, + { + "os": "macos", + "arch": "x86_64", + "filename": "TencentKona-17.0.12.b1_jdk_macosx-x86_64_notarized.tar.gz", + "checksum": "870678cabbabd6970e8f9d0a7fafa8d87597f71d9f581d0f0d103879101e97bc" + }, + { + "os": "windows", + "arch": "x86_64", + "filename": "TencentKona-17.0.12.b1_jdk_windows-x86_64_signed.zip", + "checksum": "0a0bc7c10cd9d0852f368674d02ee6d39200ef4d8857904004b677a15937e412" + } + ] + } + ] +} diff --git a/__tests__/distributors/kona-installer.test.ts b/__tests__/distributors/kona-installer.test.ts new file mode 100644 index 000000000..f9de64337 --- /dev/null +++ b/__tests__/distributors/kona-installer.test.ts @@ -0,0 +1,189 @@ +import {KonaDistribution} from '../../src/distributions/kona/installer'; + +import manifestData from '../data/kona.json'; + +function mockDistr( + version: string, + os: string, + arch: string, + packageType: string +): KonaDistribution { + const distribution = new KonaDistribution({ + version: version, + architecture: arch, + packageType: packageType, + checkLatest: false + }); + + distribution['getOs'] = () => os; + distribution['fetchReleaseInfo'] = async () => manifestData; + + return distribution; +} + +describe('Check getAvailableReleases', () => { + it.each([ + ['8', 'linux', 'aarch64', 'linux-aarch64'], + ['8.0.19', 'macos', 'x86_64', 'macosx-x86_64'], + ['11', 'linux', 'x86_64', 'linux-x86_64'], + ['11.0.24', 'macos', 'aarch64', 'macosx-aarch64'], + ['17.0.12', 'windows', 'x86_64', 'windows-x86_64'] + ])( + 'should get releases with the specified version "%s", OS "%s" and arch "%s"', + async ( + version: string, + os: string, + arch: string, + expectedPattern: string + ) => { + const distribution = mockDistr(version, os, arch, 'jdk'); + + const releases = await distribution['getAvailableReleases'](); + expect(releases).not.toBeNull(); + expect(releases.length).toBe(3); + releases.forEach((release, index) => + expect(releases[index].downloadUrl).toContain(expectedPattern) + ); + } + ); +}); + +describe('Check findPackageForDownload', () => { + it.each([ + [ + '8', + 'linux', + 'aarch64', + 'https://github.com/Tencent/TencentKona-8/releases/download/8.0.19-GA/TencentKona8.0.19.b1_jdk_linux-aarch64_8u422.tar.gz' + ], + [ + '8.0.19', + 'linux', + 'x86_64', + 'https://github.com/Tencent/TencentKona-8/releases/download/8.0.19-GA/TencentKona8.0.19.b1_jdk_linux-x86_64_8u422.tar.gz' + ], + [ + '8.0.19', + 'macos', + 'aarch64', + 'https://github.com/Tencent/TencentKona-8/releases/download/8.0.19-GA/TencentKona8.0.19.b1_jdk_macosx-aarch64_8u422_notarized.tar.gz' + ], + [ + '8.0.19', + 'macos', + 'x86_64', + 'https://github.com/Tencent/TencentKona-8/releases/download/8.0.19-GA/TencentKona8.0.19.b1_jdk_macosx-x86_64_8u422_notarized.tar.gz' + ], + [ + '8.0.19', + 'windows', + 'x86_64', + 'https://github.com/Tencent/TencentKona-8/releases/download/8.0.19-GA/TencentKona8.0.19.b1_jdk_windows-x86_64_8u422_signed.zip' + ], + + [ + '11', + 'linux', + 'aarch64', + 'https://github.com/Tencent/TencentKona-11/releases/download/kona11.0.24/TencentKona-11.0.24.b1-jdk_linux-aarch64.tar.gz' + ], + [ + '11.0.24', + 'linux', + 'x86_64', + 'https://github.com/Tencent/TencentKona-11/releases/download/kona11.0.24/TencentKona-11.0.24.b1-jdk_linux-x86_64.tar.gz' + ], + [ + '11.0.24', + 'macos', + 'aarch64', + 'https://github.com/Tencent/TencentKona-11/releases/download/kona11.0.24/TencentKona-11.0.24.b1_jdk_macosx-aarch64_notarized.tar.gz' + ], + [ + '11.0.24', + 'macos', + 'x86_64', + 'https://github.com/Tencent/TencentKona-11/releases/download/kona11.0.24/TencentKona-11.0.24.b1_jdk_macosx-x86_64_notarized.tar.gz' + ], + [ + '11.0.24', + 'windows', + 'x86_64', + 'https://github.com/Tencent/TencentKona-11/releases/download/kona11.0.24/TencentKona-11.0.24.b1_jdk_windows-x86_64_signed.zip' + ], + + [ + '17', + 'linux', + 'aarch64', + 'https://github.com/Tencent/TencentKona-17/releases/download/TencentKona-17.0.12/TencentKona-17.0.12.b1-jdk_linux-aarch64.tar.gz' + ], + [ + '17.0.12', + 'linux', + 'x86_64', + 'https://github.com/Tencent/TencentKona-17/releases/download/TencentKona-17.0.12/TencentKona-17.0.12.b1-jdk_linux-x86_64.tar.gz' + ], + [ + '17.0.12', + 'macos', + 'aarch64', + 'https://github.com/Tencent/TencentKona-17/releases/download/TencentKona-17.0.12/TencentKona-17.0.12.b1_jdk_macosx-aarch64_notarized.tar.gz' + ], + [ + '17.0.12', + 'macos', + 'x86_64', + 'https://github.com/Tencent/TencentKona-17/releases/download/TencentKona-17.0.12/TencentKona-17.0.12.b1_jdk_macosx-x86_64_notarized.tar.gz' + ], + [ + '17.0.12', + 'windows', + 'x86_64', + 'https://github.com/Tencent/TencentKona-17/releases/download/TencentKona-17.0.12/TencentKona-17.0.12.b1_jdk_windows-x86_64_signed.zip' + ] + ])( + 'should return the download URL with the specified version "%s", OS "%s" and arch "%s"', + async (version: string, os: string, arch: string, expectedUrl: string) => { + const distribution = mockDistr(version, os, arch, 'jdk'); + + const availableRelease = await distribution['findPackageForDownload']( + version + ); + expect(availableRelease).not.toBeNull(); + expect(availableRelease.url).toBe(expectedUrl); + } + ); +}); + +describe('No release is found', () => { + it.each([ + ['8', 'linux', 'x86'], + ['17', 'solaris', 'x86_64'], + ['21', 'linux', 'x86_64'] + ])( + `should throw an error due to no release with the specified version "%s", os "%s" and arch "%s"`, + async (version: string, os: string, arch: string) => { + const distribution = mockDistr(version, os, arch, 'jdk'); + + await expect( + distribution['findPackageForDownload'](version) + ).rejects.toThrow( + `No Kona release for the specified version "${version}" on OS "${os}" and arch "${arch}".` + ); + } + ); +}); + +describe('The package type must be jdk', () => { + it('should throw an error due to the specified package type is not jdk', async () => { + const version = '8.0.19'; + const os = 'linux'; + const arch = 'x86_64'; + const distribution = mockDistr(version, os, arch, 'jre'); + + await expect( + distribution['findPackageForDownload'](version) + ).rejects.toThrow('Kona provides jdk only'); + }); +}); diff --git a/dist/setup/index.js b/dist/setup/index.js index be40d6dbd..063048d93 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -124049,6 +124049,7 @@ const installer_7 = __nccwpck_require__(41121); const installer_8 = __nccwpck_require__(34750); const installer_9 = __nccwpck_require__(64298); const installer_10 = __nccwpck_require__(16132); +const installer_11 = __nccwpck_require__(45696); var JavaDistribution; (function (JavaDistribution) { JavaDistribution["Adopt"] = "adopt"; @@ -124063,6 +124064,7 @@ var JavaDistribution; JavaDistribution["Corretto"] = "corretto"; JavaDistribution["Oracle"] = "oracle"; JavaDistribution["Dragonwell"] = "dragonwell"; + JavaDistribution["Kona"] = "kona"; })(JavaDistribution || (JavaDistribution = {})); function getJavaDistribution(distributionName, installerOptions, jdkFile) { switch (distributionName) { @@ -124089,6 +124091,8 @@ function getJavaDistribution(distributionName, installerOptions, jdkFile) { return new installer_9.OracleDistribution(installerOptions); case JavaDistribution.Dragonwell: return new installer_10.DragonwellDistribution(installerOptions); + case JavaDistribution.Kona: + return new installer_11.KonaDistribution(installerOptions); default: return null; } @@ -124306,6 +124310,180 @@ class DragonwellDistribution extends base_installer_1.JavaBase { exports.DragonwellDistribution = DragonwellDistribution; +/***/ }), + +/***/ 45696: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + 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 })); +exports.KonaDistribution = void 0; +const core = __importStar(__nccwpck_require__(42186)); +const tc = __importStar(__nccwpck_require__(27784)); +const fs_1 = __importDefault(__nccwpck_require__(57147)); +const path_1 = __importDefault(__nccwpck_require__(71017)); +const base_installer_1 = __nccwpck_require__(59741); +const util_1 = __nccwpck_require__(92629); +class KonaDistribution extends base_installer_1.JavaBase { + constructor(installerOptions) { + super('Kona', installerOptions); + } + downloadTool(javaRelease) { + return __awaiter(this, void 0, void 0, function* () { + core.info(`Downloading Kona JDK ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...`); + const javaArchivePath = yield tc.downloadTool(javaRelease.url); + core.info(`Extracting Java archive...`); + const extension = (0, util_1.getDownloadArchiveExtension)(); + const extractedJavaPath = yield (0, util_1.extractJdkFile)(javaArchivePath, extension); + const archiveName = fs_1.default.readdirSync(extractedJavaPath)[0]; + const archivePath = path_1.default.join(extractedJavaPath, archiveName); + const version = this.getToolcacheVersionName(javaRelease.version); + const javaPath = yield tc.cacheDir(archivePath, this.toolcacheFolderName, version, this.architecture); + return { version: javaRelease.version, path: javaPath }; + }); + } + findPackageForDownload(version) { + return __awaiter(this, void 0, void 0, function* () { + if (!this.stable) { + throw new Error('Kona provides stable releases only'); + } + if (this.packageType !== 'jdk') { + throw new Error('Kona provides jdk only'); + } + const availableReleases = yield this.getAvailableReleases(); + const releases = availableReleases + .filter(item => { + return (0, util_1.isVersionSatisfies)(version, item.version); + }) + .map(item => { + return { + version: item.version, + url: item.downloadUrl + }; + }); + if (!releases.length) { + throw new Error(`No Kona release for the specified version "${version}" on OS "${this.getOs()}" and arch "${this.getArch()}".`); + } + return releases[0]; + }); + } + getAvailableReleases() { + return __awaiter(this, void 0, void 0, function* () { + if (core.isDebug()) { + console.time('Retrieving available releases for Kona took'); // eslint-disable-line no-console + } + const releaseInfo = yield this.fetchReleaseInfo(); + if (!releaseInfo) { + throw new Error(`Couldn't fetch Kona release information`); + } + const availableReleases = this.chooseReleases(this.getOs(), this.getArch(), releaseInfo); + if (core.isDebug()) { + core.startGroup('Print information about available releases'); + core.debug(availableReleases.map(item => item.version).join(', ')); + core.endGroup(); + } + return availableReleases; + }); + } + fetchReleaseInfo() { + return __awaiter(this, void 0, void 0, function* () { + const releasesInfoUrl = 'https://tencent.github.io/konajdk/releases/kona-v1.json'; + try { + core.debug(`Fetching Kona release info from URL: ${releasesInfoUrl}`); + return (yield this.http.getJson(releasesInfoUrl)) + .result; + } + catch (err) { + core.debug(`Fetching Kona release info from the URL: ${releasesInfoUrl} failed with the error: ${err.message}`); + return null; + } + }); + } + chooseReleases(os, arch, releaseInfo) { + const releases = []; + for (const majorVersion in releaseInfo) { + const versions = releaseInfo[majorVersion]; + for (const version of versions) { + if (!version.latest) { + continue; + } + for (const file of version.files) { + if (file.os === os && file.arch === arch) { + releases.push({ + version: version.version, + jdkVersion: version.jdkVersion, + os: os, + arch: arch, + downloadUrl: version.baseUrl + file.filename, + checksum: file.checksum + }); + break; + } + } + } + } + return releases; + } + getOs() { + switch (process.platform) { + case 'darwin': + return 'macos'; + case 'win32': + return 'windows'; + default: + return process.platform; + } + } + getArch() { + switch (this.architecture) { + case 'arm64': + return 'aarch64'; + case 'x64': + return 'x86_64'; + default: + return this.architecture; + } + } +} +exports.KonaDistribution = KonaDistribution; + + /***/ }), /***/ 40883: @@ -127946,4 +128124,4 @@ module.exports = JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"] /******/ module.exports = __webpack_exports__; /******/ /******/ })() -; +; \ No newline at end of file diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index cfbda09fc..33e72b461 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -8,6 +8,7 @@ - [Amazon Corretto](#Amazon-Corretto) - [Oracle](#Oracle) - [Alibaba Dragonwell](#Alibaba-Dragonwell) + - [Tencent Kona](#Tencent-Kona) - [Installing custom Java package type](#Installing-custom-Java-package-type) - [Installing custom Java architecture](#Installing-custom-Java-architecture) - [Installing custom Java distribution from local file](#Installing-Java-from-local-file) @@ -142,6 +143,19 @@ steps: - run: java -cp java HelloWorldApp ``` +### Tencent Kona +**NOTE:** Tencent Kona supports major versions 8, 11 and 17, and provides jdk only. + +```yaml +steps: +- uses: actions/checkout@v4 +- uses: actions/setup-java@v4 + with: + distribution: 'kona' + java-version: '8' +- run: java -cp java HelloWorldApp +``` + ## Installing custom Java package type ```yaml steps: @@ -182,7 +196,7 @@ steps: jdkFile: ${{ runner.temp }}/java_package.tar.gz java-version: '11.0.0' architecture: x64 - + - run: java -cp java HelloWorldApp ``` @@ -527,12 +541,12 @@ steps: ## Java version file If the `java-version-file` input is specified, the action will extract the version from the file and install it. - + Supported files are .java-version and .tool-versions. In .java-version file, only the version should be specified (e.g., 17.0.7). In .tool-versions file, java version should be preceded by the java keyword (e.g., java 17.0.7). The `.java-version` file recognizes all variants of the version description according to [jenv](https://github.com/jenv/jenv). Similarly, 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/)). - + If both java-version and java-version-file inputs are provided, the java-version input will be used. Valid entry options: diff --git a/src/distributions/distribution-factory.ts b/src/distributions/distribution-factory.ts index 52a41b5b4..93e95d3f5 100644 --- a/src/distributions/distribution-factory.ts +++ b/src/distributions/distribution-factory.ts @@ -10,6 +10,7 @@ import {SemeruDistribution} from './semeru/installer'; import {CorrettoDistribution} from './corretto/installer'; import {OracleDistribution} from './oracle/installer'; import {DragonwellDistribution} from './dragonwell/installer'; +import {KonaDistribution} from './kona/installer'; enum JavaDistribution { Adopt = 'adopt', @@ -23,7 +24,8 @@ enum JavaDistribution { Semeru = 'semeru', Corretto = 'corretto', Oracle = 'oracle', - Dragonwell = 'dragonwell' + Dragonwell = 'dragonwell', + Kona = 'kona' } export function getJavaDistribution( @@ -64,6 +66,8 @@ export function getJavaDistribution( return new OracleDistribution(installerOptions); case JavaDistribution.Dragonwell: return new DragonwellDistribution(installerOptions); + case JavaDistribution.Kona: + return new KonaDistribution(installerOptions); default: return null; } diff --git a/src/distributions/kona/installer.ts b/src/distributions/kona/installer.ts new file mode 100644 index 000000000..e09c1b5fe --- /dev/null +++ b/src/distributions/kona/installer.ts @@ -0,0 +1,183 @@ +import * as core from '@actions/core'; +import * as tc from '@actions/tool-cache'; + +import fs from 'fs'; +import path from 'path'; + +import {JavaBase} from '../base-installer'; +import {IKonaReleaseInfo, IKonaRelease} from './models'; +import { + JavaDownloadRelease, + JavaInstallerOptions, + JavaInstallerResults +} from '../base-models'; +import { + extractJdkFile, + getDownloadArchiveExtension, + isVersionSatisfies +} from '../../util'; + +export class KonaDistribution extends JavaBase { + constructor(installerOptions: JavaInstallerOptions) { + super('Kona', installerOptions); + } + + protected async downloadTool( + javaRelease: JavaDownloadRelease + ): Promise { + core.info( + `Downloading Kona JDK ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...` + ); + const javaArchivePath = await tc.downloadTool(javaRelease.url); + + core.info(`Extracting Java archive...`); + + const extension = getDownloadArchiveExtension(); + const extractedJavaPath = await extractJdkFile(javaArchivePath, extension); + + const archiveName = fs.readdirSync(extractedJavaPath)[0]; + const archivePath = path.join(extractedJavaPath, archiveName); + const version = this.getToolcacheVersionName(javaRelease.version); + + const javaPath = await tc.cacheDir( + archivePath, + this.toolcacheFolderName, + version, + this.architecture + ); + + return {version: javaRelease.version, path: javaPath}; + } + + protected async findPackageForDownload( + version: string + ): Promise { + if (!this.stable) { + throw new Error('Kona provides stable releases only'); + } + + if (this.packageType !== 'jdk') { + throw new Error('Kona provides jdk only'); + } + + const availableReleases = await this.getAvailableReleases(); + const releases = availableReleases + .filter(item => { + return isVersionSatisfies(version, item.version); + }) + .map(item => { + return { + version: item.version, + url: item.downloadUrl + } as JavaDownloadRelease; + }); + + if (!releases.length) { + throw new Error( + `No Kona release for the specified version "${version}" on OS "${this.getOs()}" and arch "${this.getArch()}".` + ); + } + + return releases[0]; + } + + private async getAvailableReleases(): Promise { + if (core.isDebug()) { + console.time('Retrieving available releases for Kona took'); // eslint-disable-line no-console + } + + const releaseInfo = await this.fetchReleaseInfo(); + if (!releaseInfo) { + throw new Error(`Couldn't fetch Kona release information`); + } + + const availableReleases = this.chooseReleases( + this.getOs(), + this.getArch(), + releaseInfo + ); + + if (core.isDebug()) { + core.startGroup('Print information about available releases'); + core.debug(availableReleases.map(item => item.version).join(', ')); + core.endGroup(); + } + + return availableReleases; + } + + private async fetchReleaseInfo(): Promise { + const releasesInfoUrl = + 'https://tencent.github.io/konajdk/releases/kona-v1.json'; + + try { + core.debug(`Fetching Kona release info from URL: ${releasesInfoUrl}`); + return (await this.http.getJson(releasesInfoUrl)) + .result; + } catch (err) { + core.debug( + `Fetching Kona release info from the URL: ${releasesInfoUrl} failed with the error: ${ + (err as Error).message + }` + ); + return null; + } + } + + private chooseReleases( + os: string, + arch: string, + releaseInfo: IKonaReleaseInfo + ): IKonaRelease[] { + const releases: IKonaRelease[] = []; + + for (const majorVersion in releaseInfo) { + const versions = releaseInfo[majorVersion]; + + for (const version of versions) { + if (!version.latest) { + continue; + } + + for (const file of version.files) { + if (file.os === os && file.arch === arch) { + releases.push({ + version: version.version, + jdkVersion: version.jdkVersion, + os: os, + arch: arch, + downloadUrl: version.baseUrl + file.filename, + checksum: file.checksum + }); + + break; + } + } + } + } + + return releases; + } + + private getOs(): string { + switch (process.platform) { + case 'darwin': + return 'macos'; + case 'win32': + return 'windows'; + default: + return process.platform; + } + } + + private getArch(): string { + switch (this.architecture) { + case 'arm64': + return 'aarch64'; + case 'x64': + return 'x86_64'; + default: + return this.architecture; + } + } +} diff --git a/src/distributions/kona/models.ts b/src/distributions/kona/models.ts new file mode 100644 index 000000000..196ab693e --- /dev/null +++ b/src/distributions/kona/models.ts @@ -0,0 +1,25 @@ +export interface IKonaReleaseInfo { + [majorVersion: string]: { + version: string; + jdkVersion: string; + latest: boolean; + + baseUrl: string; + files: { + os: string; // linux, macos, windows + arch: string; // x86_64, aarch64 + + filename: string; + checksum: string; + }[]; + }[]; +} + +export interface IKonaRelease { + version: string; + jdkVersion: string; + os: string; // linux, macos, windows + arch: string; // x86_64, aarch64 + downloadUrl: string; + checksum: string; // SHA-256 digest +}