2019-07-30 14:01:45 -04:00
let tempDirectory = process . env [ 'RUNNER_TEMP' ] || '' ;
2019-07-10 23:11:48 -04:00
import * as core from '@actions/core' ;
import * as io from '@actions/io' ;
import * as exec from '@actions/exec' ;
import * as tc from '@actions/tool-cache' ;
import * as fs from 'fs' ;
import * as path from 'path' ;
2019-07-18 16:00:58 -04:00
import * as semver from 'semver' ;
2019-07-15 14:59:23 -04:00
import * as httpm from 'typed-rest-client/HttpClient' ;
2019-07-10 23:11:48 -04:00
const IS_WINDOWS = process . platform === 'win32' ;
if ( ! tempDirectory ) {
let baseLocation ;
if ( IS_WINDOWS ) {
// On windows use the USERPROFILE env variable
baseLocation = process . env [ 'USERPROFILE' ] || 'C:\\' ;
} else {
if ( process . platform === 'darwin' ) {
baseLocation = '/Users' ;
} else {
baseLocation = '/home' ;
}
}
tempDirectory = path . join ( baseLocation , 'actions' , 'temp' ) ;
}
export async function getJava (
version : string ,
arch : string ,
2019-11-03 00:39:35 -04:00
jdkFile : string ,
javaPackage : string
2019-07-10 23:11:48 -04:00
) : Promise < void > {
2019-11-03 00:39:35 -04:00
let toolPath = tc . find ( javaPackage , version ) ;
2019-07-10 23:11:48 -04:00
if ( toolPath ) {
core . debug ( ` Tool found in cache ${ toolPath } ` ) ;
} else {
2019-07-15 14:59:23 -04:00
let compressedFileExtension = '' ;
2019-07-15 11:26:32 -04:00
if ( ! jdkFile ) {
2019-07-15 14:59:23 -04:00
core . debug ( 'Downloading Jdk from Azul' ) ;
2019-07-18 16:00:58 -04:00
let http : httpm.HttpClient = new httpm . HttpClient ( 'setup-java' ) ;
2019-11-25 10:12:17 -05:00
let contents = await (
await http . get ( 'https://static.azul.com/zulu/bin/' )
) . readBody ( ) ;
2019-07-18 16:00:58 -04:00
let refs = contents . match ( /<a href.*\">/gi ) || [ ] ;
2019-11-03 00:39:35 -04:00
const downloadInfo = getDownloadInfo ( refs , version , javaPackage ) ;
2019-07-18 16:00:58 -04:00
jdkFile = await tc . downloadTool ( downloadInfo . url ) ;
version = downloadInfo . version ;
2019-07-15 14:59:23 -04:00
compressedFileExtension = IS_WINDOWS ? '.zip' : '.tar.gz' ;
} else {
core . debug ( 'Retrieving Jdk from local path' ) ;
2019-07-15 11:26:32 -04:00
}
2019-07-15 14:59:23 -04:00
compressedFileExtension = compressedFileExtension || getFileEnding ( jdkFile ) ;
2019-07-10 23:11:48 -04:00
let tempDir : string = path . join (
tempDirectory ,
'temp_' + Math . floor ( Math . random ( ) * 2000000000 )
) ;
const jdkDir = await unzipJavaDownload (
jdkFile ,
compressedFileExtension ,
tempDir
) ;
core . debug ( ` jdk extracted to ${ jdkDir } ` ) ;
2019-07-15 14:59:23 -04:00
toolPath = await tc . cacheDir (
jdkDir ,
2019-11-03 00:39:35 -04:00
javaPackage ,
2019-07-18 16:00:58 -04:00
getCacheVersionString ( version ) ,
2019-07-15 14:59:23 -04:00
arch
) ;
2019-07-10 23:11:48 -04:00
}
let extendedJavaHome = 'JAVA_HOME_' + version + '_' + arch ;
core . exportVariable ( 'JAVA_HOME' , toolPath ) ;
core . exportVariable ( extendedJavaHome , toolPath ) ;
core . addPath ( path . join ( toolPath , 'bin' ) ) ;
}
2019-07-18 16:00:58 -04:00
function getCacheVersionString ( version : string ) {
2019-07-15 14:59:23 -04:00
const versionArray = version . split ( '.' ) ;
const major = versionArray [ 0 ] ;
const minor = versionArray . length > 1 ? versionArray [ 1 ] : '0' ;
const patch = versionArray . length > 2 ? versionArray [ 2 ] : '0' ;
return ` ${ major } . ${ minor } . ${ patch } ` ;
}
2019-07-10 23:11:48 -04:00
function getFileEnding ( file : string ) : string {
let fileEnding = '' ;
if ( file . endsWith ( '.tar' ) ) {
fileEnding = '.tar' ;
} else if ( file . endsWith ( '.tar.gz' ) ) {
fileEnding = '.tar.gz' ;
} else if ( file . endsWith ( '.zip' ) ) {
fileEnding = '.zip' ;
} else if ( file . endsWith ( '.7z' ) ) {
fileEnding = '.7z' ;
} else {
throw new Error ( ` ${ file } has an unsupported file extension ` ) ;
}
return fileEnding ;
}
async function extractFiles (
file : string ,
fileEnding : string ,
destinationFolder : string
) : Promise < void > {
const stats = fs . statSync ( file ) ;
if ( ! stats ) {
throw new Error ( ` Failed to extract ${ file } - it doesn't exist ` ) ;
} else if ( stats . isDirectory ( ) ) {
throw new Error ( ` Failed to extract ${ file } - it is a directory ` ) ;
}
if ( '.tar' === fileEnding || '.tar.gz' === fileEnding ) {
await tc . extractTar ( file , destinationFolder ) ;
} else if ( '.zip' === fileEnding ) {
await tc . extractZip ( file , destinationFolder ) ;
} else {
// fall through and use sevenZip
await tc . extract7z ( file , destinationFolder ) ;
}
}
// This method recursively finds all .pack files under fsPath and unpacks them with the unpack200 tool
async function unpackJars ( fsPath : string , javaBinPath : string ) {
if ( fs . existsSync ( fsPath ) ) {
if ( fs . lstatSync ( fsPath ) . isDirectory ( ) ) {
for ( const file in fs . readdirSync ( fsPath ) ) {
const curPath = path . join ( fsPath , file ) ;
await unpackJars ( curPath , javaBinPath ) ;
}
} else if ( path . extname ( fsPath ) . toLowerCase ( ) === '.pack' ) {
// Unpack the pack file synchonously
const p = path . parse ( fsPath ) ;
const toolName = IS_WINDOWS ? 'unpack200.exe' : 'unpack200' ;
const args = IS_WINDOWS ? '-r -v -l ""' : '' ;
const name = path . join ( p . dir , p . name ) ;
await exec . exec ( ` " ${ path . join ( javaBinPath , toolName ) } " ` , [
` ${ args } " ${ name } .pack" " ${ name } .jar" `
] ) ;
}
}
}
async function unzipJavaDownload (
repoRoot : string ,
fileEnding : string ,
2019-07-15 14:59:23 -04:00
destinationFolder : string ,
extension? : string
2019-07-10 23:11:48 -04:00
) : Promise < string > {
// Create the destination folder if it doesn't exist
await io . mkdirP ( destinationFolder ) ;
const jdkFile = path . normalize ( repoRoot ) ;
const stats = fs . statSync ( jdkFile ) ;
if ( stats . isFile ( ) ) {
await extractFiles ( jdkFile , fileEnding , destinationFolder ) ;
const jdkDirectory = path . join (
destinationFolder ,
fs . readdirSync ( destinationFolder ) [ 0 ]
) ;
await unpackJars ( jdkDirectory , path . join ( jdkDirectory , 'bin' ) ) ;
return jdkDirectory ;
} else {
throw new Error ( ` Jdk argument ${ jdkFile } is not a file ` ) ;
}
}
2019-07-15 14:59:23 -04:00
2019-07-18 16:00:58 -04:00
function getDownloadInfo (
refs : string [ ] ,
2019-11-03 00:39:35 -04:00
version : string ,
javaPackage : string
2019-07-18 16:00:58 -04:00
) : { version : string ; url : string } {
version = normalizeVersion ( version ) ;
let extension = '' ;
2019-07-15 14:59:23 -04:00
if ( IS_WINDOWS ) {
2019-07-18 16:00:58 -04:00
extension = ` -win_x64.zip ` ;
2019-07-15 14:59:23 -04:00
} else {
if ( process . platform === 'darwin' ) {
2019-07-18 16:00:58 -04:00
extension = ` -macosx_x64.tar.gz ` ;
2019-07-15 14:59:23 -04:00
} else {
2019-07-18 16:00:58 -04:00
extension = ` -linux_x64.tar.gz ` ;
2019-07-15 14:59:23 -04:00
}
}
2019-07-18 16:00:58 -04:00
2019-11-03 00:39:35 -04:00
let pkgRegexp = new RegExp ( '' ) ;
let pkgTypeLength = 0 ;
if ( javaPackage === 'jdk' ) {
pkgRegexp = /jdk.*-/gi ;
pkgTypeLength = 'jdk' . length ;
} else if ( javaPackage == 'jre' ) {
pkgRegexp = /jre.*-/gi ;
pkgTypeLength = 'jre' . length ;
} else if ( javaPackage == 'jdk+fx' ) {
pkgRegexp = /fx-jdk.*-/gi ;
pkgTypeLength = 'fx-jdk' . length ;
} else {
throw new Error (
` package argument ${ javaPackage } is not in [jdk | jre | jdk+fx] `
) ;
}
2019-07-18 16:00:58 -04:00
// Maps version to url
let versionMap = new Map ( ) ;
// Filter by platform
refs . forEach ( ref = > {
2019-11-03 00:39:35 -04:00
if ( ! ref . endsWith ( extension + '">' ) ) {
2019-07-18 16:00:58 -04:00
return ;
}
// If we haven't returned, means we're looking at the correct platform
2019-11-03 00:39:35 -04:00
let versions = ref . match ( pkgRegexp ) || [ ] ;
2019-07-18 16:00:58 -04:00
if ( versions . length > 1 ) {
throw new Error (
` Invalid ref received from https://static.azul.com/zulu/bin/: ${ ref } `
) ;
}
if ( versions . length == 0 ) {
return ;
}
2019-11-03 00:39:35 -04:00
const refVersion = versions [ 0 ] . slice ( pkgTypeLength , versions [ 0 ] . length - 1 ) ;
2019-07-18 16:00:58 -04:00
if ( semver . satisfies ( refVersion , version ) ) {
versionMap . set (
refVersion ,
'https://static.azul.com/zulu/bin/' +
ref . slice ( '<a href="' . length , ref . length - '">' . length )
) ;
2019-07-15 14:59:23 -04:00
}
} ) ;
2019-07-18 16:00:58 -04:00
// Choose the most recent satisfying version
let curVersion = '0.0.0' ;
let curUrl = '' ;
for ( const entry of versionMap . entries ( ) ) {
const entryVersion = entry [ 0 ] ;
const entryUrl = entry [ 1 ] ;
if ( semver . gt ( entryVersion , curVersion ) ) {
curUrl = entryUrl ;
curVersion = entryVersion ;
}
}
if ( curUrl == '' ) {
2019-07-15 14:59:23 -04:00
throw new Error (
2019-11-03 00:39:35 -04:00
` No valid download found for version ${ version } and package ${ javaPackage } . Check https://static.azul.com/zulu/bin/ for a list of valid versions or download your own jdk file and add the jdkFile argument `
2019-07-15 14:59:23 -04:00
) ;
}
2019-07-18 16:00:58 -04:00
return { version : curVersion , url : curUrl } ;
}
function normalizeVersion ( version : string ) : string {
if ( version . slice ( 0 , 2 ) === '1.' ) {
// Trim leading 1. for versions like 1.8
version = version . slice ( 2 ) ;
if ( ! version ) {
throw new Error ( '1. is not a valid version' ) ;
}
}
// Add trailing .x if it is missing
if ( version . split ( '.' ) . length != 3 ) {
if ( version [ version . length - 1 ] != 'x' ) {
version = version + '.x' ;
}
}
return version ;
2019-07-15 14:59:23 -04:00
}