Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add versions-manifest.json for Microsoft Build of OpenJDK #383

Merged
Merged
48 changes: 16 additions & 32 deletions __tests__/distributors/microsoft-installer.test.ts
@@ -1,7 +1,12 @@
import { MicrosoftDistributions } from '../../src/distributions/microsoft/installer';
import * as tc from '@actions/tool-cache';
import data from '../../versions-manifest.json';
import * as core from '@actions/core';

describe('findPackageForDownload', () => {
let distribution: MicrosoftDistributions;
let spyGetManifestFromRepo: jest.SpyInstance;
let spyDebug: jest.SpyInstance;

beforeEach(() => {
distribution = new MicrosoftDistributions({
Expand All @@ -10,12 +15,20 @@ describe('findPackageForDownload', () => {
packageType: 'jdk',
checkLatest: false
});

spyGetManifestFromRepo = jest.spyOn(tc, 'getManifestFromRepo');
spyGetManifestFromRepo.mockImplementation(() => {
return data;
});

spyDebug = jest.spyOn(core, 'debug');
spyDebug.mockImplementation(() => {});
});

it.each([
[
'17.0.1',
'17.0.1',
'17.0.1+12.1',
'https://aka.ms/download-jdk/microsoft-jdk-17.0.1.12.1-{{OS_TYPE}}-x64.{{ARCHIVE_TYPE}}'
],
[
Expand All @@ -25,12 +38,12 @@ describe('findPackageForDownload', () => {
],
[
'16.0.x',
'16.0.2',
'16.0.2+7.1',
'https://aka.ms/download-jdk/microsoft-jdk-16.0.2.7.1-{{OS_TYPE}}-x64.{{ARCHIVE_TYPE}}'
],
[
'11.0.13',
'11.0.13',
'11.0.13+8.1',
'https://aka.ms/download-jdk/microsoft-jdk-11.0.13.8.1-{{OS_TYPE}}-x64.{{ARCHIVE_TYPE}}'
],
[
Expand Down Expand Up @@ -67,32 +80,3 @@ describe('findPackageForDownload', () => {
);
});
});

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

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

expect(actual.archive).toEqual(expectedArchive);
expect(actual.os).toEqual(expectedOs);
});

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: .+/
);
}
);
});
3 changes: 3 additions & 0 deletions action.yml
Expand Up @@ -59,6 +59,9 @@ inputs:
job-status:
description: 'Workaround to pass job status to post job step. This variable is not intended for manual setting'
default: ${{ job.status }}
token:
description: Used to pull java versions from setup-java. Since there is a default value, token is typically not supplied by the user.
default: ${{ github.token }}
outputs:
distribution:
description: 'Distribution of Java that has been installed'
Expand Down
69 changes: 13 additions & 56 deletions dist/setup/index.js
Expand Up @@ -104405,7 +104405,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.MicrosoftDistributions = void 0;
const base_installer_1 = __nccwpck_require__(9741);
const semver_1 = __importDefault(__nccwpck_require__(1383));
const util_1 = __nccwpck_require__(2629);
const core = __importStar(__nccwpck_require__(2186));
const tc = __importStar(__nccwpck_require__(7784));
Expand Down Expand Up @@ -104439,70 +104438,28 @@ class MicrosoftDistributions extends base_installer_1.JavaBase {
if (this.packageType !== 'jdk') {
throw new Error('Microsoft Build of OpenJDK provides only the `jdk` package type');
}
const availableVersionsRaw = yield this.getAvailableVersions();
const opts = this.getPlatformOption();
const availableVersions = availableVersionsRaw.map(item => ({
url: `https://aka.ms/download-jdk/microsoft-jdk-${item.version.join('.')}-${opts.os}-${this.architecture}.${opts.archive}`,
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}`);
const manifest = yield this.getAvailableVersions();
if (!manifest) {
throw new Error('Could not load manifest for Microsoft Build of OpenJDK');
}
return satisfiedVersion;
const foundRelease = yield tc.findFromManifest(range, true, manifest, this.architecture);
if (!foundRelease) {
throw new Error(`Could not find satisfied version for SemVer ${range}. ${manifest
.map(item => item.version)
.join(', ')}`);
}
return { url: foundRelease.files[0].download_url, version: foundRelease.version };
});
}
getAvailableVersions() {
return __awaiter(this, void 0, void 0, function* () {
// TODO get these dynamically!
// We will need Microsoft to add an endpoint where we can query for versions.
const jdkVersions = [
{
version: [17, 0, 3]
},
{
version: [17, 0, 1, 12, 1]
},
{
version: [16, 0, 2, 7, 1]
},
{
version: [11, 0, 15]
}
];
// M1 is only supported for Java 16 & 17
if (process.platform !== 'darwin' || this.architecture !== 'aarch64') {
jdkVersions.push({
version: [11, 0, 13, 8, 1]
});
}
return jdkVersions;
const token = core.getInput('token');
const manifest = yield tc.getManifestFromRepo('dmitry-shibanov', 'setup-java', token, 'add-json-for-microsoft-versions');
return manifest;
});
}
getPlatformOption(platform = process.platform /* for testing */) {
switch (platform) {
case 'darwin':
return { archive: 'tar.gz', os: 'macos' };
case 'win32':
return { archive: 'zip', os: 'windows' };
case 'linux':
return { archive: 'tar.gz', os: 'linux' };
default:
throw new Error(`Platform '${platform}' is not supported. Supported platforms: 'darwin', 'linux', 'win32'`);
}
}
convertVersionToSemver(version) {
const major = version.version[0];
const minor = version.version[1];
const patch = version.version[2];
return `${major}.${minor}.${patch}`;
}
}
exports.MicrosoftDistributions = MicrosoftDistributions;

Expand Down
100 changes: 29 additions & 71 deletions src/distributions/microsoft/installer.ts
@@ -1,13 +1,17 @@
import { JavaBase } from '../base-installer';
import { JavaDownloadRelease, JavaInstallerOptions, JavaInstallerResults } from '../base-models';
import semver from 'semver';
import { extractJdkFile, getDownloadArchiveExtension, isVersionSatisfies } from '../../util';
import { extractJdkFile, getDownloadArchiveExtension } from '../../util';
import * as core from '@actions/core';
import { MicrosoftVersion, PlatformOptions } from './models';
import * as tc from '@actions/tool-cache';
import fs from 'fs';
import path from 'path';

export interface IToolRelease {
version: string;
stable: boolean;
files: tc.IToolReleaseFile[];
}

export class MicrosoftDistributions extends JavaBase {
constructor(installerOptions: JavaInstallerOptions) {
super('Microsoft', installerOptions);
Expand Down Expand Up @@ -49,82 +53,36 @@ export class MicrosoftDistributions extends JavaBase {
throw new Error('Microsoft Build of OpenJDK provides only the `jdk` package type');
}

const availableVersionsRaw = await this.getAvailableVersions();

const opts = this.getPlatformOption();
const availableVersions = availableVersionsRaw.map(item => ({
url: `https://aka.ms/download-jdk/microsoft-jdk-${item.version.join('.')}-${opts.os}-${
this.architecture
}.${opts.archive}`,
version: this.convertVersionToSemver(item)
}));

const satisfiedVersion = availableVersions
.filter(item => isVersionSatisfies(range, item.version))
.sort((a, b) => -semver.compareBuild(a.version, b.version))[0];

if (!satisfiedVersion) {
const availableOptions = availableVersions.map(item => item.version).join(', ');
const availableOptionsMessage = availableOptions
? `\nAvailable versions: ${availableOptions}`
: '';
const manifest = await this.getAvailableVersions();

if (!manifest) {
throw new Error('Could not load manifest for Microsoft Build of OpenJDK');
}

const foundRelease = await tc.findFromManifest(range, true, manifest, this.architecture);

if (!foundRelease) {
throw new Error(
`Could not find satisfied version for SemVer ${range}. ${availableOptionsMessage}`
`Could not find satisfied version for SemVer ${range}. ${manifest
.map(item => item.version)
.join(', ')}`
);
}

return satisfiedVersion;
return { url: foundRelease.files[0].download_url, version: foundRelease.version };
}

private async getAvailableVersions(): Promise<MicrosoftVersion[]> {
private async getAvailableVersions(): Promise<tc.IToolRelease[] | null> {
// TODO get these dynamically!
// We will need Microsoft to add an endpoint where we can query for versions.
const jdkVersions = [
{
version: [17, 0, 3]
},
{
version: [17, 0, 1, 12, 1]
},
{
version: [16, 0, 2, 7, 1]
},
{
version: [11, 0, 15]
}
];

// M1 is only supported for Java 16 & 17
if (process.platform !== 'darwin' || this.architecture !== 'aarch64') {
jdkVersions.push({
version: [11, 0, 13, 8, 1]
});
}

return jdkVersions;
}

private getPlatformOption(
platform: NodeJS.Platform = process.platform /* for testing */
): PlatformOptions {
switch (platform) {
case 'darwin':
return { archive: 'tar.gz', os: 'macos' };
case 'win32':
return { archive: 'zip', os: 'windows' };
case 'linux':
return { archive: 'tar.gz', os: 'linux' };
default:
throw new Error(
`Platform '${platform}' is not supported. Supported platforms: 'darwin', 'linux', 'win32'`
);
}
}
const token = core.getInput('token');
const manifest = await tc.getManifestFromRepo(
'dmitry-shibanov',
'setup-java',
token,
'add-json-for-microsoft-versions'
);

private convertVersionToSemver(version: MicrosoftVersion): string {
const major = version.version[0];
const minor = version.version[1];
const patch = version.version[2];
return `${major}.${minor}.${patch}`;
return manifest;
}
}
10 changes: 0 additions & 10 deletions src/distributions/microsoft/models.ts
@@ -1,12 +1,2 @@
type OsVersions = 'linux' | 'macos' | 'windows';
type ArchiveType = 'tar.gz' | 'zip';

export interface PlatformOptions {
archive: ArchiveType;
os: OsVersions;
}

export interface MicrosoftVersion {
downloadUrl?: string;
version: Array<number>;
}
1 change: 1 addition & 0 deletions tsconfig.json
Expand Up @@ -6,6 +6,7 @@
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
"resolveJsonModule": true,
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
Expand Down