From 8549eb9d9f3c5d48c2a7a56013627677aae319b3 Mon Sep 17 00:00:00 2001 From: John Jiang Date: Thu, 10 Oct 2024 17:13:30 +0800 Subject: [PATCH] Support Tencent Kona JDK (#671) --- .github/workflows/e2e-versions.yml | 3 +- README.md | 2 + __tests__/data/kona.json | 162 +++++++++++++ __tests__/distributors/kona-installer.test.ts | 221 ++++++++++++++++++ dist/setup/index.js | 178 ++++++++++++++ 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, 795 insertions(+), 5 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 045dee1..2599072 100644 --- a/.github/workflows/e2e-versions.yml +++ b/.github/workflows/e2e-versions.yml @@ -31,7 +31,8 @@ jobs: 'semeru', 'corretto', 'dragonwell', - 'sapmachine' + 'sapmachine', + 'kona' ] # internally 'adopt-hotspot' is the same as 'adopt' version: ['21', '11', '17'] exclude: diff --git a/README.md b/README.md index aaf9cce..7709473 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,7 @@ Currently, the following distributions are supported: | `dragonwell` | Alibaba Dragonwell JDK | [Link](https://dragonwell-jdk.io/) | [Link](https://www.aliyun.com/product/dragonwell/) | `sapmachine` | SAP SapMachine JDK/JRE | [Link](https://sapmachine.io/) | [Link](https://github.com/SAP/SapMachine/blob/sapmachine/LICENSE) | `graalvm` | Oracle GraalVM | [Link](https://www.graalvm.org/) | [Link](https://www.oracle.com/downloads/licenses/graal-free-license.html) +| `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. @@ -261,6 +262,7 @@ In the example above multiple JDKs are installed for the same job. The result af - [Alibaba Dragonwell](docs/advanced-usage.md#Alibaba-Dragonwell) - [SapMachine](docs/advanced-usage.md#SapMachine) - [GraalVM](docs/advanced-usage.md#GraalVM) + - [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 0000000..7caf845 --- /dev/null +++ b/__tests__/data/kona.json @@ -0,0 +1,162 @@ +{ + "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" + } + ] + } + ], + "21": [ + { + "version": "21.0.4", + "jdkVersion": "21.0.4", + "latest": true, + "baseUrl": "https://github.com/Tencent/TencentKona-21/releases/download/TencentKona-21.0.4/", + "files": [ + { + "os": "linux", + "arch": "aarch64", + "filename": "TencentKona-21.0.4.b1-jdk_linux-aarch64.tar.gz", + "checksum": "47b81d125b2bbd7a77f9220aac38f5b1dcc990995b8888e0ecbd3e40418381d9" + }, + { + "os": "linux", + "arch": "x86_64", + "filename": "TencentKona-21.0.4.b1-jdk_linux-x86_64.tar.gz", + "checksum": "f506d86c5a9321d37cd7aaa783529653f2b15d5817f2cd9eda3e2131029dd7a4" + }, + { + "os": "macos", + "arch": "aarch64", + "filename": "TencentKona-21.0.4.b1_jdk_macosx-aarch64_notarized.tar.gz", + "checksum": "71041e40bacacb99376e09229263cf3254d5c723074b248f4a590d324a06c188" + }, + { + "os": "macos", + "arch": "x86_64", + "filename": "TencentKona-21.0.4.b1_jdk_macosx-x86_64_notarized.tar.gz", + "checksum": "445703ac1cae143090362da36ca08c3975190f37d149913ab2495bc26c3d41f7" + }, + { + "os": "windows", + "arch": "x86_64", + "filename": "TencentKona-21.0.4.b1_jdk_windows-x86_64_signed.zip", + "checksum": "0e10f33df898567dd33c2cdd8e5352dee86b699e810c16b3a4e5e38715d26447" + } + ] + } + ] +} diff --git a/__tests__/distributors/kona-installer.test.ts b/__tests__/distributors/kona-installer.test.ts new file mode 100644 index 0000000..4470317 --- /dev/null +++ b/__tests__/distributors/kona-installer.test.ts @@ -0,0 +1,221 @@ +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'], + ['21.0.4', 'linux', 'x86_64', 'linux-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(4); + 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' + ], + + [ + '21', + 'linux', + 'aarch64', + 'https://github.com/Tencent/TencentKona-21/releases/download/TencentKona-21.0.4/TencentKona-21.0.4.b1-jdk_linux-aarch64.tar.gz' + ], + [ + '21.0.4', + 'linux', + 'x86_64', + 'https://github.com/Tencent/TencentKona-21/releases/download/TencentKona-21.0.4/TencentKona-21.0.4.b1-jdk_linux-x86_64.tar.gz' + ], + [ + '21.0.4', + 'macos', + 'aarch64', + 'https://github.com/Tencent/TencentKona-21/releases/download/TencentKona-21.0.4/TencentKona-21.0.4.b1_jdk_macosx-aarch64_notarized.tar.gz' + ], + [ + '21.0.4', + 'macos', + 'x86_64', + 'https://github.com/Tencent/TencentKona-21/releases/download/TencentKona-21.0.4/TencentKona-21.0.4.b1_jdk_macosx-x86_64_notarized.tar.gz' + ], + [ + '21.0.4', + 'windows', + 'x86_64', + 'https://github.com/Tencent/TencentKona-21/releases/download/TencentKona-21.0.4/TencentKona-21.0.4.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'], + ['22', '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 6dd09d3..a2ef234 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -124051,6 +124051,7 @@ const installer_9 = __nccwpck_require__(64298); const installer_10 = __nccwpck_require__(16132); const installer_11 = __nccwpck_require__(52869); const installer_12 = __nccwpck_require__(55644); +const installer_13 = __nccwpck_require__(45696); var JavaDistribution; (function (JavaDistribution) { JavaDistribution["Adopt"] = "adopt"; @@ -124067,6 +124068,7 @@ var JavaDistribution; JavaDistribution["Dragonwell"] = "dragonwell"; JavaDistribution["SapMachine"] = "sapmachine"; JavaDistribution["GraalVM"] = "graalvm"; + JavaDistribution["Kona"] = "kona"; })(JavaDistribution || (JavaDistribution = {})); function getJavaDistribution(distributionName, installerOptions, jdkFile) { switch (distributionName) { @@ -124097,6 +124099,8 @@ function getJavaDistribution(distributionName, installerOptions, jdkFile) { return new installer_11.SapMachineDistribution(installerOptions); case JavaDistribution.GraalVM: return new installer_12.GraalVMDistribution(installerOptions); + case JavaDistribution.Kona: + return new installer_13.KonaDistribution(installerOptions); default: return null; } @@ -124480,6 +124484,180 @@ class GraalVMDistribution extends base_installer_1.JavaBase { exports.GraalVMDistribution = GraalVMDistribution; +/***/ }), + +/***/ 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: diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index efc443b..52490ca 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -10,6 +10,7 @@ - [Alibaba Dragonwell](#Alibaba-Dragonwell) - [SapMachine](#SapMachine) - [GraalVM](#GraalVM) + - [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) @@ -171,6 +172,19 @@ steps: native-image -cp java HelloWorldApp ``` +### Tencent Kona +**NOTE:** Tencent Kona supports major versions 8, 11, 17 and 21, 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: @@ -211,7 +225,7 @@ steps: jdkFile: ${{ runner.temp }}/java_package.tar.gz java-version: '11.0.0' architecture: x64 - + - run: java -cp java HelloWorldApp ``` @@ -556,12 +570,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 563c9a8..3e6d493 100644 --- a/src/distributions/distribution-factory.ts +++ b/src/distributions/distribution-factory.ts @@ -12,6 +12,7 @@ import {OracleDistribution} from './oracle/installer'; import {DragonwellDistribution} from './dragonwell/installer'; import {SapMachineDistribution} from './sapmachine/installer'; import {GraalVMDistribution} from './graalvm/installer'; +import {KonaDistribution} from './kona/installer'; enum JavaDistribution { Adopt = 'adopt', @@ -27,7 +28,8 @@ enum JavaDistribution { Oracle = 'oracle', Dragonwell = 'dragonwell', SapMachine = 'sapmachine', - GraalVM = 'graalvm' + GraalVM = 'graalvm', + Kona = 'kona' } export function getJavaDistribution( @@ -72,6 +74,8 @@ export function getJavaDistribution( return new SapMachineDistribution(installerOptions); case JavaDistribution.GraalVM: return new GraalVMDistribution(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 0000000..e09c1b5 --- /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 0000000..196ab69 --- /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 +}