Skip to content

Commit

Permalink
Add support for EA builds of Oracle GraalVM
Browse files Browse the repository at this point in the history
  • Loading branch information
fniephaus committed Sep 5, 2024
1 parent adc0a82 commit d8356f8
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 16 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/e2e-versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ jobs:
- distribution: graalvm
os: ubuntu-latest
version: 21
- distribution: graalvm
os: ubuntu-latest
version: '24-ea'
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down
53 changes: 48 additions & 5 deletions __tests__/distributors/graalvm-installer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,37 @@ describe('findPackageForDownload', () => {
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']
Expand All @@ -75,7 +106,7 @@ describe('findPackageForDownload', () => {
jest.spyOn(os, 'arch').mockReturnValue(osArch);
jest.spyOn(os, 'platform').mockReturnValue('linux');

const version = '17';
const version = '21';
const distro = new GraalVMDistribution({
version,
architecture: '', // to get default value
Expand All @@ -89,21 +120,33 @@ describe('findPackageForDownload', () => {
}
const archiveType = getDownloadArchiveExtension();
const result = await distro['findPackageForDownload'](version);
const expectedUrl = `https://download.oracle.com/graalvm/17/latest/graalvm-jdk-17_${osType}-${distroArch}_bin.${archiveType}`;
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 JDK is only supported for JDK 17 and later/
/GraalVM is only supported for JDK 17 and later/
);
await expect(distribution['findPackageForDownload']('11')).rejects.toThrow(
/GraalVM JDK is only supported for JDK 17 and later/
/GraalVM is only supported for JDK 17 and later/
);
await expect(distribution['findPackageForDownload']('18')).rejects.toThrow(
/Could not find GraalVM JDK for SemVer */
/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\?/
);
});
});
53 changes: 48 additions & 5 deletions dist/setup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -124362,6 +124362,8 @@ 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);
Expand All @@ -124387,10 +124389,10 @@ class GraalVMDistribution extends base_installer_1.JavaBase {
throw new Error(`Unsupported architecture: ${this.architecture}`);
}
if (!this.stable) {
throw new Error('Early access versions are not supported');
return this.findEABuildDownloadUrl(`${range}-ea`);
}
if (this.packageType !== 'jdk') {
throw new Error('GraalVM JDK provides only the `jdk` package type');
throw new Error('GraalVM provides only the `jdk` package type');
}
const platform = this.getPlatform();
const extension = (0, util_1.getDownloadArchiveExtension)();
Expand All @@ -124405,18 +124407,59 @@ class GraalVMDistribution extends base_installer_1.JavaBase {
fileUrl = `${GRAALVM_DL_BASE}/${range}/latest/graalvm-jdk-${range}_${platform}-${arch}_bin.${extension}`;
}
if (parseInt(major) < 17) {
throw new Error('GraalVM JDK is only supported for JDK 17 and later');
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 JDK for SemVer ${range}`);
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 JDK failed with status code: ${response.message.statusCode}`);
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':
Expand Down
74 changes: 68 additions & 6 deletions src/distributions/graalvm/installer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,17 @@ import {
JavaInstallerOptions,
JavaInstallerResults
} from '../base-models';
import {extractJdkFile, getDownloadArchiveExtension} from '../../util';
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) {
Expand Down Expand Up @@ -56,11 +63,11 @@ export class GraalVMDistribution extends JavaBase {
}

if (!this.stable) {
throw new Error('Early access versions are not supported');
return this.findEABuildDownloadUrl(`${range}-ea`);
}

if (this.packageType !== 'jdk') {
throw new Error('GraalVM JDK provides only the `jdk` package type');
throw new Error('GraalVM provides only the `jdk` package type');
}

const platform = this.getPlatform();
Expand All @@ -76,24 +83,79 @@ export class GraalVMDistribution extends JavaBase {
}

if (parseInt(major) < 17) {
throw new Error('GraalVM JDK is only supported for JDK 17 and later');
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 JDK for SemVer ${range}`);
throw new Error(`Could not find GraalVM for SemVer ${range}`);
}

if (response.message.statusCode !== HttpCodes.OK) {
throw new Error(
`Http request for GraalVM JDK failed with status code: ${response.message.statusCode}`
`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':
Expand Down
13 changes: 13 additions & 0 deletions src/distributions/graalvm/models.ts
Original file line number Diff line number Diff line change
@@ -1 +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[];
}

0 comments on commit d8356f8

Please sign in to comment.