mirror of
https://github.com/graalvm/setup-graalvm.git
synced 2025-02-23 20:42:25 +08:00
Add infrastructure for setting up GraalVM.
This commit is contained in:
parent
db50d45bd5
commit
a686e47055
19
src/constants.ts
Normal file
19
src/constants.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import * as otypes from '@octokit/types'
|
||||||
|
import {homedir} from 'os'
|
||||||
|
import {join} from 'path'
|
||||||
|
|
||||||
|
export const IS_MACOS = process.platform === 'darwin'
|
||||||
|
export const IS_WINDOWS = process.platform === 'win32'
|
||||||
|
|
||||||
|
export const VERSION_LATEST = 'latest'
|
||||||
|
export const VERSION_NIGHTLY = 'nightly'
|
||||||
|
export const VERSION_TRUNK = 'trunk'
|
||||||
|
|
||||||
|
export const GRAALVM_BASE = join(homedir(), '.graalvm')
|
||||||
|
export const GRAALVM_FILE_EXTENSION = IS_WINDOWS ? '.zip' : '.tar.gz'
|
||||||
|
export const GRAALVM_GH_USER = 'graalvm'
|
||||||
|
export const GRAALVM_PLATFORM = IS_WINDOWS ? 'windows' : process.platform
|
||||||
|
export const JDK_HOME_SUFFIX = IS_MACOS ? '/Contents/Home' : ''
|
||||||
|
|
||||||
|
export type LatestReleaseResponse =
|
||||||
|
otypes.Endpoints['GET /repos/{owner}/{repo}/releases/latest']['response']
|
103
src/graalvm-trunk.ts
Normal file
103
src/graalvm-trunk.ts
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import * as c from './constants'
|
||||||
|
import * as core from '@actions/core'
|
||||||
|
import * as tc from '@actions/tool-cache'
|
||||||
|
import {SpawnSyncOptionsWithStringEncoding, spawnSync} from 'child_process'
|
||||||
|
import {mkdirP, mv} from '@actions/io'
|
||||||
|
import {findJavaHomeInSubfolder} from './utils'
|
||||||
|
import {join} from 'path'
|
||||||
|
|
||||||
|
const GRAALVM_TRUNK_DL =
|
||||||
|
'https://github.com/oracle/graal/archive/refs/heads/master.zip'
|
||||||
|
const GRAALVM_MX_DL =
|
||||||
|
'https://github.com/graalvm/mx/archive/refs/heads/master.zip'
|
||||||
|
const DEFAULT_SUITES = '/compiler,/regex,/sdk,/tools,/truffle'
|
||||||
|
const GRAAL_REPO_DIR = join(c.GRAALVM_BASE, 'graal')
|
||||||
|
const VM_DIR = join(GRAAL_REPO_DIR, 'vm')
|
||||||
|
const MX_DIR = join(c.GRAALVM_BASE, 'mx')
|
||||||
|
const MX_EXEC = c.IS_WINDOWS ? 'mx.cmd' : 'mx'
|
||||||
|
const SPAWN_OPTIONS: SpawnSyncOptionsWithStringEncoding = {
|
||||||
|
cwd: VM_DIR,
|
||||||
|
encoding: 'utf8',
|
||||||
|
stdio: 'inherit'
|
||||||
|
}
|
||||||
|
|
||||||
|
const COMPONENTS_TO_SUITE_NAME = new Map<string, string>([
|
||||||
|
['espresso', '/espresso'],
|
||||||
|
['js', '/graal-js'],
|
||||||
|
['llvm-toolchain', '/sulong'],
|
||||||
|
['native-image', '/substratevm'],
|
||||||
|
['nodejs', '/graal-nodejs'],
|
||||||
|
['python', 'graalpython'],
|
||||||
|
['R', 'fastr'],
|
||||||
|
['ruby', 'truffleruby'],
|
||||||
|
['wasm', '/wasm']
|
||||||
|
])
|
||||||
|
|
||||||
|
export async function setUpGraalVMTrunk(
|
||||||
|
javaVersion: string,
|
||||||
|
components: string[]
|
||||||
|
): Promise<string> {
|
||||||
|
const jdkId = `labsjdk-ce-${javaVersion}`
|
||||||
|
|
||||||
|
core.startGroup(`Downloading GraalVM sources, mx, and ${jdkId}...`)
|
||||||
|
|
||||||
|
await tc.extractZip(await tc.downloadTool(GRAALVM_TRUNK_DL), c.GRAALVM_BASE)
|
||||||
|
await mv(join(c.GRAALVM_BASE, 'graal-master'), GRAAL_REPO_DIR)
|
||||||
|
|
||||||
|
await tc.extractZip(await tc.downloadTool(GRAALVM_MX_DL), c.GRAALVM_BASE)
|
||||||
|
await mv(join(c.GRAALVM_BASE, 'mx-master'), MX_DIR)
|
||||||
|
core.addPath(MX_DIR)
|
||||||
|
core.debug(`"${MX_DIR}" added to $PATH`)
|
||||||
|
|
||||||
|
const labsJDKDir = join(c.GRAALVM_BASE, 'labsjdk')
|
||||||
|
await mkdirP(labsJDKDir)
|
||||||
|
spawnSync(
|
||||||
|
MX_EXEC,
|
||||||
|
['--java-home=', 'fetch-jdk', '--jdk-id', jdkId, '--to', labsJDKDir],
|
||||||
|
SPAWN_OPTIONS
|
||||||
|
)
|
||||||
|
const labsJDKHome = findJavaHomeInSubfolder(labsJDKDir)
|
||||||
|
core.exportVariable('JAVA_HOME', labsJDKHome)
|
||||||
|
core.debug(`$JAVA_HOME set to "${labsJDKHome}"`)
|
||||||
|
|
||||||
|
core.endGroup()
|
||||||
|
|
||||||
|
const dynamicImports = toSuiteNames(components).join(',')
|
||||||
|
const mxArgs = [
|
||||||
|
'--no-download-progress', // avoid cluttering the build log
|
||||||
|
'--disable-installables=true', // installables not needed
|
||||||
|
'--force-bash-launchers=true', // disable native launchers
|
||||||
|
'--exclude-components=LibGraal', // avoid building libgraal to save time
|
||||||
|
'--dynamicimports',
|
||||||
|
dynamicImports
|
||||||
|
]
|
||||||
|
if (core.isDebug()) {
|
||||||
|
spawnSync(MX_EXEC, mxArgs.concat('graalvm-show'), SPAWN_OPTIONS)
|
||||||
|
}
|
||||||
|
const graalvmHome = spawnSync(MX_EXEC, mxArgs.concat(['graalvm-home']), {
|
||||||
|
...SPAWN_OPTIONS,
|
||||||
|
stdio: 'pipe'
|
||||||
|
})
|
||||||
|
core.startGroup('Building GraalVM CE from source...')
|
||||||
|
spawnSync(MX_EXEC, mxArgs.concat(['build']), SPAWN_OPTIONS)
|
||||||
|
core.endGroup()
|
||||||
|
const graalvmHomePath = graalvmHome.stdout.trim()
|
||||||
|
if (core.isDebug()) {
|
||||||
|
const cmd = c.IS_WINDOWS ? 'dir' : 'ls'
|
||||||
|
spawnSync(cmd, [graalvmHomePath], {stdio: 'inherit'})
|
||||||
|
}
|
||||||
|
return graalvmHomePath
|
||||||
|
}
|
||||||
|
|
||||||
|
function toSuiteNames(components: string[]): string[] {
|
||||||
|
const names = [DEFAULT_SUITES]
|
||||||
|
for (const component of components) {
|
||||||
|
const suiteName = COMPONENTS_TO_SUITE_NAME.get(component)
|
||||||
|
if (suiteName) {
|
||||||
|
names.push(suiteName)
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unsupported component: ${component}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return names
|
||||||
|
}
|
51
src/graalvm.ts
Normal file
51
src/graalvm.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import * as c from './constants'
|
||||||
|
import {downloadAndExtractJDK, getLatestRelease} from './utils'
|
||||||
|
|
||||||
|
const GRAALVM_CE_DL_BASE =
|
||||||
|
'https://github.com/graalvm/graalvm-ce-builds/releases/download'
|
||||||
|
const GRAALVM_REPO_NIGHTLY = 'graalvm-ce-dev-builds'
|
||||||
|
const GRAALVM_REPO_RELEASES = 'graalvm-ce-builds'
|
||||||
|
const GRAALVM_TAG_PREFIX = 'vm-'
|
||||||
|
|
||||||
|
export async function setUpGraalVMLatest(javaVersion: string): Promise<string> {
|
||||||
|
const latestRelease = await getLatestRelease(GRAALVM_REPO_RELEASES)
|
||||||
|
const tag_name = latestRelease.tag_name
|
||||||
|
if (tag_name.startsWith(GRAALVM_TAG_PREFIX)) {
|
||||||
|
const latestVersion = tag_name.substring(
|
||||||
|
GRAALVM_TAG_PREFIX.length,
|
||||||
|
tag_name.length
|
||||||
|
)
|
||||||
|
return setUpGraalVMRelease(latestVersion, javaVersion)
|
||||||
|
}
|
||||||
|
throw new Error(`Could not find latest GraalVM release: ${tag_name}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setUpGraalVMNightly(
|
||||||
|
javaVersion: string
|
||||||
|
): Promise<string> {
|
||||||
|
const latestNightly = await getLatestRelease(GRAALVM_REPO_NIGHTLY)
|
||||||
|
const graalVMIdentifier = determineGraalVMIdentifier('dev', javaVersion)
|
||||||
|
const expectedFileName = `${graalVMIdentifier}${c.GRAALVM_FILE_EXTENSION}`
|
||||||
|
for (const asset of latestNightly.assets) {
|
||||||
|
if (asset.name === expectedFileName) {
|
||||||
|
return downloadAndExtractJDK(asset.browser_download_url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error('Could not find GraalVM nightly build')
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setUpGraalVMRelease(
|
||||||
|
version: string,
|
||||||
|
javaVersion: string
|
||||||
|
): Promise<string> {
|
||||||
|
const graalVMIdentifier = determineGraalVMIdentifier(version, javaVersion)
|
||||||
|
const downloadUrl = `${GRAALVM_CE_DL_BASE}/${GRAALVM_TAG_PREFIX}${version}/${graalVMIdentifier}${c.GRAALVM_FILE_EXTENSION}`
|
||||||
|
return downloadAndExtractJDK(downloadUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
function determineGraalVMIdentifier(
|
||||||
|
version: string,
|
||||||
|
javaVersion: string
|
||||||
|
): string {
|
||||||
|
return `graalvm-ce-java${javaVersion}-${c.GRAALVM_PLATFORM}-amd64-${version}`
|
||||||
|
}
|
39
src/main.ts
39
src/main.ts
@ -1,9 +1,48 @@
|
|||||||
|
import * as c from './constants'
|
||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
|
import * as graalvm from './graalvm'
|
||||||
|
import {join} from 'path'
|
||||||
|
import {mkdirP} from '@actions/io'
|
||||||
|
import {setUpGraalVMTrunk} from './graalvm-trunk'
|
||||||
|
|
||||||
async function run(): Promise<void> {
|
async function run(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
|
const graalvmVersion: string = core.getInput('version', {required: true})
|
||||||
|
const javaVersion: string = core.getInput('java-version', {required: true})
|
||||||
|
const componentsString: string = core.getInput('components')
|
||||||
|
const components: string[] =
|
||||||
|
componentsString.length > 0 ? componentsString.split(',') : []
|
||||||
|
const setJavaHome = core.getInput('set-java-home') === 'true'
|
||||||
|
|
||||||
|
await mkdirP(c.GRAALVM_BASE)
|
||||||
|
|
||||||
|
// Download or build GraalVM
|
||||||
let graalVMHome
|
let graalVMHome
|
||||||
|
switch (graalvmVersion) {
|
||||||
|
case c.VERSION_LATEST:
|
||||||
|
graalVMHome = await graalvm.setUpGraalVMLatest(javaVersion)
|
||||||
|
break
|
||||||
|
case c.VERSION_NIGHTLY:
|
||||||
|
graalVMHome = await graalvm.setUpGraalVMNightly(javaVersion)
|
||||||
|
break
|
||||||
|
case c.VERSION_TRUNK:
|
||||||
|
graalVMHome = await setUpGraalVMTrunk(javaVersion, components)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
graalVMHome = await graalvm.setUpGraalVMRelease(
|
||||||
|
graalvmVersion,
|
||||||
|
javaVersion
|
||||||
|
)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activate GraalVM
|
||||||
|
core.debug(`Activating GraalVM located at '${graalVMHome}'...`)
|
||||||
core.exportVariable('GRAALVM_HOME', graalVMHome)
|
core.exportVariable('GRAALVM_HOME', graalVMHome)
|
||||||
|
core.addPath(join(graalVMHome, 'bin'))
|
||||||
|
if (setJavaHome) {
|
||||||
|
core.exportVariable('JAVA_HOME', graalVMHome)
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Error) core.setFailed(error.message)
|
if (error instanceof Error) core.setFailed(error.message)
|
||||||
}
|
}
|
||||||
|
55
src/utils.ts
Normal file
55
src/utils.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import * as c from './constants'
|
||||||
|
import * as core from '@actions/core'
|
||||||
|
import * as httpClient from '@actions/http-client'
|
||||||
|
import * as tc from '@actions/tool-cache'
|
||||||
|
import {Octokit} from '@octokit/core'
|
||||||
|
import {join} from 'path'
|
||||||
|
import {readdirSync} from 'fs'
|
||||||
|
|
||||||
|
// Set up Octokit in the same way as @actions/github (see https://git.io/Jy9YP)
|
||||||
|
const baseUrl = process.env['GITHUB_API_URL'] || 'https://api.github.com'
|
||||||
|
const GitHub = Octokit.defaults({
|
||||||
|
baseUrl,
|
||||||
|
request: {
|
||||||
|
agent: new httpClient.HttpClient().getAgent(baseUrl)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export async function getLatestRelease(
|
||||||
|
repo: string
|
||||||
|
): Promise<c.LatestReleaseResponse['data']> {
|
||||||
|
const githubToken = core.getInput('github-token')
|
||||||
|
const options = githubToken.length > 0 ? {auth: githubToken} : {}
|
||||||
|
const octokit = new GitHub(options)
|
||||||
|
return (
|
||||||
|
await octokit.request('GET /repos/{owner}/{repo}/releases/latest', {
|
||||||
|
owner: c.GRAALVM_GH_USER,
|
||||||
|
repo
|
||||||
|
})
|
||||||
|
).data
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function downloadAndExtractJDK(
|
||||||
|
downloadUrl: string
|
||||||
|
): Promise<string> {
|
||||||
|
const downloadPath = await tc.downloadTool(downloadUrl)
|
||||||
|
if (downloadUrl.endsWith('.tar.gz')) {
|
||||||
|
await tc.extractTar(downloadPath, c.GRAALVM_BASE)
|
||||||
|
} else if (downloadUrl.endsWith('.zip')) {
|
||||||
|
await tc.extractZip(downloadPath, c.GRAALVM_BASE)
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unexpected filetype downloaded: ${downloadUrl}`)
|
||||||
|
}
|
||||||
|
return findJavaHomeInSubfolder(c.GRAALVM_BASE)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function findJavaHomeInSubfolder(searchPath: string): string {
|
||||||
|
const baseContents = readdirSync(searchPath)
|
||||||
|
if (baseContents.length === 1) {
|
||||||
|
return join(searchPath, baseContents[0], c.JDK_HOME_SUFFIX)
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
`Unexpected amount of directory items found: ${baseContents.length}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user