Add support for Oracle GraalVM (#501)
* Add support for Oracle GraalVM * Add support for EA builds of Oracle GraalVM
This commit is contained in:
		
							parent
							
								
									bcfbca5b71
								
							
						
					
					
						commit
						0a40ce6f61
					
				
							
								
								
									
										22
									
								
								.github/workflows/e2e-versions.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								.github/workflows/e2e-versions.yml
									
									
									
									
										vendored
									
									
								
							| @ -45,11 +45,22 @@ jobs: | ||||
|             version: 17 | ||||
|           - distribution: oracle | ||||
|             os: windows-latest | ||||
|             version: 20 | ||||
|             version: 21 | ||||
|           - distribution: oracle | ||||
|             os: ubuntu-latest | ||||
|             version: 20 | ||||
| 
 | ||||
|             version: 21 | ||||
|           - distribution: graalvm | ||||
|             os: macos-latest | ||||
|             version: 17 | ||||
|           - distribution: graalvm | ||||
|             os: windows-latest | ||||
|             version: 21 | ||||
|           - distribution: graalvm | ||||
|             os: ubuntu-latest | ||||
|             version: 21 | ||||
|           - distribution: graalvm | ||||
|             os: ubuntu-latest | ||||
|             version: '24-ea' | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
| @ -79,7 +90,10 @@ jobs: | ||||
|         include: | ||||
|           - distribution: oracle | ||||
|             os: ubuntu-latest | ||||
|             version: '20.0.1' | ||||
|             version: '21.0.4' | ||||
|           - distribution: graalvm | ||||
|             os: ubuntu-latest | ||||
|             version: '21.0.4' | ||||
|           - distribution: dragonwell | ||||
|             os: ubuntu-latest | ||||
|             version: '11.0' | ||||
|  | ||||
| @ -109,6 +109,7 @@ Currently, the following distributions are supported: | ||||
| | `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/) | ||||
| | `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) | ||||
| 
 | ||||
| **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. | ||||
| 
 | ||||
