diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 1b7aa6584..fbc613873 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -5,7 +5,7 @@ jobs: runs-on: ${{ matrix.operating-system }} strategy: matrix: - operating-system: [ubuntu-latest, windows-latest] + operating-system: [ubuntu-latest, windows-latest, macOS-latest] steps: - name: Checkout uses: actions/checkout@v2 @@ -20,7 +20,34 @@ jobs: - name: npm test run: npm test - test: + testAdoptOpenJDK: + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: [ubuntu-latest, windows-latest] + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Clear tool cache + if: runner.os != 'windows' + run: mv "${{ runner.tool_cache }}" "${{ runner.tool_cache }}.old" + - name: Clear tool cache (Windows) + if: runner.os == 'windows' + run: move "${{ runner.tool_cache }}" "${{ runner.tool_cache }}.old" + - name: Setup Java 13 + id: setup-java-adopt + uses: ./ + with: + java-version: 13.0.2 + distro: adoptopenjdk + - name: Verify Java 13 + if: runner.os != 'windows' + run: __tests__/verify-java.sh 13.0.2 "${{ steps.setup-java-adopt.outputs.path }}" "${{ steps.setup-java-adopt.outputs.version }}" + - name: Verify Java 13 (Windows) + if: runner.os == 'windows' + run: __tests__/verify-java.ps1 13.0.2 "${{ steps.setup-java-adopt.outputs.path }}" "${{ steps.setup-java-adopt.outputs.version }}" + + testZulu: runs-on: ${{ matrix.operating-system }} strategy: matrix: @@ -35,18 +62,45 @@ jobs: if: runner.os == 'windows' run: move "${{ runner.tool_cache }}" "${{ runner.tool_cache }}.old" - name: Setup Java 13 - id: setup-java + id: setup-java-zulu uses: ./ with: java-version: 13.0.2 + distro: zulu - name: Verify Java 13 if: runner.os != 'windows' - run: __tests__/verify-java.sh 13.0.2 "${{ steps.setup-java.outputs.path }}" "${{ steps.setup-java.outputs.version }}" + run: __tests__/verify-java.sh 13.0.2 "${{ steps.setup-java-zulu.outputs.path }}" "${{ steps.setup-java-zulu.outputs.version }}" - name: Verify Java 13 (Windows) if: runner.os == 'windows' - run: __tests__/verify-java.ps1 13.0.2 "${{ steps.setup-java.outputs.path }}" "${{ steps.setup-java.outputs.version }}" + run: __tests__/verify-java.ps1 13.0.2 "${{ steps.setup-java-zulu.outputs.path }}" "${{ steps.setup-java-zulu.outputs.version }}" + + test-proxy-adopt: + runs-on: ubuntu-latest + container: + image: ubuntu:latest + options: --dns 127.0.0.1 + services: + squid-proxy: + image: datadog/squid:latest + ports: + - 3128:3128 + env: + https_proxy: http://squid-proxy:3128 + steps: + - uses: actions/checkout@v2 + - name: Clear tool cache + run: rm -rf $RUNNER_TOOL_CACHE/* + - name: Setup Java 13 + id: setup-java + uses: ./ + with: + java-version: 13 + distro: 'adoptopenjdk' + - name: Verify Java 13 + run: __tests__/verify-java.sh 13.0.2 "${{ steps.setup-java.outputs.path }}" "${{ steps.setup-java.outputs.version }}" + - test-proxy: + test-proxy-zulu: runs-on: ubuntu-latest container: image: ubuntu:latest @@ -67,6 +121,7 @@ jobs: uses: ./ with: java-version: 13.0.2 + distro: zulu - name: Verify Java 13 run: __tests__/verify-java.sh 13.0.2 "${{ steps.setup-java.outputs.path }}" "${{ steps.setup-java.outputs.version }}" @@ -84,5 +139,6 @@ jobs: uses: ./ with: java-version: 13.0.2 + distro: zulu - name: Verify Java 13 run: __tests__/verify-java.sh 13.0.2 "${{ steps.setup-java.outputs.path }}" "${{ steps.setup-java.outputs.version }}" diff --git a/README.md b/README.md index 2cd5af64a..aa6fbaef9 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,8 @@ steps: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 with: - java-version: '9.0.4' # The JDK version to make available on the path. + java-version: '11' # The JDK version to make available on the path. + vendor: adoptopenjdk # (adoptopenjdk or zulu) - defaults to adoptopenjdk java-package: jdk # (jre, jdk, or jdk+fx) - defaults to jdk architecture: x64 # (x64 or x86) - defaults to x64 - run: java -cp java HelloWorldApp @@ -29,14 +30,14 @@ Examples of version specifications that the java-version parameter will accept: - A major Java version e.g. ```6, 7, 8, 9, 10, 11, 12, 13, ...``` - + - A semver Java version specification e.g. ```8.0.232, 7.0.181, 11.0.4``` - - e.g. ```8.0.x, >11.0.3, >=13.0.1, <8.0.212``` - -- An early access (EA) Java version + + e.g. ```8.0.x, >11.0.3, >=13.0.1, <8.0.212``` (Zulu only) + +- An early access (EA) Java version (Zulu only) e.g. ```14-ea, 15-ea``` @@ -45,7 +46,7 @@ Examples of version specifications that the java-version parameter will accept: e.g. ```14.0.0-ea.28, 15.0.0-ea.2``` (syntax for specifying an EA build number) Note that, per semver rules, EA builds will be matched by explicit EA version specifications. - + - 1.x syntax e.g. ```1.8``` (same as ```8```) diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index ff2d61b5b..c41b3fcb5 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -13,12 +13,15 @@ import * as installer from '../src/installer'; let javaFilePath = ''; let javaUrl = ''; +let additionalPath = ''; if (process.platform === 'win32') { javaFilePath = path.join(javaDir, 'java_win.zip'); javaUrl = 'https://download.java.net/java/GA/jdk12/33/GPL/openjdk-12_windows-x64_bin.zip'; } else if (process.platform === 'darwin') { javaFilePath = path.join(javaDir, 'java_mac.tar.gz'); + // macOS tarballs are in bundle format + additionalPath = '/Contents/Home'; javaUrl = 'https://download.java.net/java/GA/jdk12/33/GPL/openjdk-12_osx-x64_bin.tar.gz'; } else { @@ -51,50 +54,97 @@ describe('installer tests', () => { } }, 100000); - it('Installs version of Java from jdkFile if no matching version is installed', async () => { - await installer.getJava('12', 'x64', javaFilePath, 'jdk'); + it('Installs version of Java from jdkFile if no matching version is installed AdoptOpenJDK', async () => { + await installer.getJava('12', 'adoptopenjdk', '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, additionalPath, 'bin'))).toBe(true); + }, 100000); + it('Installs version of Java from jdkFile if no matching version is installed Zulu', async () => { + await installer.getJava('12', 'zulu', '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); + expect(fs.existsSync(path.join(JavaDir, additionalPath, 'bin'))).toBe(true); }, 100000); - it('Throws if invalid directory to jdk', async () => { + it('Throws if invalid directory to jdk AdoptOpenJDK', async () => { let thrown = false; try { - await installer.getJava('1000', 'x64', 'bad path', 'jdk'); + await installer.getJava('1000', 'adoptopenjdk', 'x64', 'bad path', 'jdk'); } catch { thrown = true; } expect(thrown).toBe(true); }); - it('Downloads java if no file given', async () => { - await installer.getJava('8.0.102', 'x64', '', 'jdk'); - const JavaDir = path.join(toolDir, 'jdk', '8.0.102', 'x64'); + it('Throws if invalid directory to jdk Zulu', async () => { + let thrown = false; + try { + await installer.getJava('1000', 'zulu', 'x64', 'bad path', 'jdk'); + } catch { + thrown = true; + } + expect(thrown).toBe(true); + }); + + it('Downloads java if no file given AdoptOpenJDK', async () => { + await installer.getJava('8.0.252', 'adoptopenjdk', 'x64', '', 'jdk'); + const JavaDir = path.join(toolDir, 'jdk', '8.0.252', 'x64'); + expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true); + expect(fs.existsSync(path.join(JavaDir, additionalPath, 'bin'))).toBe(true); + }, 100000); + + it('Downloads java if no file given Zulu', async () => { + await installer.getJava('8.0.102', 'zulu', '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', '', 'jdk'); + it('Downloads java with 1.x syntax AdoptOpenJDK', async () => { + await installer.getJava('1.13', 'adoptopenjdk', 'x64', '', 'jdk'); + const JavaDir = path.join(toolDir, 'jdk', '13.0.2', 'x64'); + + expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true); + expect(fs.existsSync(path.join(JavaDir, additionalPath, 'bin'))).toBe(true); + }, 100000); + + it('Downloads java with 1.x syntax Zulu', async () => { + await installer.getJava('1.10', 'zulu', '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', '', 'jdk'); + it('Downloads java with normal semver syntax AdoptOpenJDK', async () => { + await installer.getJava('13.0.x', 'adoptopenjdk', 'x64', '', 'jdk'); + const JavaDir = path.join(toolDir, 'jdk', '13.0.2', 'x64'); + + expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true); + expect(fs.existsSync(path.join(JavaDir, additionalPath, 'bin'))).toBe(true); + }, 100000); + + it('Downloads java with normal semver syntax Zulu', async () => { + await installer.getJava('9.0.x', 'zulu', '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'); + it('Downloads java if package is jre AdoptOpenJDK', async () => { + await installer.getJava('11.0.2', 'adoptopenjdk', 'x64', '', 'jre'); + const JavaDir = path.join(toolDir, 'jre', '11.0.2', 'x64'); + + expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true); + expect(fs.existsSync(path.join(JavaDir, additionalPath, 'bin'))).toBe(true); + }, 100000); + + it('Downloads java if package is jre Zulu', async () => { + await installer.getJava('8.0.222', 'zulu', 'x64', '', 'jre'); const JavaDir = path.join(toolDir, 'jre', '8.0.222', 'x64'); expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true); @@ -102,17 +152,27 @@ describe('installer tests', () => { }, 100000); it('Downloads java if package is jdk+fx', async () => { - await installer.getJava('8.0.222', 'x64', '', 'jdk+fx'); + await installer.getJava('8.0.222', 'zulu', '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 () => { + it('Throws if invalid java package is specified AdoptOpenJDK', async () => { + let thrown = false; + try { + await installer.getJava('8', 'adoptopenjdk', 'x64', '', 'bad jdk'); + } catch { + thrown = true; + } + expect(thrown).toBe(true); + }); + + it('Throws if invalid java package is specified Zulu', async () => { let thrown = false; try { - await installer.getJava('8.0.222', 'x64', '', 'bad jdk'); + await installer.getJava('8.0.222', 'zulu', 'x64', '', 'bad jdk'); } catch { thrown = true; } @@ -122,7 +182,7 @@ describe('installer tests', () => { it('Throws if invalid directory to jdk', async () => { let thrown = false; try { - await installer.getJava('1000', 'x64', 'bad path', 'jdk'); + await installer.getJava('1000', 'zulu', 'x64', 'bad path', 'jdk'); } catch { thrown = true; } @@ -136,6 +196,7 @@ describe('installer tests', () => { // This will throw if it doesn't find it in the cache (because no such version exists) await installer.getJava( '250', + 'zulu', 'x64', 'path shouldnt matter, found in cache', 'jdk' @@ -149,7 +210,7 @@ describe('installer tests', () => { 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', 'jdk'); + await installer.getJava('251', 'zulu', 'x64', 'bad path', 'jdk'); } catch { thrown = true; } diff --git a/action.yml b/action.yml index 745726873..225ad5616 100644 --- a/action.yml +++ b/action.yml @@ -9,6 +9,11 @@ inputs: Early access versions can be specified in the form of e.g. 14-ea, 14.0.0-ea, or 14.0.0-ea.28' required: true + distro: + description: 'The vendor to fetch the binary from (adoptopenjdk, zulu). + Defaults to adoptopenjdk' + required: false + default: 'adoptopenjdk' java-package: description: 'The package type (jre, jdk, jdk+fx)' required: false diff --git a/dist/setup/index.js b/dist/setup/index.js index 3beeeecea..b3815dee0 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -7905,7 +7905,7 @@ const RangeImpl_1 = __webpack_require__(90); exports.Range = RangeImpl_1.RangeImpl; const ShadowRootImpl_1 = __webpack_require__(581); exports.ShadowRoot = ShadowRootImpl_1.ShadowRootImpl; -const SlotableImpl_1 = __webpack_require__(476); +const SlotableImpl_1 = __webpack_require__(340); const StaticRangeImpl_1 = __webpack_require__(688); exports.StaticRange = StaticRangeImpl_1.StaticRangeImpl; const TextImpl_1 = __webpack_require__(820); @@ -13681,6 +13681,33 @@ exports.utf8Decode = utf8Decode; /***/ }), +/***/ 340: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const algorithm_1 = __webpack_require__(163); +/** + * Represents a mixin that allows nodes to become the contents of + * a element. This mixin is implemented by {@link Element} and + * {@link Text}. + */ +class SlotableImpl { + get _name() { return this.__name || ''; } + set _name(val) { this.__name = val; } + get _assignedSlot() { return this.__assignedSlot || null; } + set _assignedSlot(val) { this.__assignedSlot = val; } + /** @inheritdoc */ + get assignedSlot() { + return algorithm_1.shadowTree_findASlot(this, true); + } +} +exports.SlotableImpl = SlotableImpl; +//# sourceMappingURL=SlotableImpl.js.map + +/***/ }), + /***/ 344: /***/ (function(__unusedmodule, exports) { @@ -17406,25 +17433,86 @@ exports.getState = getState; "use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; Object.defineProperty(exports, "__esModule", { value: true }); -const algorithm_1 = __webpack_require__(163); -/** - * Represents a mixin that allows nodes to become the contents of - * a element. This mixin is implemented by {@link Element} and - * {@link Text}. - */ -class SlotableImpl { - get _name() { return this.__name || ''; } - set _name(val) { this.__name = val; } - get _assignedSlot() { return this.__assignedSlot || null; } - set _assignedSlot(val) { this.__assignedSlot = val; } - /** @inheritdoc */ - get assignedSlot() { - return algorithm_1.shadowTree_findASlot(this, true); +const core = __importStar(__webpack_require__(470)); +const tc = __importStar(__webpack_require__(533)); +const httpm = __importStar(__webpack_require__(539)); +function getJavaAdoptOpenJDK(version, javaPackage, arch) { + return __awaiter(this, void 0, void 0, function* () { + core.debug('Downloading JDK from AdoptOpenJDK'); + let OS = process.platform.toString(); + switch (process.platform) { + case 'darwin': + OS = 'mac'; + break; + case 'win32': + OS = 'windows'; + break; + } + const http = new httpm.HttpClient('setup-java', undefined, { + allowRetries: true, + maxRetries: 3 + }); + const url = `https://api.adoptopenjdk.net/v3/assets/version/${normalizeVersion(version)}?architecture=${arch}&heap_size=normal&image_type=${javaPackage}&jvm_impl=hotspot&os=${OS}&page_size=1&release_type=ga&vendor=adoptopenjdk`; + const response = yield http.get(url); + const statusCode = response.message.statusCode || 0; + if (statusCode < 200 || statusCode > 299) { + let body = ''; + try { + body = yield response.readBody(); + } + catch (err) { + core.debug(`Unable to read body: ${err.message}`); + } + const message = `Unexpected HTTP status code '${response.message.statusCode}' when retrieving versions from '${url}'. ${body}`.trim(); + throw new Error(message); + } + const contents = yield response.readBody(); + const parsedContents = JSON.parse(contents)[0]; + // turn 13.0.2+8.1 into 13.0.2 + version = parsedContents.version_data.semver.split('+')[0]; + const jdkFile = yield tc.downloadTool(parsedContents.binaries[0].package.link); + return [jdkFile, version]; + }); +} +exports.getJavaAdoptOpenJDK = getJavaAdoptOpenJDK; +function normalizeVersion(version) { + 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'); + } + } + const parsedVersion = version.split('.'); + let versionNumber; + if (parsedVersion[1]) { + versionNumber = parseInt(parsedVersion[parsedVersion.length - 1]) + 1; + version = `%28%2C${version.replace(parsedVersion[parsedVersion.length - 1], versionNumber.toString())}%29`; } + else { + versionNumber = parseInt(version) + 1; + version = `%28%2C${versionNumber.toString()}%29`; + } + return version; } -exports.SlotableImpl = SlotableImpl; -//# sourceMappingURL=SlotableImpl.js.map + /***/ }), @@ -28689,7 +28777,8 @@ function run() { required: true }); const jdkFile = core.getInput(constants.INPUT_JDK_FILE, { required: false }); - yield installer.getJava(version, arch, jdkFile, javaPackage); + const distro = core.getInput('distro', { required: true }); + yield installer.getJava(version, distro, arch, jdkFile, javaPackage); const matchersPath = path.join(__dirname, '..', '..', '.github'); core.info(`##[add-matcher]${path.join(matchersPath, 'java.json')}`); const id = core.getInput(constants.INPUT_SERVER_ID, { required: false }); @@ -33358,6 +33447,161 @@ exports.CDATASectionImpl = CDATASectionImpl; WebIDLAlgorithm_1.idl_defineConst(CDATASectionImpl.prototype, "_nodeType", interfaces_1.NodeType.CData); //# sourceMappingURL=CDATASectionImpl.js.map +/***/ }), + +/***/ 922: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const core = __importStar(__webpack_require__(470)); +const tc = __importStar(__webpack_require__(533)); +const httpm = __importStar(__webpack_require__(539)); +const semver = __importStar(__webpack_require__(280)); +const IS_WINDOWS = process.platform === 'win32'; +function getJavaZulu(version, javaPackage) { + return __awaiter(this, void 0, void 0, function* () { + core.debug('Downloading JDK from Azul'); + const http = new httpm.HttpClient('setup-java', undefined, { + allowRetries: true, + maxRetries: 3 + }); + const url = 'https://static.azul.com/zulu/bin/'; + const response = yield http.get(url); + const statusCode = response.message.statusCode || 0; + if (statusCode < 200 || statusCode > 299) { + let body = ''; + try { + body = yield response.readBody(); + } + catch (err) { + core.debug(`Unable to read body: ${err.message}`); + } + const message = `Unexpected HTTP status code '${response.message.statusCode}' when retrieving versions from '${url}'. ${body}`.trim(); + throw new Error(message); + } + const contents = yield response.readBody(); + const refs = contents.match(//gi) || []; + const downloadInfo = getDownloadInfo(refs, version, javaPackage); + const jdkFile = yield tc.downloadTool(downloadInfo.url); + version = downloadInfo.version; + return [jdkFile, version]; + }); +} +exports.getJavaZulu = getJavaZulu; +function getDownloadInfo(refs, version, javaPackage) { + version = normalizeVersion(version); + let extension = ''; + if (IS_WINDOWS) { + extension = `-win_x64.zip`; + } + else { + if (process.platform === 'darwin') { + extension = `-macosx_x64.tar.gz`; + } + else { + 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.endsWith(extension + '">')) { + return; + } + // If we haven't returned, means we're looking at the correct platform + 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(pkgTypeLength, versions[0].length - 1); + if (semver.satisfies(refVersion, version)) { + versionMap.set(refVersion, 'https://static.azul.com/zulu/bin/' + + ref.slice(''.length)); + } + }); + // 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 == '') { + 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 }; +} +function normalizeVersion(version) { + 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'); + } + } + if (version.endsWith('-ea')) { + // convert e.g. 14-ea to 14.0.0-ea + if (version.indexOf('.') == -1) { + version = version.slice(0, version.length - 3) + '.0.0-ea'; + } + // match anything in -ea.X (semver won't do .x matching on pre-release versions) + if (version[0] >= '0' && version[0] <= '9') { + version = '>=' + version; + } + } + else if (version.split('.').length < 3) { + // For non-ea versions, add trailing .x if it is missing + if (version[version.length - 1] != 'x') { + version = version + '.x'; + } + } + return version; +} + + /***/ }), /***/ 923: @@ -33385,15 +33629,15 @@ Object.defineProperty(exports, "__esModule", { value: true }); const core = __importStar(__webpack_require__(470)); const io = __importStar(__webpack_require__(1)); const exec = __importStar(__webpack_require__(986)); -const httpm = __importStar(__webpack_require__(539)); const tc = __importStar(__webpack_require__(533)); const fs = __importStar(__webpack_require__(747)); const path = __importStar(__webpack_require__(622)); -const semver = __importStar(__webpack_require__(280)); const util = __importStar(__webpack_require__(322)); +const adoptopenjdk_1 = __webpack_require__(476); +const zulu_1 = __webpack_require__(922); const tempDirectory = util.getTempDir(); const IS_WINDOWS = util.isWindows(); -function getJava(version, arch, jdkFile, javaPackage) { +function getJava(version, distro, arch, jdkFile, javaPackage) { return __awaiter(this, void 0, void 0, function* () { let toolPath = tc.find(javaPackage, version); if (toolPath) { @@ -33402,30 +33646,20 @@ function getJava(version, arch, jdkFile, javaPackage) { else { let compressedFileExtension = ''; if (!jdkFile) { - core.debug('Downloading JDK from Azul'); - const http = new httpm.HttpClient('setup-java', undefined, { - allowRetries: true, - maxRetries: 3 - }); - const url = 'https://static.azul.com/zulu/bin/'; - const response = yield http.get(url); - const statusCode = response.message.statusCode || 0; - if (statusCode < 200 || statusCode > 299) { - let body = ''; - try { - body = yield response.readBody(); - } - catch (err) { - core.debug(`Unable to read body: ${err.message}`); - } - const message = `Unexpected HTTP status code '${response.message.statusCode}' when retrieving versions from '${url}'. ${body}`.trim(); - throw new Error(message); - } - const contents = yield response.readBody(); - const refs = contents.match(//gi) || []; - const downloadInfo = getDownloadInfo(refs, version, javaPackage); - jdkFile = yield tc.downloadTool(downloadInfo.url); - version = downloadInfo.version; + function setupVendor(distro) { + return __awaiter(this, void 0, void 0, function* () { + switch (distro) { + case 'adoptopenjdk': + [jdkFile, version] = yield adoptopenjdk_1.getJavaAdoptOpenJDK(version, javaPackage, arch); + break; + case 'zulu': + [jdkFile, version] = yield zulu_1.getJavaZulu(version, javaPackage); + break; + } + return [jdkFile, version]; + }); + } + [jdkFile, version] = yield setupVendor(distro); compressedFileExtension = IS_WINDOWS ? '.zip' : '.tar.gz'; } else { @@ -33437,6 +33671,8 @@ function getJava(version, arch, jdkFile, javaPackage) { core.debug(`jdk extracted to ${jdkDir}`); toolPath = yield tc.cacheDir(jdkDir, javaPackage, getCacheVersionString(version), arch); } + if (process.platform === 'darwin') + toolPath += '/Contents/Home'; let extendedJavaHome = 'JAVA_HOME_' + version + '_' + arch; core.exportVariable(extendedJavaHome, toolPath); //TODO: remove for v2 // For portability reasons environment variables should only consist of @@ -33539,100 +33775,6 @@ function unzipJavaDownload(repoRoot, fileEnding, destinationFolder, extension) { } }); } -function getDownloadInfo(refs, version, javaPackage) { - version = normalizeVersion(version); - let extension = ''; - if (IS_WINDOWS) { - extension = `-win_x64.zip`; - } - else { - if (process.platform === 'darwin') { - extension = `-macosx_x64.tar.gz`; - } - else { - 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.endsWith(extension + '">')) { - return; - } - // If we haven't returned, means we're looking at the correct platform - 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(pkgTypeLength, versions[0].length - 1); - if (semver.satisfies(refVersion, version)) { - versionMap.set(refVersion, 'https://static.azul.com/zulu/bin/' + - ref.slice(''.length)); - } - }); - // 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 == '') { - 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 }; -} -function normalizeVersion(version) { - 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'); - } - } - if (version.endsWith('-ea')) { - // convert e.g. 14-ea to 14.0.0-ea - if (version.indexOf('.') == -1) { - version = version.slice(0, version.length - 3) + '.0.0-ea'; - } - // match anything in -ea.X (semver won't do .x matching on pre-release versions) - if (version[0] >= '0' && version[0] <= '9') { - version = '>=' + version; - } - } - else if (version.split('.').length < 3) { - // For non-ea versions, add trailing .x if it is missing - if (version[version.length - 1] != 'x') { - version = version + '.x'; - } - } - return version; -} /***/ }), diff --git a/package.json b/package.json index 9f3817368..33bb56541 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "main": "dist/index.js", "scripts": { "build": "ncc build -o dist/setup src/setup-java.ts && ncc build -o dist/cleanup src/cleanup-java.ts", - "format": "prettier --write **/*.ts", - "format-check": "prettier --check **/*.ts", + "format": "prettier --write **/*.ts src/distro/*.ts", + "format-check": "prettier --check **/*.ts src/distro/*.ts", "prerelease": "npm run-script build", "release": "git add -f dist/setup/index.js dist/cleanup/index.js", "test": "jest" diff --git a/src/distro/adoptopenjdk.ts b/src/distro/adoptopenjdk.ts new file mode 100644 index 000000000..021d8da08 --- /dev/null +++ b/src/distro/adoptopenjdk.ts @@ -0,0 +1,79 @@ +import * as core from '@actions/core'; +import * as tc from '@actions/tool-cache'; +import * as httpm from '@actions/http-client'; + +export async function getJavaAdoptOpenJDK( + version: string, + javaPackage: string, + arch: string +) { + core.debug('Downloading JDK from AdoptOpenJDK'); + + let OS = process.platform.toString(); + + switch (process.platform) { + case 'darwin': + OS = 'mac'; + break; + case 'win32': + OS = 'windows'; + break; + } + + const http = new httpm.HttpClient('setup-java', undefined, { + allowRetries: true, + maxRetries: 3 + }); + + const url = `https://api.adoptopenjdk.net/v3/assets/version/${normalizeVersion( + version + )}?architecture=${arch}&heap_size=normal&image_type=${javaPackage}&jvm_impl=hotspot&os=${OS}&page_size=1&release_type=ga&vendor=adoptopenjdk`; + + const response = await http.get(url); + const statusCode = response.message.statusCode || 0; + if (statusCode < 200 || statusCode > 299) { + let body = ''; + try { + body = await response.readBody(); + } catch (err) { + core.debug(`Unable to read body: ${err.message}`); + } + const message = `Unexpected HTTP status code '${response.message.statusCode}' when retrieving versions from '${url}'. ${body}`.trim(); + throw new Error(message); + } + + const contents = await response.readBody(); + + const parsedContents = JSON.parse(contents)[0]; + + // turn 13.0.2+8.1 into 13.0.2 + version = parsedContents.version_data.semver.split('+')[0]; + + const jdkFile = await tc.downloadTool( + parsedContents.binaries[0].package.link + ); + return [jdkFile, version]; +} + +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'); + } + } + const parsedVersion = version.split('.'); + let versionNumber: number; + if (parsedVersion[1]) { + versionNumber = parseInt(parsedVersion[parsedVersion.length - 1]) + 1; + version = `%28%2C${version.replace( + parsedVersion[parsedVersion.length - 1], + versionNumber.toString() + )}%29`; + } else { + versionNumber = parseInt(version) + 1; + version = `%28%2C${versionNumber!.toString()}%29`; + } + return version; +} diff --git a/src/distro/zulu.ts b/src/distro/zulu.ts new file mode 100644 index 000000000..c1cafa135 --- /dev/null +++ b/src/distro/zulu.ts @@ -0,0 +1,150 @@ +import * as core from '@actions/core'; +import * as tc from '@actions/tool-cache'; +import * as httpm from '@actions/http-client'; +import * as semver from 'semver'; + +const IS_WINDOWS = process.platform === 'win32'; + +export async function getJavaZulu(version: string, javaPackage: string) { + core.debug('Downloading JDK from Azul'); + const http = new httpm.HttpClient('setup-java', undefined, { + allowRetries: true, + maxRetries: 3 + }); + + const url = 'https://static.azul.com/zulu/bin/'; + + const response = await http.get(url); + const statusCode = response.message.statusCode || 0; + if (statusCode < 200 || statusCode > 299) { + let body = ''; + try { + body = await response.readBody(); + } catch (err) { + core.debug(`Unable to read body: ${err.message}`); + } + const message = `Unexpected HTTP status code '${response.message.statusCode}' when retrieving versions from '${url}'. ${body}`.trim(); + throw new Error(message); + } + + const contents = await response.readBody(); + const refs = contents.match(//gi) || []; + const downloadInfo = getDownloadInfo(refs, version, javaPackage); + const jdkFile = await tc.downloadTool(downloadInfo.url); + + version = downloadInfo.version; + return [jdkFile, version]; +} + +function getDownloadInfo( + refs: string[], + version: string, + javaPackage: string +): {version: string; url: string} { + version = normalizeVersion(version); + let extension = ''; + if (IS_WINDOWS) { + extension = `-win_x64.zip`; + } else { + if (process.platform === 'darwin') { + extension = `-macosx_x64.tar.gz`; + } else { + 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.endsWith(extension + '">')) { + return; + } + + // If we haven't returned, means we're looking at the correct platform + 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(pkgTypeLength, versions[0].length - 1); + + if (semver.satisfies(refVersion, version)) { + versionMap.set( + refVersion, + 'https://static.azul.com/zulu/bin/' + + ref.slice(''.length) + ); + } + }); + + // 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 == '') { + 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}; +} + +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'); + } + } + + if (version.endsWith('-ea')) { + // convert e.g. 14-ea to 14.0.0-ea + if (version.indexOf('.') == -1) { + version = version.slice(0, version.length - 3) + '.0.0-ea'; + } + // match anything in -ea.X (semver won't do .x matching on pre-release versions) + if (version[0] >= '0' && version[0] <= '9') { + version = '>=' + version; + } + } else if (version.split('.').length < 3) { + // For non-ea versions, add trailing .x if it is missing + if (version[version.length - 1] != 'x') { + version = version + '.x'; + } + } + + return version; +} diff --git a/src/installer.ts b/src/installer.ts index 88a8ff181..03633ef64 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -1,18 +1,21 @@ import * as core from '@actions/core'; import * as io from '@actions/io'; import * as exec from '@actions/exec'; -import * as httpm from '@actions/http-client'; import * as tc from '@actions/tool-cache'; import * as fs from 'fs'; import * as path from 'path'; import * as semver from 'semver'; import * as util from './util'; +import {getJavaAdoptOpenJDK} from './distro/adoptopenjdk'; +import {getJavaZulu} from './distro/zulu'; + const tempDirectory = util.getTempDir(); const IS_WINDOWS = util.isWindows(); export async function getJava( version: string, + distro: string, arch: string, jdkFile: string, javaPackage: string @@ -23,31 +26,26 @@ export async function getJava( core.debug(`Tool found in cache ${toolPath}`); } else { let compressedFileExtension = ''; + if (!jdkFile) { - core.debug('Downloading JDK from Azul'); - const http = new httpm.HttpClient('setup-java', undefined, { - allowRetries: true, - maxRetries: 3 - }); - const url = 'https://static.azul.com/zulu/bin/'; - const response = await http.get(url); - const statusCode = response.message.statusCode || 0; - if (statusCode < 200 || statusCode > 299) { - let body = ''; - try { - body = await response.readBody(); - } catch (err) { - core.debug(`Unable to read body: ${err.message}`); + async function setupVendor(distro: string) { + switch (distro) { + case 'adoptopenjdk': + [jdkFile, version] = await getJavaAdoptOpenJDK( + version, + javaPackage, + arch + ); + break; + case 'zulu': + [jdkFile, version] = await getJavaZulu(version, javaPackage); + break; } - const message = `Unexpected HTTP status code '${response.message.statusCode}' when retrieving versions from '${url}'. ${body}`.trim(); - throw new Error(message); + return [jdkFile, version]; } - const contents = await response.readBody(); - const refs = contents.match(//gi) || []; - const downloadInfo = getDownloadInfo(refs, version, javaPackage); - jdkFile = await tc.downloadTool(downloadInfo.url); - version = downloadInfo.version; + [jdkFile, version] = await setupVendor(distro); + compressedFileExtension = IS_WINDOWS ? '.zip' : '.tar.gz'; } else { core.debug('Retrieving Jdk from local path'); @@ -71,6 +69,8 @@ export async function getJava( ); } + if (process.platform === 'darwin') toolPath += '/Contents/Home'; + let extendedJavaHome = 'JAVA_HOME_' + version + '_' + arch; core.exportVariable(extendedJavaHome, toolPath); //TODO: remove for v2 // For portability reasons environment variables should only consist of @@ -177,116 +177,3 @@ async function unzipJavaDownload( throw new Error(`Jdk argument ${jdkFile} is not a file`); } } - -function getDownloadInfo( - refs: string[], - version: string, - javaPackage: string -): {version: string; url: string} { - version = normalizeVersion(version); - let extension = ''; - if (IS_WINDOWS) { - extension = `-win_x64.zip`; - } else { - if (process.platform === 'darwin') { - extension = `-macosx_x64.tar.gz`; - } else { - 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.endsWith(extension + '">')) { - return; - } - - // If we haven't returned, means we're looking at the correct platform - 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(pkgTypeLength, versions[0].length - 1); - - if (semver.satisfies(refVersion, version)) { - versionMap.set( - refVersion, - 'https://static.azul.com/zulu/bin/' + - ref.slice(''.length) - ); - } - }); - - // 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 == '') { - 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}; -} - -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'); - } - } - - if (version.endsWith('-ea')) { - // convert e.g. 14-ea to 14.0.0-ea - if (version.indexOf('.') == -1) { - version = version.slice(0, version.length - 3) + '.0.0-ea'; - } - // match anything in -ea.X (semver won't do .x matching on pre-release versions) - if (version[0] >= '0' && version[0] <= '9') { - version = '>=' + version; - } - } else if (version.split('.').length < 3) { - // For non-ea versions, add trailing .x if it is missing - if (version[version.length - 1] != 'x') { - version = version + '.x'; - } - } - - return version; -} diff --git a/src/setup-java.ts b/src/setup-java.ts index db169f296..4d852c047 100644 --- a/src/setup-java.ts +++ b/src/setup-java.ts @@ -16,8 +16,9 @@ async function run() { required: true }); const jdkFile = core.getInput(constants.INPUT_JDK_FILE, {required: false}); + const distro = core.getInput('distro', {required: true}); - await installer.getJava(version, arch, jdkFile, javaPackage); + await installer.getJava(version, distro, arch, jdkFile, javaPackage); const matchersPath = path.join(__dirname, '..', '..', '.github'); core.info(`##[add-matcher]${path.join(matchersPath, 'java.json')}`);