import * as c from './constants' import * as semver from 'semver' import { downloadAndExtractJDK, downloadExtractAndCacheJDK, getLatestPrerelease, getLatestRelease, getMatchingTags, getTaggedRelease, toSemVer } from './utils' import {downloadGraalVMEELegacy} from './gds' import {downloadTool} from '@actions/tool-cache' import {basename} from 'path' const GRAALVM_DL_BASE = 'https://download.oracle.com/graalvm' const GRAALVM_CE_DL_BASE = `https://github.com/graalvm/${c.GRAALVM_RELEASES_REPO}/releases/download` const ORACLE_GRAALVM_REPO_EA_BUILDS = 'oracle-graalvm-dev-builds' const GRAALVM_REPO_DEV_BUILDS = 'graalvm-ce-dev-builds' const GRAALVM_JDK_TAG_PREFIX = 'jdk-' const GRAALVM_TAG_PREFIX = 'vm-' // Support for GraalVM for JDK 17 and later export async function setUpGraalVMJDK( javaVersionOrDev: string ): Promise { if (javaVersionOrDev === c.VERSION_DEV) { return setUpGraalVMJDKDevBuild() } const javaVersion = javaVersionOrDev const toolName = determineToolName(javaVersion, false) let downloadName = toolName let downloadUrl: string if (javaVersion.includes('.')) { if (semver.valid(javaVersion)) { const majorJavaVersion = semver.major(javaVersion) const minorJavaVersion = semver.minor(javaVersion) const patchJavaVersion = semver.patch(javaVersion) const isGARelease = minorJavaVersion === 0 && patchJavaVersion === 0 if (isGARelease) { // For GA versions of JDKs, /archive/ does not use minor and patch version (see https://www.oracle.com/java/technologies/jdk-script-friendly-urls/) downloadName = determineToolName(majorJavaVersion.toString(), false) } downloadUrl = `${GRAALVM_DL_BASE}/${majorJavaVersion}/archive/${downloadName}${c.GRAALVM_FILE_EXTENSION}` } else { throw new Error( `java-version set to '${javaVersion}'. Please make sure the java-version is set correctly. ${c.ERROR_HINT}` ) } } else if (javaVersion === '22-ea') { downloadUrl = await findLatestEABuildDownloadUrl(javaVersion) } else { downloadUrl = `${GRAALVM_DL_BASE}/${javaVersion}/latest/${downloadName}${c.GRAALVM_FILE_EXTENSION}` } const downloader = async () => downloadGraalVMJDK(downloadUrl, javaVersion) return downloadExtractAndCacheJDK(downloader, toolName, javaVersion) } async function findLatestEABuildDownloadUrl( javaEaVersion: string ): Promise { const latestPrerelease = await getLatestPrerelease( ORACLE_GRAALVM_REPO_EA_BUILDS ) const expectedFileNamePrefix = 'graalvm-jdk-' const expectedFileNameSuffix = `_${c.JDK_PLATFORM}-${c.JDK_ARCH}_bin${c.GRAALVM_FILE_EXTENSION}` for (const asset of latestPrerelease.assets) { if ( asset.name.startsWith(expectedFileNamePrefix) && asset.name.endsWith(expectedFileNameSuffix) ) { return asset.browser_download_url } } throw new Error( `Could not find Oracle GraalVM build for ${javaEaVersion}. ${c.ERROR_HINT}` ) } export async function setUpGraalVMJDKCE( javaVersionOrDev: string ): Promise { if (javaVersionOrDev === c.VERSION_DEV) { return setUpGraalVMJDKDevBuild() } let javaVersion = javaVersionOrDev if (!javaVersion.includes('.')) { javaVersion = await findLatestGraalVMJDKCEJavaVersion(javaVersion) } if (javaVersion.split('.').length != 3) { throw new Error( `java-version set to '${javaVersionOrDev}', which was resolved to '${javaVersion}'. Please make sure the java-version is set correctly. ${c.ERROR_HINT}` ) } const toolName = determineToolName(javaVersion, true) const downloadUrl = `${GRAALVM_CE_DL_BASE}/jdk-${javaVersion}/${toolName}${c.GRAALVM_FILE_EXTENSION}` const downloader = async () => downloadGraalVMJDK(downloadUrl, javaVersion) return downloadExtractAndCacheJDK(downloader, toolName, javaVersion) } export async function findLatestGraalVMJDKCEJavaVersion( majorJavaVersion: string ): Promise { const matchingRefs = await getMatchingTags( `${GRAALVM_JDK_TAG_PREFIX}${majorJavaVersion}` ) const lowestNonExistingVersion = '0.0.1' let highestVersion = lowestNonExistingVersion const versionNumberStartIndex = `refs/tags/${GRAALVM_JDK_TAG_PREFIX}`.length for (const matchingRef of matchingRefs) { const currentVersion = matchingRef.ref.substring(versionNumberStartIndex) if ( semver.valid(currentVersion) && semver.gt(currentVersion, highestVersion) ) { highestVersion = currentVersion } } if (highestVersion === lowestNonExistingVersion) { throw new Error( `Unable to find the latest Java version for '${majorJavaVersion}'. Please make sure the java-version is set correctly. ${c.ERROR_HINT}` ) } return highestVersion } function determineToolName(javaVersion: string, isCommunity: boolean) { return `graalvm${isCommunity ? '-community' : ''}-jdk-${javaVersion}_${ c.JDK_PLATFORM }-${c.JDK_ARCH}_bin` } async function downloadGraalVMJDK( downloadUrl: string, javaVersion: string ): Promise { try { return await downloadTool(downloadUrl) } catch (error) { if (error instanceof Error && error.message.includes('404')) { // Not Found throw new Error( `Failed to download ${basename( downloadUrl )}. Are you sure java-version: '${javaVersion}' is correct?` ) } throw new Error( `Failed to download ${basename(downloadUrl)} (error: ${error}).` ) } } // Support for GraalVM dev builds export async function setUpGraalVMJDKDevBuild(): Promise { const latestDevBuild = await getLatestRelease(GRAALVM_REPO_DEV_BUILDS) const resolvedJavaVersion = findHighestJavaVersion( latestDevBuild, c.VERSION_DEV ) const downloadUrl = findDownloadUrl(latestDevBuild, resolvedJavaVersion) return downloadAndExtractJDK(downloadUrl) } export function findHighestJavaVersion( release: c.LatestReleaseResponse['data'], version: string ): string { const graalVMIdentifierPattern = determineGraalVMLegacyIdentifier( false, version, '(\\d+)' ) const expectedFileNameRegExp = new RegExp( `^${graalVMIdentifierPattern}${c.GRAALVM_FILE_EXTENSION.replace( /\./g, '\\.' )}$` ) let highestJavaVersion = 0 for (const asset of release.assets) { const matches = asset.name.match(expectedFileNameRegExp) if (matches) { const javaVersion = +matches[1] if (javaVersion > highestJavaVersion) { highestJavaVersion = javaVersion } } } if (highestJavaVersion > 0) { return String(highestJavaVersion) } else { throw new Error( 'Could not find highest Java version. Please file an issue at: https://github.com/graalvm/setup-graalvm/issues.' ) } } // Support for GraalVM 22.X releases and earlier export async function setUpGraalVMLatest_22_X( gdsToken: string, javaVersion: string ): Promise { const lockedVersion = javaVersion === '19' ? '22.3.1' : '22.3.3' if (gdsToken.length > 0) { return setUpGraalVMRelease(gdsToken, lockedVersion, javaVersion) } const latestRelease = await getTaggedRelease( c.GRAALVM_RELEASES_REPO, GRAALVM_TAG_PREFIX + lockedVersion ) const version = findGraalVMVersion(latestRelease) return setUpGraalVMRelease(gdsToken, version, javaVersion) } export function findGraalVMVersion(release: c.LatestReleaseResponse['data']) { const tag_name = release.tag_name if (!tag_name.startsWith(GRAALVM_TAG_PREFIX)) { throw new Error(`Could not find latest GraalVM release: ${tag_name}`) } return tag_name.substring(GRAALVM_TAG_PREFIX.length, tag_name.length) } export async function setUpGraalVMRelease( gdsToken: string, version: string, javaVersion: string ): Promise { const isEE = gdsToken.length > 0 const toolName = determineLegacyToolName(isEE, version, javaVersion) let downloader: () => Promise if (isEE) { downloader = async () => downloadGraalVMEELegacy(gdsToken, version, javaVersion) } else { downloader = async () => downloadGraalVMCELegacy(version, javaVersion) } return downloadExtractAndCacheJDK(downloader, toolName, version) } function findDownloadUrl( release: c.LatestReleaseResponse['data'], javaVersion: string ): string { const graalVMIdentifier = determineGraalVMLegacyIdentifier( false, c.VERSION_DEV, javaVersion ) const expectedFileName = `${graalVMIdentifier}${c.GRAALVM_FILE_EXTENSION}` for (const asset of release.assets) { if (asset.name === expectedFileName) { return asset.browser_download_url } } throw new Error( `Could not find GraalVM dev build for Java ${javaVersion}. It may no longer be available, so please consider upgrading the Java version. ${c.ERROR_HINT}` ) } function determineGraalVMLegacyIdentifier( isEE: boolean, version: string, javaVersion: string ): string { return `${determineLegacyToolName(isEE, version, javaVersion)}-${ c.GRAALVM_ARCH }-${version}` } function determineLegacyToolName( isEE: boolean, version: string, javaVersion: string ): string { const infix = isEE ? 'ee' : version === c.VERSION_DEV ? 'community' : 'ce' return `graalvm-${infix}-java${javaVersion}-${c.GRAALVM_PLATFORM}` } async function downloadGraalVMCELegacy( version: string, javaVersion: string ): Promise { const graalVMIdentifier = determineGraalVMLegacyIdentifier( false, version, javaVersion ) const downloadUrl = `${GRAALVM_CE_DL_BASE}/${GRAALVM_TAG_PREFIX}${version}/${graalVMIdentifier}${c.GRAALVM_FILE_EXTENSION}` try { return await downloadTool(downloadUrl) } catch (error) { if (error instanceof Error && error.message.includes('404')) { // Not Found throw new Error( `Failed to download ${graalVMIdentifier}. Are you sure version: '${version}' and java-version: '${javaVersion}' are correct?` ) } throw new Error( `Failed to download ${graalVMIdentifier} (error: ${error}).` ) } }