From 7d219e5bd53c9902a0e55641dbb71c62e2c0c9aa Mon Sep 17 00:00:00 2001 From: Gil Tene Date: Sat, 2 Nov 2019 21:39:35 -0700 Subject: [PATCH 1/2] Add java-package parameter to action, support jre, jdk, and jdk+fx (#1) * Add java-package parameter to action, support jre, jdk, and jdk+fx (#1) * Update tests to use 'jdk', 'jre', and 'jdk+fx' javaPackage parameters * Match extension only at end of line * Update README.md * Update workflow to use 'node-version' instead of deprecated 'version' --- .github/workflows/workflow.yml | 2 +- README.md | 11 +++---- __tests__/installer.test.ts | 55 +++++++++++++++++++++++++--------- action.yml | 8 +++-- lib/installer.js | 35 ++++++++++++++++------ lib/setup-java.js | 3 +- src/installer.ts | 37 +++++++++++++++++------ src/setup-java.ts | 3 +- 8 files changed, 112 insertions(+), 42 deletions(-) diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 22e0e06..4558c6f 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -14,7 +14,7 @@ jobs: - name: Set Node.js 10.x uses: actions/setup-node@master with: - version: 10.x + node-version: 10.x - name: npm install run: npm install diff --git a/README.md b/README.md index 38d33c1..bb8d071 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This action sets up a java environment for use in actions by: -- optionally downloading and caching a version of java by version and adding to PATH. Downloads from [Azul's Zulu distribution](http://static.azul.com/zulu/bin/). +- optionally downloading and caching a requested version of java by version and adding to PATH. Default downloads are populated from the [Zulu Community distribution of OpenJDK](http://static.azul.com/zulu/bin/) - registering problem matchers for error output # Usage @@ -19,7 +19,8 @@ steps: - uses: actions/checkout@latest - uses: actions/setup-java@v1 with: - java-version: '9.0.4' // The JDK version to make available on the path. Takes a whole or semver Jdk version, or 1.x syntax (e.g. 1.8 => Jdk 8.x) + java-version: '11.0.4' // The Java version to make available on the path. Takes a whole or semver Java version, or 1.x syntax (e.g. 1.8 => Jdk 8.x) + java-package: jdk // (jre, jdk, or jdk+fx) - defaults to jdk architecture: x64 // (x64 or x86) - defaults to x64 - run: java -cp java HelloWorldApp ``` @@ -32,7 +33,7 @@ steps: with: java-version: '4.0.0' architecture: x64 - jdkFile: # Optional - jdkFile to install java from. Useful for versions not supported by Azul + jdkFile: # Optional - jdkFile to install java from. Useful for versions not found on Zulu Community CDN - run: java -cp java HelloWorldApp ``` @@ -43,7 +44,8 @@ jobs: runs-on: ubuntu-16.04 strategy: matrix: - java: [ '1.6', '9.0.x', '12.0.2' ] + # test against latest update of each major Java version, as well as specific updates of LTS versions: + java: [ 1.6, 6.0.83, 7, 7.0.181, 8, 8.0.192, 9.0,x, 10, 11.0.x, 11.0.3, 12, 13 ] name: Java ${{ matrix.java }} sample steps: - uses: actions/checkout@master @@ -51,7 +53,6 @@ jobs: uses: actions/setup-java@v1 with: java-version: ${{ matrix.java }} - architecture: x64 - run: java -cp java HelloWorldApp ``` diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 6ac7ff8..ff2d61b 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -52,8 +52,8 @@ describe('installer tests', () => { }, 100000); it('Installs version of Java from jdkFile if no matching version is installed', async () => { - await installer.getJava('12', 'x64', javaFilePath); - const JavaDir = path.join(toolDir, 'Java', '12.0.0', 'x64'); + await installer.getJava('12', 'x64', javaFilePath, 'jdk'); + const JavaDir = path.join(toolDir, 'jdk', '12.0.0', 'x64'); expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true); expect(fs.existsSync(path.join(JavaDir, 'bin'))).toBe(true); @@ -62,7 +62,7 @@ describe('installer tests', () => { it('Throws if invalid directory to jdk', async () => { let thrown = false; try { - await installer.getJava('1000', 'x64', 'bad path'); + await installer.getJava('1000', 'x64', 'bad path', 'jdk'); } catch { thrown = true; } @@ -70,33 +70,59 @@ describe('installer tests', () => { }); it('Downloads java if no file given', async () => { - await installer.getJava('8.0.102', 'x64', ''); - const JavaDir = path.join(toolDir, 'Java', '8.0.102', 'x64'); + await installer.getJava('8.0.102', 'x64', '', 'jdk'); + const JavaDir = path.join(toolDir, 'jdk', '8.0.102', 'x64'); expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true); expect(fs.existsSync(path.join(JavaDir, 'bin'))).toBe(true); }, 100000); it('Downloads java with 1.x syntax', async () => { - await installer.getJava('1.10', 'x64', ''); - const JavaDir = path.join(toolDir, 'Java', '10.0.2', 'x64'); + await installer.getJava('1.10', 'x64', '', 'jdk'); + const JavaDir = path.join(toolDir, 'jdk', '10.0.2', 'x64'); expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true); expect(fs.existsSync(path.join(JavaDir, 'bin'))).toBe(true); }, 100000); it('Downloads java with normal semver syntax', async () => { - await installer.getJava('9.0.x', 'x64', ''); - const JavaDir = path.join(toolDir, 'Java', '9.0.7', 'x64'); + await installer.getJava('9.0.x', 'x64', '', 'jdk'); + const JavaDir = path.join(toolDir, 'jdk', '9.0.7', 'x64'); expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true); expect(fs.existsSync(path.join(JavaDir, 'bin'))).toBe(true); }, 100000); + it('Downloads java if package is jre', async () => { + await installer.getJava('8.0.222', 'x64', '', 'jre'); + const JavaDir = path.join(toolDir, 'jre', '8.0.222', 'x64'); + + expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true); + expect(fs.existsSync(path.join(JavaDir, 'bin'))).toBe(true); + }, 100000); + + it('Downloads java if package is jdk+fx', async () => { + await installer.getJava('8.0.222', 'x64', '', 'jdk+fx'); + const JavaDir = path.join(toolDir, 'jdk+fx', '8.0.222', 'x64'); + + expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true); + expect(fs.existsSync(path.join(JavaDir, 'bin'))).toBe(true); + }, 100000); + + it('Throws if invalid java package is specified', async () => { + let thrown = false; + try { + await installer.getJava('8.0.222', 'x64', '', 'bad jdk'); + } catch { + thrown = true; + } + expect(thrown).toBe(true); + }); + it('Throws if invalid directory to jdk', async () => { let thrown = false; try { - await installer.getJava('1000', 'x64', 'bad path'); + await installer.getJava('1000', 'x64', 'bad path', 'jdk'); } catch { thrown = true; } @@ -104,25 +130,26 @@ describe('installer tests', () => { }); it('Uses version of Java installed in cache', async () => { - const JavaDir: string = path.join(toolDir, 'Java', '250.0.0', 'x64'); + const JavaDir: string = path.join(toolDir, 'jdk', '250.0.0', 'x64'); await io.mkdirP(JavaDir); fs.writeFileSync(`${JavaDir}.complete`, 'hello'); // This will throw if it doesn't find it in the cache (because no such version exists) await installer.getJava( '250', 'x64', - 'path shouldnt matter, found in cache' + 'path shouldnt matter, found in cache', + 'jdk' ); return; }); it('Doesnt use version of Java that was only partially installed in cache', async () => { - const JavaDir: string = path.join(toolDir, 'Java', '251.0.0', 'x64'); + const JavaDir: string = path.join(toolDir, 'jdk', '251.0.0', 'x64'); await io.mkdirP(JavaDir); let thrown = false; try { // This will throw if it doesn't find it in the cache (because no such version exists) - await installer.getJava('251', 'x64', 'bad path'); + await installer.getJava('251', 'x64', 'bad path', 'jdk'); } catch { thrown = true; } diff --git a/action.yml b/action.yml index 6e35406..b168e93 100644 --- a/action.yml +++ b/action.yml @@ -3,10 +3,14 @@ description: 'Setup your runner with Java' author: 'GitHub' inputs: java-version: - description: 'The JDK version to make available on the path. Takes a whole or semver Jdk version, or 1.x syntax (e.g. 1.8 => Jdk 8.x)' + description: 'The Java version to make available on the path. Takes a whole or semver Java version, or 1.x syntax (e.g. 1.8 => Jdk 8.x)' required: true + java-package: + description: 'The package type (jre, jdk, jdk+fx)' + required: true + default: 'jdk' architecture: - description: 'The architecture (x86, x64) of the JDK.' + description: 'The architecture (x86, x64) of the package.' required: true default: 'x64' jdkFile: diff --git a/lib/installer.js b/lib/installer.js index 5f068a1..6bb581d 100644 --- a/lib/installer.js +++ b/lib/installer.js @@ -41,9 +41,9 @@ if (!tempDirectory) { } tempDirectory = path.join(baseLocation, 'actions', 'temp'); } -function getJava(version, arch, jdkFile) { +function getJava(version, arch, jdkFile, javaPackage) { return __awaiter(this, void 0, void 0, function* () { - let toolPath = tc.find('Java', version); + let toolPath = tc.find(javaPackage, version); if (toolPath) { core.debug(`Tool found in cache ${toolPath}`); } @@ -54,7 +54,7 @@ function getJava(version, arch, jdkFile) { let http = new httpm.HttpClient('setup-java'); let contents = yield (yield http.get('https://static.azul.com/zulu/bin/')).readBody(); let refs = contents.match(//gi) || []; - const downloadInfo = getDownloadInfo(refs, version); + const downloadInfo = getDownloadInfo(refs, version, javaPackage); jdkFile = yield tc.downloadTool(downloadInfo.url); version = downloadInfo.version; compressedFileExtension = IS_WINDOWS ? '.zip' : '.tar.gz'; @@ -66,7 +66,7 @@ function getJava(version, arch, jdkFile) { let tempDir = path.join(tempDirectory, 'temp_' + Math.floor(Math.random() * 2000000000)); const jdkDir = yield unzipJavaDownload(jdkFile, compressedFileExtension, tempDir); core.debug(`jdk extracted to ${jdkDir}`); - toolPath = yield tc.cacheDir(jdkDir, 'Java', getCacheVersionString(version), arch); + toolPath = yield tc.cacheDir(jdkDir, javaPackage, getCacheVersionString(version), arch); } let extendedJavaHome = 'JAVA_HOME_' + version + '_' + arch; core.exportVariable('JAVA_HOME', toolPath); @@ -162,7 +162,7 @@ function unzipJavaDownload(repoRoot, fileEnding, destinationFolder, extension) { } }); } -function getDownloadInfo(refs, version) { +function getDownloadInfo(refs, version, javaPackage) { version = normalizeVersion(version); let extension = ''; if (IS_WINDOWS) { @@ -176,22 +176,39 @@ function getDownloadInfo(refs, version) { extension = `-linux_x64.tar.gz`; } } + 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]`); + } // Maps version to url let versionMap = new Map(); // Filter by platform refs.forEach(ref => { - if (ref.indexOf(extension) < 0) { + if (!ref.endsWith(extension + '">')) { return; } // If we haven't returned, means we're looking at the correct platform - let versions = ref.match(/jdk.*-/gi) || []; + let versions = ref.match(pkgRegexp) || []; if (versions.length > 1) { throw new Error(`Invalid ref received from https://static.azul.com/zulu/bin/: ${ref}`); } if (versions.length == 0) { return; } - const refVersion = versions[0].slice('jdk'.length, versions[0].length - 1); + const refVersion = versions[0].slice(pkgTypeLength, versions[0].length - 1); if (semver.satisfies(refVersion, version)) { versionMap.set(refVersion, 'https://static.azul.com/zulu/bin/' + ref.slice(''.length)); @@ -209,7 +226,7 @@ function getDownloadInfo(refs, version) { } } if (curUrl == '') { - throw new Error(`No valid download found for version ${version}. Check https://static.azul.com/zulu/bin/ for a list of valid versions or download your own jdk file and add the jdkFile argument`); + throw new Error(`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`); } return { version: curVersion, url: curUrl }; } diff --git a/lib/setup-java.js b/lib/setup-java.js index 05e231c..4956423 100644 --- a/lib/setup-java.js +++ b/lib/setup-java.js @@ -26,8 +26,9 @@ function run() { version = core.getInput('java-version', { required: true }); } const arch = core.getInput('architecture', { required: true }); + const javaPackage = core.getInput('java-package', { required: true }); const jdkFile = core.getInput('jdkFile', { required: false }) || ''; - yield installer.getJava(version, arch, jdkFile); + yield installer.getJava(version, arch, jdkFile, javaPackage); const matchersPath = path.join(__dirname, '..', '.github'); console.log(`##[add-matcher]${path.join(matchersPath, 'java.json')}`); } diff --git a/src/installer.ts b/src/installer.ts index 646f552..41a7233 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -29,9 +29,10 @@ if (!tempDirectory) { export async function getJava( version: string, arch: string, - jdkFile: string + jdkFile: string, + javaPackage: string ): Promise { - let toolPath = tc.find('Java', version); + let toolPath = tc.find(javaPackage, version); if (toolPath) { core.debug(`Tool found in cache ${toolPath}`); @@ -45,7 +46,7 @@ export async function getJava( )).readBody(); let refs = contents.match(//gi) || []; - const downloadInfo = getDownloadInfo(refs, version); + const downloadInfo = getDownloadInfo(refs, version, javaPackage); jdkFile = await tc.downloadTool(downloadInfo.url); version = downloadInfo.version; @@ -66,7 +67,7 @@ export async function getJava( core.debug(`jdk extracted to ${jdkDir}`); toolPath = await tc.cacheDir( jdkDir, - 'Java', + javaPackage, getCacheVersionString(version), arch ); @@ -173,7 +174,8 @@ async function unzipJavaDownload( function getDownloadInfo( refs: string[], - version: string + version: string, + javaPackage: string ): {version: string; url: string} { version = normalizeVersion(version); let extension = ''; @@ -187,17 +189,34 @@ function getDownloadInfo( } } + 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]` + ); + } + // Maps version to url let versionMap = new Map(); // Filter by platform refs.forEach(ref => { - if (ref.indexOf(extension) < 0) { + if (!ref.endsWith(extension + '">')) { return; } // If we haven't returned, means we're looking at the correct platform - let versions = ref.match(/jdk.*-/gi) || []; + let versions = ref.match(pkgRegexp) || []; if (versions.length > 1) { throw new Error( `Invalid ref received from https://static.azul.com/zulu/bin/: ${ref}` @@ -206,7 +225,7 @@ function getDownloadInfo( if (versions.length == 0) { return; } - const refVersion = versions[0].slice('jdk'.length, versions[0].length - 1); + const refVersion = versions[0].slice(pkgTypeLength, versions[0].length - 1); if (semver.satisfies(refVersion, version)) { versionMap.set( @@ -231,7 +250,7 @@ function getDownloadInfo( if (curUrl == '') { throw new Error( - `No valid download found for version ${version}. Check https://static.azul.com/zulu/bin/ for a list of valid versions or download your own jdk file and add the jdkFile argument` + `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` ); } diff --git a/src/setup-java.ts b/src/setup-java.ts index c5f84ba..1d26bff 100644 --- a/src/setup-java.ts +++ b/src/setup-java.ts @@ -9,9 +9,10 @@ async function run() { version = core.getInput('java-version', {required: true}); } const arch = core.getInput('architecture', {required: true}); + const javaPackage = core.getInput('java-package', {required: true}); const jdkFile = core.getInput('jdkFile', {required: false}) || ''; - await installer.getJava(version, arch, jdkFile); + await installer.getJava(version, arch, jdkFile, javaPackage); const matchersPath = path.join(__dirname, '..', '.github'); console.log(`##[add-matcher]${path.join(matchersPath, 'java.json')}`); From 53de71b0d54731457476da5ef99798241c19be9e Mon Sep 17 00:00:00 2001 From: Gil Tene Date: Fri, 22 Nov 2019 10:45:27 -0800 Subject: [PATCH 2/2] Changes optional options to actually be optional --- action.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/action.yml b/action.yml index 78ad3c8..224f823 100644 --- a/action.yml +++ b/action.yml @@ -5,13 +5,13 @@ inputs: java-version: description: 'The Java version to make available on the path. Takes a whole or semver Java version, or 1.x syntax (e.g. 1.8 => Java 8.x)' required: true - java-package: +java-package: description: 'The package type (jre, jdk, jdk+fx)' - required: true + required: false default: 'jdk' - architecture: +architecture: description: 'The architecture (x86, x64) of the package.' - required: true + required: false default: 'x64' jdkFile: description: 'Path to where the compressed JDK is located. The path could be in your source repository or a local path on the agent.'