Skip to content

Commit

Permalink
Add microsoft distribution of the JDK.
Browse files Browse the repository at this point in the history
  • Loading branch information
brendanburns committed Nov 18, 2021
1 parent ae26cab commit 4dd2998
Show file tree
Hide file tree
Showing 7 changed files with 419 additions and 8 deletions.
16 changes: 10 additions & 6 deletions .github/workflows/e2e-versions.yml
Expand Up @@ -14,13 +14,14 @@ on:
workflow_dispatch:
jobs:
setup-java-major-versions:
if: ${{ matrix.distribution != 'microsoft' || matrix.version != '8' }}
name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-x64) - ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
distribution: ['temurin', 'adopt', 'adopt-openj9', 'zulu'] # internally 'adopt-hotspot' is the same as 'adopt'
distribution: ['temurin', 'adopt', 'adopt-openj9', 'zulu', 'microsoft' ] # internally 'adopt-hotspot' is the same as 'adopt'
version: ['8', '11', '16']
steps:
- name: Checkout
Expand Down Expand Up @@ -167,16 +168,19 @@ jobs:
shell: bash

setup-java-custom-architecture:
name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-x86) - ${{ matrix.os }}
# Only Zulu provides x86 arch for now and only for windows / ubuntu
# Only Microsoft provides arm64 for windows / ubuntu / os x
if: ${{ (matrix.distribution == 'zulu' && matrix.architecture == 'x86' && matrix.os != 'macos-latest' ) || (matrix.distribution == 'microsoft' && matrix.architecture == 'arm64') }}
name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-${{ matrix.architecture }}) - ${{ matrix.os }}
needs: setup-java-major-minor-versions
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
# Only Zulu provides x86 arch for now and only for windows / ubuntu
os: [windows-latest, ubuntu-latest]
distribution: ['zulu']
os: [macos-latest, windows-latest, ubuntu-latest]
distribution: ['zulu', 'microsoft']
version: ['11']
architecture: [ 'x86', 'arm64' ]
steps:
- name: Checkout
uses: actions/checkout@v2
Expand All @@ -186,7 +190,7 @@ jobs:
with:
distribution: ${{ matrix.distribution }}
java-version: ${{ matrix.version }}
architecture: x86
architecture: ${{ matrix.architecture }}
- name: Verify Java
run: bash __tests__/verify-java.sh "${{ matrix.version }}" "${{ steps.setup-java.outputs.path }}"
shell: bash
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -58,6 +58,7 @@ Currently, the following distributions are supported:
| `zulu` | Zulu OpenJDK | [Link](https://www.azul.com/downloads/zulu-community/?package=jdk) | [Link](https://www.azul.com/products/zulu-and-zulu-enterprise/zulu-terms-of-use/) |
| `adopt` or `adopt-hotspot` | Adopt OpenJDK Hotspot | [Link](https://adoptopenjdk.net/) | [Link](https://adoptopenjdk.net/about.html) |
| `adopt-openj9` | Adopt OpenJDK OpenJ9 | [Link](https://adoptopenjdk.net/) | [Link](https://adoptopenjdk.net/about.html)
| `microsoft` | Microsoft OpenJDK | [Link](https://www.microsoft.com/openjdk) | [Link](https://docs.microsoft.com/en-us/java/openjdk/faq)

**NOTE:** The different distributors can provide discrepant list of available versions / supported configurations. Please refer to the official documentation to see the list of supported versions.

Expand Down
100 changes: 100 additions & 0 deletions __tests__/distributors/microsoft-installer.test.ts
@@ -0,0 +1,100 @@
import { MicrosoftDistributions } from '../../src/distributions/microsoft/installer';
import { ArchitectureOptions } from '../../src/distributions/microsoft/models';

describe('getArchitectureOptions', () => {
it.each([
['x64', { bitness: '64', arch: 'x86' }],
['aarch64', { bitness: '64', arch: 'arm' }],
] as [string, ArchitectureOptions][])('parse architecture %s -> %s', (input, expected) => {
const distributions = new MicrosoftDistributions({
architecture: input,
checkLatest: false,
packageType: '',
version: ''
});

expect(distributions['getArchitectureOptions']()).toEqual(expected);
});

it.each(['armv6', 's390x'])('not support architecture %s', input => {
const distributions = new MicrosoftDistributions({
architecture: input,
checkLatest: false,
packageType: '',
version: ''
});

expect(() => distributions['getArchitectureOptions']()).toThrow(
/Architecture '\w+' is not supported\. Supported architectures: .*/
);
});
});

describe('findPackageForDownload', () => {
let distribution: MicrosoftDistributions;

beforeEach(() => {
distribution = new MicrosoftDistributions({
version: '',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
});

it.each([
['17.x', '17.0.1', 'https://aka.ms/download-jdk/microsoft-jdk-17.0.1.12.1-{{OS_TYPE}}-x64.tar.gz'],
['16.0.x', '16.0.2', 'https://aka.ms/download-jdk/microsoft-jdk-16.0.2.7.1-{{OS_TYPE}}-x64.tar.gz'],
['11.0.13', '11.0.13', 'https://aka.ms/download-jdk/microsoft-jdk-11.0.13.8.1-{{OS_TYPE}}-x64.tar.gz'],
])('version is %s -> %s', async (input, expectedVersion, expectedUrl) => {
const result = await distribution['findPackageForDownload'](input);
expect(result.version).toBe(expectedVersion);
var os: string;
switch (process.platform) {
case 'darwin':
os = 'macos';
break;
case 'win32':
os = 'windows';
break;
default:
os = process.platform.toString();
break;
}
expect(result.url).toBe(expectedUrl.replace('{{OS_TYPE}}', os));
});

it('should throw an error', async () => {
await expect(distribution['findPackageForDownload']('8')).rejects.toThrow(
/Could not find satisfied version for semver */
);
});
});

describe('getPlatformOption', () => {
const distributions = new MicrosoftDistributions({
architecture: 'x64',
version: '11',
packageType: 'jdk',
checkLatest: false
});

it.each([
['linux', 'linux'],
['darwin', 'macos'],
['win32', 'windows'],
])('os version %s -> %s', (input, expected) => {
const actual = distributions['getPlatformOption'](input as NodeJS.Platform);

expect(actual).toEqual(expected);
});

it.each(['aix', 'android', 'freebsd', 'openbsd', 'netbsd', 'solaris', 'cygwin'])(
'not support os version %s',
input => {
expect(() => distributions['getPlatformOption'](input as NodeJS.Platform)).toThrow(
/Platform '\w+' is not supported\. Supported platforms: .+/
);
}
);
});
164 changes: 163 additions & 1 deletion dist/setup/index.js
Expand Up @@ -14215,7 +14215,165 @@ exports.XMLCBWriter = XMLCBWriter;
/* 193 */,
/* 194 */,
/* 195 */,
/* 196 */,
/* 196 */
/***/ (function(__unusedmodule, exports, __webpack_require__) {

"use strict";

var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
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 __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MicrosoftDistributions = void 0;
const base_installer_1 = __webpack_require__(83);
const semver_1 = __importDefault(__webpack_require__(876));
const util_1 = __webpack_require__(322);
const core = __importStar(__webpack_require__(470));
const tc = __importStar(__webpack_require__(139));
const fs_1 = __importDefault(__webpack_require__(747));
const path_1 = __importDefault(__webpack_require__(622));
const supportedPlatform = `'linux', 'linux-musl', 'macos', 'solaris', 'windows'`;
const supportedArchitecture = `'x86', 'x64', 'armv7', 'aarch64', 'ppc64le'`;
class MicrosoftDistributions extends base_installer_1.JavaBase {
constructor(installerOptions) {
super('Microsoft', installerOptions);
}
downloadTool(javaRelease) {
return __awaiter(this, void 0, void 0, function* () {
core.info(`Downloading Java ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...`);
const javaArchivePath = yield tc.downloadTool(javaRelease.url);
core.info(`Extracting Java archive...`);
const extension = util_1.getDownloadArchiveExtension();
const extractedJavaPath = yield util_1.extractJdkFile(javaArchivePath, extension);
const archiveName = fs_1.default.readdirSync(extractedJavaPath)[0];
const archivePath = path_1.default.join(extractedJavaPath, archiveName);
const javaPath = yield tc.cacheDir(archivePath, this.toolcacheFolderName, this.getToolcacheVersionName(javaRelease.version), this.architecture);
return { version: javaRelease.version, path: javaPath };
});
}
findPackageForDownload(range) {
return __awaiter(this, void 0, void 0, function* () {
const availableVersionsRaw = yield this.getAvailableVersions();
const availableVersions = availableVersionsRaw.map(item => ({
url: item.downloadUrl,
version: this.convertVersionToSemver(item)
}));
const satisfiedVersion = availableVersions
.filter(item => util_1.isVersionSatisfies(range, item.version))
.sort((a, b) => -semver_1.default.compareBuild(a.version, b.version))[0];
if (!satisfiedVersion) {
const availableOptions = availableVersions.map(item => item.version).join(', ');
const availableOptionsMessage = availableOptions
? `\nAvailable versions: ${availableOptions}`
: '';
throw new Error(`Could not find satisfied version for semver ${range}. ${availableOptionsMessage}`);
}
return satisfiedVersion;
});
}
getAvailableVersions() {
var _a;
return __awaiter(this, void 0, void 0, function* () {
console.time('microsoft-retrieve-available-versions');
const url = this.prepareAvailableVersionsUrl();
if (core.isDebug()) {
core.debug(`Gathering available versions from '${url}'`);
}
const availableVersions = (_a = (yield this.http.getJson(url)).result) !== null && _a !== void 0 ? _a : [];
if (core.isDebug()) {
core.startGroup('Print information about available versions');
console.timeEnd('microsoft-retrieve-available-versions');
console.log(`Available versions: [${availableVersions.length}]`);
console.log(availableVersions.map(item => item.version));
core.endGroup();
}
return availableVersions;
});
}
prepareAvailableVersionsUrl() {
const urlOptions = Object.assign(Object.assign({ os: this.getPlatformOption(), 'bundle-type': this.getBundleType() }, this.getArchitectureOptions()), { 'build-type': this.stable ? 'all' : 'ea', 'installation-type': 'archive', fields: 'downloadUrl,version,featureVersion,interimVersion,updateVersion,buildVersion' });
const searchParams = new URLSearchParams(urlOptions).toString();
return `https://api.bell-sw.com/v1/liberica/releases?${searchParams}`;
}
getBundleType() {
const [bundleType, feature] = this.packageType.split('+');
if (feature === null || feature === void 0 ? void 0 : feature.includes('fx')) {
return bundleType + '-full';
}
return bundleType;
}
getArchitectureOptions() {
switch (this.architecture) {
case 'x86':
return { bitness: '32', arch: 'x86' };
case 'x64':
return { bitness: '64', arch: 'x86' };
case 'armv7':
return { bitness: '32', arch: 'arm' };
case 'aarch64':
return { bitness: '64', arch: 'arm' };
case 'ppc64le':
return { bitness: '64', arch: 'ppc' };
default:
throw new Error(`Architecture '${this.architecture}' is not supported. Supported architectures: ${supportedArchitecture}`);
}
}
getPlatformOption(platform = process.platform) {
switch (platform) {
case 'darwin':
return 'macos';
case 'win32':
case 'cygwin':
return 'windows';
case 'linux':
return 'linux';
case 'sunos':
return 'solaris';
default:
throw new Error(`Platform '${platform}' is not supported. Supported platforms: ${supportedPlatform}`);
}
}
convertVersionToSemver(version) {
let { buildVersion, featureVersion, interimVersion, updateVersion } = version;
const mainVersion = [featureVersion, interimVersion, updateVersion].join('.');
if (buildVersion != 0) {
return `${mainVersion}+${buildVersion}`;
}
return mainVersion;
}
}
exports.MicrosoftDistributions = MicrosoftDistributions;


/***/ }),
/* 197 */
/***/ (function(__unusedmodule, exports, __webpack_require__) {

Expand Down Expand Up @@ -55912,6 +56070,7 @@ const installer_1 = __webpack_require__(757);
const installer_2 = __webpack_require__(834);
const installer_3 = __webpack_require__(584);
const installer_4 = __webpack_require__(439);
const installer_5 = __webpack_require__(196);
var JavaDistribution;
(function (JavaDistribution) {
JavaDistribution["Adopt"] = "adopt";
Expand All @@ -55920,6 +56079,7 @@ var JavaDistribution;
JavaDistribution["Temurin"] = "temurin";
JavaDistribution["Zulu"] = "zulu";
JavaDistribution["JdkFile"] = "jdkfile";
JavaDistribution["Microsoft"] = "microsoft";
})(JavaDistribution || (JavaDistribution = {}));
function getJavaDistribution(distributionName, installerOptions, jdkFile) {
switch (distributionName) {
Expand All @@ -55934,6 +56094,8 @@ function getJavaDistribution(distributionName, installerOptions, jdkFile) {
return new installer_4.TemurinDistribution(installerOptions, installer_4.TemurinImplementation.Hotspot);
case JavaDistribution.Zulu:
return new installer_2.ZuluDistribution(installerOptions);
case JavaDistribution.Microsoft:
return new installer_5.MicrosoftDistributions(installerOptions);
default:
return null;
}
Expand Down
6 changes: 5 additions & 1 deletion src/distributions/distribution-factory.ts
Expand Up @@ -4,14 +4,16 @@ import { LocalDistribution } from './local/installer';
import { ZuluDistribution } from './zulu/installer';
import { AdoptDistribution, AdoptImplementation } from './adopt/installer';
import { TemurinDistribution, TemurinImplementation } from './temurin/installer';
import { MicrosoftDistributions } from './microsoft/installer';

enum JavaDistribution {
Adopt = 'adopt',
AdoptHotspot = 'adopt-hotspot',
AdoptOpenJ9 = 'adopt-openj9',
Temurin = 'temurin',
Zulu = 'zulu',
JdkFile = 'jdkfile'
JdkFile = 'jdkfile',
Microsoft = 'microsoft'
}

export function getJavaDistribution(
Expand All @@ -31,6 +33,8 @@ export function getJavaDistribution(
return new TemurinDistribution(installerOptions, TemurinImplementation.Hotspot);
case JavaDistribution.Zulu:
return new ZuluDistribution(installerOptions);
case JavaDistribution.Microsoft:
return new MicrosoftDistributions(installerOptions);
default:
return null;
}
Expand Down

0 comments on commit 4dd2998

Please sign in to comment.