| @ -259,6 +260,7 @@ In the example above multiple JDKs are installed for the same job. The result af | ||||
|   - [Oracle](docs/advanced-usage.md#Oracle) | ||||
|   - [Alibaba Dragonwell](docs/advanced-usage.md#Alibaba-Dragonwell) | ||||
|   - [SapMachine](docs/advanced-usage.md#SapMachine) | ||||
|   - [GraalVM](docs/advanced-usage.md#GraalVM) | ||||
| - [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) | ||||
|  | ||||
							
								
								
									
										152
									
								
								__tests__/distributors/graalvm-installer.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								__tests__/distributors/graalvm-installer.test.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,152 @@ | ||||
| import {GraalVMDistribution} from '../../src/distributions/graalvm/installer'; | ||||
| import os from 'os'; | ||||
| import * as core from '@actions/core'; | ||||
| import {getDownloadArchiveExtension} from '../../src/util'; | ||||
| import {HttpClient} from '@actions/http-client'; | ||||
| 
 | ||||
| describe('findPackageForDownload', () => { | ||||
|   let distribution: GraalVMDistribution; | ||||
|   let spyDebug: jest.SpyInstance; | ||||
|   let spyHttpClient: jest.SpyInstance; | ||||
| 
 | ||||
|   beforeEach(() => { | ||||
|     distribution = new GraalVMDistribution({ | ||||
|       version: '', | ||||
|       architecture: 'x64', | ||||
|       packageType: 'jdk', | ||||
|       checkLatest: false | ||||
|     }); | ||||
| 
 | ||||
|     spyDebug = jest.spyOn(core, 'debug'); | ||||
|     spyDebug.mockImplementation(() => {}); | ||||
|   }); | ||||
| 
 | ||||
|   it.each([ | ||||
|     [ | ||||
|       '21', | ||||
|       '21', | ||||
|       'https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_{{OS_TYPE}}-x64_bin.{{ARCHIVE_TYPE}}' | ||||
|     ], | ||||
|     [ | ||||
|       '21.0.4', | ||||
|       '21.0.4', | ||||
|       'https://download.oracle.com/graalvm/21/archive/graalvm-jdk-21.0.4_{{OS_TYPE}}-x64_bin.{{ARCHIVE_TYPE}}' | ||||
|     ], | ||||
|     [ | ||||
|       '17', | ||||
|       '17', | ||||
|       'https://download.oracle.com/graalvm/17/latest/graalvm-jdk-17_{{OS_TYPE}}-x64_bin.{{ARCHIVE_TYPE}}' | ||||
|     ], | ||||
|     [ | ||||
|       '17.0.12', | ||||
|       '17.0.12', | ||||
|       'https://download.oracle.com/graalvm/17/archive/graalvm-jdk-17.0.12_{{OS_TYPE}}-x64_bin.{{ARCHIVE_TYPE}}' | ||||
|     ] | ||||
|   ])('version is %s -> %s', async (input, expectedVersion, expectedUrl) => { | ||||
|     /* Needed only for this particular test because /latest/ urls tend to change */ | ||||
|     spyHttpClient = jest.spyOn(HttpClient.prototype, 'head'); | ||||
|     spyHttpClient.mockReturnValue( | ||||
|       Promise.resolve({ | ||||
|         message: { | ||||
|           statusCode: 200 | ||||
|         } | ||||
|       }) | ||||
|     ); | ||||
| 
 | ||||
|     const result = await distribution['findPackageForDownload'](input); | ||||
| 
 | ||||
|     jest.restoreAllMocks(); | ||||
| 
 | ||||
|     expect(result.version).toBe(expectedVersion); | ||||
|     const osType = distribution.getPlatform(); | ||||
|     const archiveType = getDownloadArchiveExtension(); | ||||
|     const url = expectedUrl | ||||
|       .replace('{{OS_TYPE}}', osType) | ||||
|       .replace('{{ARCHIVE_TYPE}}', archiveType); | ||||
|     expect(result.url).toBe(url); | ||||
|   }); | ||||
| 
 | ||||
|   it.each([ | ||||
|     [ | ||||
|       '24-ea', | ||||
|       /^https:\/\/github\.com\/graalvm\/oracle-graalvm-ea-builds\/releases\/download\/jdk-24\.0\.0-ea\./ | ||||
|     ] | ||||
|   ])('version is %s -> %s', async (version, expectedUrlPrefix) => { | ||||
|     /* Needed only for this particular test because /latest/ urls tend to change */ | ||||
|     spyHttpClient = jest.spyOn(HttpClient.prototype, 'head'); | ||||
|     spyHttpClient.mockReturnValue( | ||||
|       Promise.resolve({ | ||||
|         message: { | ||||
|           statusCode: 200 | ||||
|         } | ||||
|       }) | ||||
|     ); | ||||
| 
 | ||||
|     const eaDistro = new GraalVMDistribution({ | ||||
|       version, | ||||
|       architecture: '', // to get default value
 | ||||
|       packageType: 'jdk', | ||||
|       checkLatest: false | ||||
|     }); | ||||
| 
 | ||||
|     const versionWithoutEA = version.split('-')[0]; | ||||
|     const result = await eaDistro['findPackageForDownload'](versionWithoutEA); | ||||
| 
 | ||||
|     jest.restoreAllMocks(); | ||||
| 
 | ||||
|     expect(result.url).toEqual(expect.stringMatching(expectedUrlPrefix)); | ||||
|   }); | ||||
| 
 | ||||
|   it.each([ | ||||
|     ['amd64', 'x64'], | ||||
|     ['arm64', 'aarch64'] | ||||
|   ])( | ||||
|     'defaults to os.arch(): %s mapped to distro arch: %s', | ||||
|     async (osArch: string, distroArch: string) => { | ||||
|       jest.spyOn(os, 'arch').mockReturnValue(osArch); | ||||
|       jest.spyOn(os, 'platform').mockReturnValue('linux'); | ||||
| 
 | ||||
|       const version = '21'; | ||||
|       const distro = new GraalVMDistribution({ | ||||
|         version, | ||||
|         architecture: '', // to get default value
 | ||||
|         packageType: 'jdk', | ||||
|         checkLatest: false | ||||
|       }); | ||||
| 
 | ||||
|       const osType = distribution.getPlatform(); | ||||
|       if (osType === 'windows' && distroArch == 'aarch64') { | ||||
|         return; // skip, aarch64 is not available for Windows
 | ||||
|       } | ||||
|       const archiveType = getDownloadArchiveExtension(); | ||||
|       const result = await distro['findPackageForDownload'](version); | ||||
|       const expectedUrl = `https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_${osType}-${distroArch}_bin.${archiveType}`; | ||||
| 
 | ||||
|       expect(result.url).toBe(expectedUrl); | ||||
|     } | ||||
|   ); | ||||
| 
 | ||||
|   it('should throw an error', async () => { | ||||
|     await expect(distribution['findPackageForDownload']('8')).rejects.toThrow( | ||||
|       /GraalVM is only supported for JDK 17 and later/ | ||||
|     ); | ||||
|     await expect(distribution['findPackageForDownload']('11')).rejects.toThrow( | ||||
|       /GraalVM is only supported for JDK 17 and later/ | ||||
|     ); | ||||
|     await expect(distribution['findPackageForDownload']('18')).rejects.toThrow( | ||||
|       /Could not find GraalVM for SemVer */ | ||||
|     ); | ||||
| 
 | ||||
|     const unavailableEADistro = new GraalVMDistribution({ | ||||
|       version: '17-ea', | ||||
|       architecture: '', // to get default value
 | ||||
|       packageType: 'jdk', | ||||
|       checkLatest: false | ||||
|     }); | ||||
|     await expect( | ||||
|       unavailableEADistro['findPackageForDownload']('17') | ||||
|     ).rejects.toThrow( | ||||
|       /No GraalVM EA build found\. Are you sure java-version: '17-ea' is correct\?/ | ||||
|     ); | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										170
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										170
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							| @ -124050,6 +124050,7 @@ const installer_8 = __nccwpck_require__(34750); | ||||
| const installer_9 = __nccwpck_require__(64298); | ||||
| const installer_10 = __nccwpck_require__(16132); | ||||
| const installer_11 = __nccwpck_require__(52869); | ||||
| const installer_12 = __nccwpck_require__(55644); | ||||
| var JavaDistribution; | ||||
| (function (JavaDistribution) { | ||||
|     JavaDistribution["Adopt"] = "adopt"; | ||||
| @ -124065,6 +124066,7 @@ var JavaDistribution; | ||||
|     JavaDistribution["Oracle"] = "oracle"; | ||||
|     JavaDistribution["Dragonwell"] = "dragonwell"; | ||||
|     JavaDistribution["SapMachine"] = "sapmachine"; | ||||
|     JavaDistribution["GraalVM"] = "graalvm"; | ||||
| })(JavaDistribution || (JavaDistribution = {})); | ||||
| function getJavaDistribution(distributionName, installerOptions, jdkFile) { | ||||
|     switch (distributionName) { | ||||
| @ -124093,6 +124095,8 @@ function getJavaDistribution(distributionName, installerOptions, jdkFile) { | ||||
|             return new installer_10.DragonwellDistribution(installerOptions); | ||||
|         case JavaDistribution.SapMachine: | ||||
|             return new installer_11.SapMachineDistribution(installerOptions); | ||||
|         case JavaDistribution.GraalVM: | ||||
|             return new installer_12.GraalVMDistribution(installerOptions); | ||||
|         default: | ||||
|             return null; | ||||
|     } | ||||
| @ -124310,6 +124314,172 @@ class DragonwellDistribution extends base_installer_1.JavaBase { | ||||
| exports.DragonwellDistribution = DragonwellDistribution; | ||||
| 
 | ||||
| 
 | ||||
| /***/ }), | ||||
| 
 | ||||
| /***/ 55644: | ||||
| /***/ (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.GraalVMDistribution = 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); | ||||
| const http_client_1 = __nccwpck_require__(96255); | ||||
| const GRAALVM_DL_BASE = 'https://download.oracle.com/graalvm'; | ||||
| const IS_WINDOWS = process.platform === 'win32'; | ||||
| const GRAALVM_PLATFORM = IS_WINDOWS ? 'windows' : process.platform; | ||||
| class GraalVMDistribution extends base_installer_1.JavaBase { | ||||
|     constructor(installerOptions) { | ||||
|         super('GraalVM', installerOptions); | ||||
|     } | ||||
|     downloadTool(javaRelease) { | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             core.info(`Downloading Java ${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(range) { | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             const arch = this.distributionArchitecture(); | ||||
|             if (arch !== 'x64' && arch !== 'aarch64') { | ||||
|                 throw new Error(`Unsupported architecture: ${this.architecture}`); | ||||
|             } | ||||
|             if (!this.stable) { | ||||
|                 return this.findEABuildDownloadUrl(`${range}-ea`); | ||||
|             } | ||||
|             if (this.packageType !== 'jdk') { | ||||
|                 throw new Error('GraalVM provides only the `jdk` package type'); | ||||
|             } | ||||
|             const platform = this.getPlatform(); | ||||
|             const extension = (0, util_1.getDownloadArchiveExtension)(); | ||||
|             let major; | ||||
|             let fileUrl; | ||||
|             if (range.includes('.')) { | ||||
|                 major = range.split('.')[0]; | ||||
|                 fileUrl = `${GRAALVM_DL_BASE}/${major}/archive/graalvm-jdk-${range}_${platform}-${arch}_bin.${extension}`; | ||||
|             } | ||||
|             else { | ||||
|                 major = range; | ||||
|                 fileUrl = `${GRAALVM_DL_BASE}/${range}/latest/graalvm-jdk-${range}_${platform}-${arch}_bin.${extension}`; | ||||
|             } | ||||
|             if (parseInt(major) < 17) { | ||||
|                 throw new Error('GraalVM is only supported for JDK 17 and later'); | ||||
|             } | ||||
|             const response = yield this.http.head(fileUrl); | ||||
|             if (response.message.statusCode === http_client_1.HttpCodes.NotFound) { | ||||
|                 throw new Error(`Could not find GraalVM for SemVer ${range}`); | ||||
|             } | ||||
|             if (response.message.statusCode !== http_client_1.HttpCodes.OK) { | ||||
|                 throw new Error(`Http request for GraalVM failed with status code: ${response.message.statusCode}`); | ||||
|             } | ||||
|             return { url: fileUrl, version: range }; | ||||
|         }); | ||||
|     } | ||||
|     findEABuildDownloadUrl(javaEaVersion) { | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             const versions = yield this.fetchEAJson(javaEaVersion); | ||||
|             const latestVersion = versions.find(v => v.latest); | ||||
|             if (!latestVersion) { | ||||
|                 throw new Error(`Unable to find latest version for '${javaEaVersion}'`); | ||||
|             } | ||||
|             const arch = this.distributionArchitecture(); | ||||
|             const file = latestVersion.files.find(f => f.arch === arch && f.platform === GRAALVM_PLATFORM); | ||||
|             if (!file || !file.filename.startsWith('graalvm-jdk-')) { | ||||
|                 throw new Error(`Unable to find file metadata for '${javaEaVersion}'`); | ||||
|             } | ||||
|             return { | ||||
|                 url: `${latestVersion.download_base_url}${file.filename}`, | ||||
|                 version: latestVersion.version | ||||
|             }; | ||||
|         }); | ||||
|     } | ||||
|     fetchEAJson(javaEaVersion) { | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             const owner = 'graalvm'; | ||||
|             const repository = 'oracle-graalvm-ea-builds'; | ||||
|             const branch = 'main'; | ||||
|             const filePath = `versions/${javaEaVersion}.json`; | ||||
|             const url = `https://api.github.com/repos/${owner}/${repository}/contents/${filePath}?ref=${branch}`; | ||||
|             const headers = (0, util_1.getGitHubHttpHeaders)(); | ||||
|             core.debug(`Trying to fetch available version info for GraalVM EA builds from '${url}'`); | ||||
|             let fetchedJson; | ||||
|             try { | ||||
|                 fetchedJson = (yield this.http.getJson(url, headers)) | ||||
|                     .result; | ||||
|             } | ||||
|             catch (err) { | ||||
|                 throw Error(`Fetching version info for GraalVM EA builds from '${url}' failed with the error: ${err.message}`); | ||||
|             } | ||||
|             if (fetchedJson === null) { | ||||
|                 throw Error(`No GraalVM EA build found. Are you sure java-version: '${javaEaVersion}' is correct?`); | ||||
|             } | ||||
|             return fetchedJson; | ||||
|         }); | ||||
|     } | ||||
|     getPlatform(platform = process.platform) { | ||||
|         switch (platform) { | ||||
|             case 'darwin': | ||||
|                 return 'macos'; | ||||
|             case 'win32': | ||||
|                 return 'windows'; | ||||
|             case 'linux': | ||||
|                 return 'linux'; | ||||
|             default: | ||||
|                 throw new Error(`Platform '${platform}' is not supported. Supported platforms: 'linux', 'macos', 'windows'`); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| exports.GraalVMDistribution = GraalVMDistribution; | ||||
| 
 | ||||
| 
 | ||||
| /***/ }), | ||||
| 
 | ||||
| /***/ 40883: | ||||
|  | ||||
| @ -9,6 +9,7 @@ | ||||
|   - [Oracle](#Oracle) | ||||
|   - [Alibaba Dragonwell](#Alibaba-Dragonwell) | ||||
|   - [SapMachine](#SapMachine) | ||||
|   - [GraalVM](#GraalVM) | ||||
| - [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) | ||||
| @ -155,6 +156,21 @@ steps: | ||||
| - run: java -cp java HelloWorldApp | ||||
| ``` | ||||
| 
 | ||||
| ### GraalVM | ||||
| **NOTE:** Oracle GraalVM is only available for JDK 17 and later. | ||||
| 
 | ||||
| ```yaml | ||||
| steps: | ||||
| - uses: actions/checkout@v4 | ||||
| - uses: actions/setup-java@v4 | ||||
|   with: | ||||
|     distribution: 'graalvm' | ||||
|     java-version: '21' | ||||
| - run: | | ||||
|     java -cp java HelloWorldApp | ||||
|     native-image -cp java HelloWorldApp | ||||
| ``` | ||||
| 
 | ||||
| ## Installing custom Java package type | ||||
| ```yaml | ||||
| steps: | ||||
|  | ||||
| @ -11,6 +11,7 @@ import {CorrettoDistribution} from './corretto/installer'; | ||||
| import {OracleDistribution} from './oracle/installer'; | ||||
| import {DragonwellDistribution} from './dragonwell/installer'; | ||||
| import {SapMachineDistribution} from './sapmachine/installer'; | ||||
| import {GraalVMDistribution} from './graalvm/installer'; | ||||
| 
 | ||||
| enum JavaDistribution { | ||||
|   Adopt = 'adopt', | ||||
| @ -25,7 +26,8 @@ enum JavaDistribution { | ||||
|   Corretto = 'corretto', | ||||
|   Oracle = 'oracle', | ||||
|   Dragonwell = 'dragonwell', | ||||
|   SapMachine = 'sapmachine' | ||||
|   SapMachine = 'sapmachine', | ||||
|   GraalVM = 'graalvm' | ||||
| } | ||||
| 
 | ||||
| export function getJavaDistribution( | ||||
| @ -68,6 +70,8 @@ export function getJavaDistribution( | ||||
|       return new DragonwellDistribution(installerOptions); | ||||
|     case JavaDistribution.SapMachine: | ||||
|       return new SapMachineDistribution(installerOptions); | ||||
|     case JavaDistribution.GraalVM: | ||||
|       return new GraalVMDistribution(installerOptions); | ||||
|     default: | ||||
|       return null; | ||||
|   } | ||||
|  | ||||
							
								
								
									
										173
									
								
								src/distributions/graalvm/installer.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								src/distributions/graalvm/installer.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,173 @@ | ||||
| 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 { | ||||
|   JavaDownloadRelease, | ||||
|   JavaInstallerOptions, | ||||
|   JavaInstallerResults | ||||
| } from '../base-models'; | ||||
| import { | ||||
|   extractJdkFile, | ||||
|   getDownloadArchiveExtension, | ||||
|   getGitHubHttpHeaders | ||||
| } from '../../util'; | ||||
| import {HttpCodes} from '@actions/http-client'; | ||||
| import {GraalVMEAVersion} from './models'; | ||||
| 
 | ||||
| const GRAALVM_DL_BASE = 'https://download.oracle.com/graalvm'; | ||||
| const IS_WINDOWS = process.platform === 'win32'; | ||||
| const GRAALVM_PLATFORM = IS_WINDOWS ? 'windows' : process.platform; | ||||
| 
 | ||||
| export class GraalVMDistribution extends JavaBase { | ||||
|   constructor(installerOptions: JavaInstallerOptions) { | ||||
|     super('GraalVM', installerOptions); | ||||
|   } | ||||
| 
 | ||||
|   protected async downloadTool( | ||||
|     javaRelease: JavaDownloadRelease | ||||
|   ): Promise<JavaInstallerResults> { | ||||
|     core.info( | ||||
|       `Downloading Java ${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( | ||||
|     range: string | ||||
|   ): Promise<JavaDownloadRelease> { | ||||
|     const arch = this.distributionArchitecture(); | ||||
|     if (arch !== 'x64' && arch !== 'aarch64') { | ||||
|       throw new Error(`Unsupported architecture: ${this.architecture}`); | ||||
|     } | ||||
| 
 | ||||
|     if (!this.stable) { | ||||
|       return this.findEABuildDownloadUrl(`${range}-ea`); | ||||
|     } | ||||
| 
 | ||||
|     if (this.packageType !== 'jdk') { | ||||
|       throw new Error('GraalVM provides only the `jdk` package type'); | ||||
|     } | ||||
| 
 | ||||
|     const platform = this.getPlatform(); | ||||
|     const extension = getDownloadArchiveExtension(); | ||||
|     let major; | ||||
|     let fileUrl; | ||||
|     if (range.includes('.')) { | ||||
|       major = range.split('.')[0]; | ||||
|       fileUrl = `${GRAALVM_DL_BASE}/${major}/archive/graalvm-jdk-${range}_${platform}-${arch}_bin.${extension}`; | ||||
|     } else { | ||||
|       major = range; | ||||
|       fileUrl = `${GRAALVM_DL_BASE}/${range}/latest/graalvm-jdk-${range}_${platform}-${arch}_bin.${extension}`; | ||||
|     } | ||||
| 
 | ||||
|     if (parseInt(major) < 17) { | ||||
|       throw new Error('GraalVM is only supported for JDK 17 and later'); | ||||
|     } | ||||
| 
 | ||||
|     const response = await this.http.head(fileUrl); | ||||
| 
 | ||||
|     if (response.message.statusCode === HttpCodes.NotFound) { | ||||
|       throw new Error(`Could not find GraalVM for SemVer ${range}`); | ||||
|     } | ||||
| 
 | ||||
|     if (response.message.statusCode !== HttpCodes.OK) { | ||||
|       throw new Error( | ||||
|         `Http request for GraalVM failed with status code: ${response.message.statusCode}` | ||||
|       ); | ||||
|     } | ||||
| 
 | ||||
|     return {url: fileUrl, version: range}; | ||||
|   } | ||||
| 
 | ||||
|   private async findEABuildDownloadUrl( | ||||
|     javaEaVersion: string | ||||
|   ): Promise<JavaDownloadRelease> { | ||||
|     const versions = await this.fetchEAJson(javaEaVersion); | ||||
|     const latestVersion = versions.find(v => v.latest); | ||||
|     if (!latestVersion) { | ||||
|       throw new Error(`Unable to find latest version for '${javaEaVersion}'`); | ||||
|     } | ||||
|     const arch = this.distributionArchitecture(); | ||||
|     const file = latestVersion.files.find( | ||||
|       f => f.arch === arch && f.platform === GRAALVM_PLATFORM | ||||
|     ); | ||||
|     if (!file || !file.filename.startsWith('graalvm-jdk-')) { | ||||
|       throw new Error(`Unable to find file metadata for '${javaEaVersion}'`); | ||||
|     } | ||||
|     return { | ||||
|       url: `${latestVersion.download_base_url}${file.filename}`, | ||||
|       version: latestVersion.version | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   private async fetchEAJson( | ||||
|     javaEaVersion: string | ||||
|   ): Promise<GraalVMEAVersion[]> { | ||||
|     const owner = 'graalvm'; | ||||
|     const repository = 'oracle-graalvm-ea-builds'; | ||||
|     const branch = 'main'; | ||||
|     const filePath = `versions/${javaEaVersion}.json`; | ||||
| 
 | ||||
|     const url = `https://api.github.com/repos/${owner}/${repository}/contents/${filePath}?ref=${branch}`; | ||||
| 
 | ||||
|     const headers = getGitHubHttpHeaders(); | ||||
| 
 | ||||
|     core.debug( | ||||
|       `Trying to fetch available version info for GraalVM EA builds from '${url}'` | ||||
|     ); | ||||
|     let fetchedJson; | ||||
|     try { | ||||
|       fetchedJson = (await this.http.getJson<GraalVMEAVersion[]>(url, headers)) | ||||
|         .result; | ||||
|     } catch (err) { | ||||
|       throw Error( | ||||
|         `Fetching version info for GraalVM EA builds from '${url}' failed with the error: ${ | ||||
|           (err as Error).message | ||||
|         }` | ||||
|       ); | ||||
|     } | ||||
|     if (fetchedJson === null) { | ||||
|       throw Error( | ||||
|         `No GraalVM EA build found. Are you sure java-version: '${javaEaVersion}' is correct?` | ||||
|       ); | ||||
|     } | ||||
|     return fetchedJson; | ||||
|   } | ||||
| 
 | ||||
|   public getPlatform(platform: NodeJS.Platform = process.platform): OsVersions { | ||||
|     switch (platform) { | ||||
|       case 'darwin': | ||||
|         return 'macos'; | ||||
|       case 'win32': | ||||
|         return 'windows'; | ||||
|       case 'linux': | ||||
|         return 'linux'; | ||||
|       default: | ||||
|         throw new Error( | ||||
|           `Platform '${platform}' is not supported. Supported platforms: 'linux', 'macos', 'windows'` | ||||
|         ); | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										14
									
								
								src/distributions/graalvm/models.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/distributions/graalvm/models.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| export type OsVersions = 'linux' | 'macos' | 'windows'; | ||||
| 
 | ||||
| export interface GraalVMEAFile { | ||||
|   filename: string; | ||||
|   arch: 'aarch64' | 'x64'; | ||||
|   platform: 'darwin' | 'linux' | 'windows'; | ||||
| } | ||||
| 
 | ||||
| export interface GraalVMEAVersion { | ||||
|   version: string; | ||||
|   latest?: boolean; | ||||
|   download_base_url: string; | ||||
|   files: GraalVMEAFile[]; | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user