Add Amazon Corretto distribution (#312)

This commit is contained in:
Manuel 2022-04-29 12:38:36 +02:00 committed by GitHub
parent dd80852400
commit bae3140877
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 1699 additions and 9 deletions

@ -20,7 +20,7 @@ jobs:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
distribution: ['temurin', 'adopt', 'adopt-openj9', 'zulu', 'liberica', 'microsoft' ] # internally 'adopt-hotspot' is the same as 'adopt'
distribution: ['temurin', 'adopt', 'adopt-openj9', 'zulu', 'liberica', 'microsoft', 'corretto' ] # internally 'adopt-hotspot' is the same as 'adopt'
version: ['8', '11', '16']
exclude:
- distribution: microsoft
@ -141,7 +141,7 @@ jobs:
os: [macos-latest, windows-latest, ubuntu-latest]
distribution: ['temurin', 'zulu', 'liberica']
java-package: ['jre']
version: ['16.0']
version: ['17.0']
include:
- distribution: 'zulu'
java-package: jre+fx
@ -159,10 +159,10 @@ jobs:
java-package: jre+fx
version: '11'
os: ubuntu-latest
exclude:
# Eclipse Temurin currently doesn't publish JREs, only JDKs
- distribution: 'temurin'
java-package: 'jre'
- distribution: 'corretto'
java-package: jre
version: '8'
os: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v3
@ -187,7 +187,7 @@ jobs:
matrix:
# x86 is not supported on macOS
os: [windows-latest, ubuntu-latest]
distribution: ['liberica', 'zulu']
distribution: ['liberica', 'zulu', 'corretto']
version: ['11']
steps:
- name: Checkout

@ -60,6 +60,7 @@ Currently, the following distributions are supported:
| `adopt-openj9` | Adopt OpenJDK OpenJ9 | [Link](https://adoptopenjdk.net/) | [Link](https://adoptopenjdk.net/about.html) |
| `liberica` | Liberica JDK | [Link](https://bell-sw.com/) | [Link](https://bell-sw.com/liberica_eula/) |
| `microsoft` | Microsoft Build of OpenJDK | [Link](https://www.microsoft.com/openjdk) | [Link](https://docs.microsoft.com/java/openjdk/faq)
| `corretto` | Amazon Corretto Build of OpenJDK | [Link](https://aws.amazon.com/corretto/) | [Link](https://aws.amazon.com/corretto/faqs/)
**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.

1183
__tests__/data/corretto.json Normal file

File diff suppressed because it is too large Load Diff

@ -0,0 +1,152 @@
import { HttpClient } from '@actions/http-client';
import { JavaInstallerOptions } from '../../src/distributions/base-models';
import { CorrettoDistribution } from '../../src/distributions/corretto/installer';
import * as util from '../../src/util';
const manifestData = require('../data/corretto.json') as [];
describe('getAvailableVersions', () => {
let spyHttpClient: jest.SpyInstance;
let spyGetDownloadArchiveExtension: jest.SpyInstance;
beforeEach(() => {
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
spyHttpClient.mockReturnValue({
statusCode: 200,
headers: {},
result: manifestData
});
spyGetDownloadArchiveExtension = jest.spyOn(util, 'getDownloadArchiveExtension');
});
afterEach(() => {
jest.resetAllMocks();
jest.clearAllMocks();
jest.restoreAllMocks();
});
describe('getAvailableVersions', () => {
it('load available versions', async () => {
const distribution = new CorrettoDistribution({
version: '11',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
mockPlatform(distribution, 'linux');
const availableVersions = await distribution['getAvailableVersions']();
expect(availableVersions).not.toBeNull();
expect(availableVersions.length).toBe(6);
});
it.each([
[{ version: '16', architecture: 'x64', packageType: 'jdk', checkLatest: false }, 'macos', 6],
[{ version: '16', architecture: 'x86', packageType: 'jdk', checkLatest: false }, 'macos', 0],
[{ version: '16', architecture: 'x64', packageType: 'jre', checkLatest: false }, 'macos', 0],
[{ version: '16', architecture: 'x64', packageType: 'jdk', checkLatest: false }, 'linux', 6],
[
{ version: '18', architecture: 'x64', packageType: 'jdk', checkLatest: false },
'windows',
6
],
[{ version: '18', architecture: 'x64', packageType: 'jre', checkLatest: false }, 'windows', 1]
])(
'fetch expected amount of available versions for %s',
async (
installerOptions: JavaInstallerOptions,
platform: string,
expectedAmountOfAvailableVersions
) => {
const distribution = new CorrettoDistribution(installerOptions);
mockPlatform(distribution, platform);
const availableVersions = await distribution['getAvailableVersions']();
expect(availableVersions).not.toBeNull();
expect(availableVersions.length).toBe(expectedAmountOfAvailableVersions);
}
);
});
describe('findPackageForDownload', () => {
it.each([
[
'macos',
'https://corretto.aws/downloads/resources/18.0.0.37.1/amazon-corretto-18.0.0.37.1-macosx-x64.tar.gz'
],
[
'windows',
'https://corretto.aws/downloads/resources/18.0.0.37.1/amazon-corretto-18.0.0.37.1-windows-x64-jdk.zip'
],
[
'linux',
'https://corretto.aws/downloads/resources/18.0.0.37.1/amazon-corretto-18.0.0.37.1-linux-x64.tar.gz'
]
])('for os: %s', async (platform: string, expectedLink: string) => {
const version = '18';
const distribution = new CorrettoDistribution({
version,
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
mockPlatform(distribution, platform);
const availableVersion = await distribution['findPackageForDownload'](version);
expect(availableVersion).not.toBeNull();
expect(availableVersion.url).toBe(expectedLink);
});
it('with unstable version expect to throw not supported error', async () => {
const version = '18.0.1-ea';
const distribution = new CorrettoDistribution({
version,
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
mockPlatform(distribution, 'linux');
await expect(distribution['findPackageForDownload'](version)).rejects.toThrowError(
'Early access versions are not supported'
);
});
it('with non major version expect to throw not supported error', async () => {
const version = '18.0.1';
const distribution = new CorrettoDistribution({
version,
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
mockPlatform(distribution, 'linux');
await expect(distribution['findPackageForDownload'](version)).rejects.toThrowError(
'Only major versions are supported'
);
});
it('with unfound version throw could not find error', async () => {
const version = '4';
const distribution = new CorrettoDistribution({
version,
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
mockPlatform(distribution, 'linux');
await expect(distribution['findPackageForDownload'](version)).rejects.toThrowError(
"Could not find satisfied version for SemVer '4'"
);
});
});
const mockPlatform = (distributon: CorrettoDistribution, platform: string) => {
distributon['getPlatformOption'] = () => platform;
const mockedExtension = platform === 'windows' ? 'zip' : 'tar.gz';
spyGetDownloadArchiveExtension.mockReturnValue(mockedExtension);
};
});

170
dist/setup/index.js vendored

@ -101135,6 +101135,172 @@ class JavaBase {
exports.JavaBase = JavaBase;
/***/ }),
/***/ 4750:
/***/ (function(__unused_webpack_module, exports, __nccwpck_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.CorrettoDistribution = void 0;
const core = __importStar(__nccwpck_require__(2186));
const tc = __importStar(__nccwpck_require__(7784));
const fs_1 = __importDefault(__nccwpck_require__(7147));
const path_1 = __importDefault(__nccwpck_require__(1017));
const util_1 = __nccwpck_require__(2629);
const base_installer_1 = __nccwpck_require__(9741);
class CorrettoDistribution extends base_installer_1.JavaBase {
constructor(installerOptions) {
super('Corretto', 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 extractedJavaPath = yield util_1.extractJdkFile(javaArchivePath, util_1.getDownloadArchiveExtension());
const archiveName = fs_1.default.readdirSync(extractedJavaPath)[0];
const archivePath = path_1.default.join(extractedJavaPath, archiveName);
const version = this.getToolcacheVersionName(javaRelease.version);
const javaPath = yield tc.cacheDir(archivePath, this.toolcacheFolderName, version, this.architecture);
return { version: javaRelease.version, path: javaPath };
});
}
findPackageForDownload(version) {
return __awaiter(this, void 0, void 0, function* () {
if (!this.stable) {
throw new Error('Early access versions are not supported');
}
if (version.includes('.')) {
throw new Error('Only major versions are supported');
}
const availableVersions = yield this.getAvailableVersions();
const matchingVersions = availableVersions
.filter(item => item.version == version)
.map(item => {
return {
version: item.correttoVersion,
url: item.downloadLink
};
});
const resolvedVersion = matchingVersions.length > 0 ? matchingVersions[0] : null;
if (!resolvedVersion) {
const availableOptions = availableVersions.map(item => item.version).join(', ');
const availableOptionsMessage = availableOptions
? `\nAvailable versions: ${availableOptions}`
: '';
throw new Error(`Could not find satisfied version for SemVer '${version}'. ${availableOptionsMessage}`);
}
return resolvedVersion;
});
}
getAvailableVersions() {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const platform = this.getPlatformOption();
const arch = this.architecture;
const imageType = this.packageType;
console.time('coretto-retrieve-available-versions');
const availableVersionsUrl = 'https://corretto.github.io/corretto-downloads/latest_links/indexmap_with_checksum.json';
const fetchCurrentVersions = yield this.http.getJson(availableVersionsUrl);
const fetchedCurrentVersions = fetchCurrentVersions.result;
if (!fetchedCurrentVersions) {
throw Error(`Could not fetch latest corretto versions from ${availableVersionsUrl}`);
}
const eligbleVersions = (_b = (_a = fetchedCurrentVersions === null || fetchedCurrentVersions === void 0 ? void 0 : fetchedCurrentVersions[platform]) === null || _a === void 0 ? void 0 : _a[arch]) === null || _b === void 0 ? void 0 : _b[imageType];
const availableVersions = this.getAvailableVersionsForPlatform(eligbleVersions);
if (core.isDebug()) {
this.printAvailableVersions(availableVersions);
}
return availableVersions;
});
}
getAvailableVersionsForPlatform(eligbleVersions) {
const availableVersions = [];
for (const version in eligbleVersions) {
const availableVersion = eligbleVersions[version];
for (const fileType in availableVersion) {
const skipNonExtractableBinaries = fileType != util_1.getDownloadArchiveExtension();
if (skipNonExtractableBinaries) {
continue;
}
const availableVersionDetails = availableVersion[fileType];
const correttoVersion = this.getCorettoVersion(availableVersionDetails.resource);
availableVersions.push({
checksum: availableVersionDetails.checksum,
checksum_sha256: availableVersionDetails.checksum_sha256,
fileType,
resource: availableVersionDetails.resource,
downloadLink: `https://corretto.aws${availableVersionDetails.resource}`,
version: version,
correttoVersion
});
}
}
return availableVersions;
}
printAvailableVersions(availableVersions) {
core.startGroup('Print information about available versions');
console.timeEnd('coretto-retrieve-available-versions');
console.log(`Available versions: [${availableVersions.length}]`);
console.log(availableVersions.map(item => `${item.version}: ${item.correttoVersion}`).join(', '));
core.endGroup();
}
getPlatformOption() {
// Coretto has its own platform names so we need to map them
switch (process.platform) {
case 'darwin':
return 'macos';
case 'win32':
return 'windows';
default:
return process.platform;
}
}
getCorettoVersion(resource) {
const regex = /(\d+.+)\//;
const match = regex.exec(resource);
if (match === null) {
throw Error(`Could not parse corretto version from ${resource}`);
}
return match[1];
}
}
exports.CorrettoDistribution = CorrettoDistribution;
/***/ }),
/***/ 924:
@ -101150,6 +101316,7 @@ const installer_3 = __nccwpck_require__(8766);
const installer_4 = __nccwpck_require__(8579);
const installer_5 = __nccwpck_require__(883);
const installer_6 = __nccwpck_require__(3613);
const installer_7 = __nccwpck_require__(4750);
var JavaDistribution;
(function (JavaDistribution) {
JavaDistribution["Adopt"] = "adopt";
@ -101160,6 +101327,7 @@ var JavaDistribution;
JavaDistribution["Liberica"] = "liberica";
JavaDistribution["JdkFile"] = "jdkfile";
JavaDistribution["Microsoft"] = "microsoft";
JavaDistribution["Corretto"] = "corretto";
})(JavaDistribution || (JavaDistribution = {}));
function getJavaDistribution(distributionName, installerOptions, jdkFile) {
switch (distributionName) {
@ -101178,6 +101346,8 @@ function getJavaDistribution(distributionName, installerOptions, jdkFile) {
return new installer_5.LibericaDistributions(installerOptions);
case JavaDistribution.Microsoft:
return new installer_6.MicrosoftDistributions(installerOptions);
case JavaDistribution.Corretto:
return new installer_7.CorrettoDistribution(installerOptions);
default:
return null;
}

@ -4,7 +4,7 @@ import * as fs from 'fs';
import semver from 'semver';
import path from 'path';
import * as httpm from '@actions/http-client';
import { getToolcachePath, getVersionFromToolcachePath, isVersionSatisfies } from '../util';
import { getToolcachePath, isVersionSatisfies } from '../util';
import { JavaDownloadRelease, JavaInstallerOptions, JavaInstallerResults } from './base-models';
import { MACOS_JAVA_CONTENT_POSTFIX } from '../constants';

@ -0,0 +1,155 @@
import * as core from '@actions/core';
import * as tc from '@actions/tool-cache';
import fs from 'fs';
import path from 'path';
import { extractJdkFile, getDownloadArchiveExtension } from '../../util';
import { JavaBase } from '../base-installer';
import { JavaDownloadRelease, JavaInstallerOptions, JavaInstallerResults } from '../base-models';
import { ICorrettoAllAvailableVersions, ICorettoAvailableVersions } from './models';
export class CorrettoDistribution extends JavaBase {
constructor(installerOptions: JavaInstallerOptions) {
super('Corretto', installerOptions);
}
protected async downloadTool(javaRelease: JavaDownloadRelease): Promise<JavaInstallerResults> {
core.info(
`Downloading Java ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...`
);
const javaArchivePath = await tc.downloadTool(javaRelease.url);
core.info(`Extracting Java archive...`);
const extractedJavaPath = await extractJdkFile(javaArchivePath, getDownloadArchiveExtension());
const archiveName = fs.readdirSync(extractedJavaPath)[0];
const archivePath = path.join(extractedJavaPath, archiveName);
const version = this.getToolcacheVersionName(javaRelease.version);
const javaPath = await tc.cacheDir(
archivePath,
this.toolcacheFolderName,
version,
this.architecture
);
return { version: javaRelease.version, path: javaPath };
}
protected async findPackageForDownload(version: string): Promise<JavaDownloadRelease> {
if (!this.stable) {
throw new Error('Early access versions are not supported');
}
if (version.includes('.')) {
throw new Error('Only major versions are supported');
}
const availableVersions = await this.getAvailableVersions();
const matchingVersions = availableVersions
.filter(item => item.version == version)
.map(item => {
return {
version: item.correttoVersion,
url: item.downloadLink
} as JavaDownloadRelease;
});
const resolvedVersion = matchingVersions.length > 0 ? matchingVersions[0] : null;
if (!resolvedVersion) {
const availableOptions = availableVersions.map(item => item.version).join(', ');
const availableOptionsMessage = availableOptions
? `\nAvailable versions: ${availableOptions}`
: '';
throw new Error(
`Could not find satisfied version for SemVer '${version}'. ${availableOptionsMessage}`
);
}
return resolvedVersion;
}
private async getAvailableVersions(): Promise<ICorettoAvailableVersions[]> {
const platform = this.getPlatformOption();
const arch = this.architecture;
const imageType = this.packageType;
console.time('coretto-retrieve-available-versions');
const availableVersionsUrl =
'https://corretto.github.io/corretto-downloads/latest_links/indexmap_with_checksum.json';
const fetchCurrentVersions = await this.http.getJson<ICorrettoAllAvailableVersions>(
availableVersionsUrl
);
const fetchedCurrentVersions = fetchCurrentVersions.result;
if (!fetchedCurrentVersions) {
throw Error(`Could not fetch latest corretto versions from ${availableVersionsUrl}`);
}
const eligbleVersions = fetchedCurrentVersions?.[platform]?.[arch]?.[imageType];
const availableVersions = this.getAvailableVersionsForPlatform(eligbleVersions);
if (core.isDebug()) {
this.printAvailableVersions(availableVersions);
}
return availableVersions;
}
private getAvailableVersionsForPlatform(
eligbleVersions: ICorrettoAllAvailableVersions['os']['arch']['imageType'] | undefined
): ICorettoAvailableVersions[] {
const availableVersions: ICorettoAvailableVersions[] = [];
for (const version in eligbleVersions) {
const availableVersion = eligbleVersions[version];
for (const fileType in availableVersion) {
const skipNonExtractableBinaries = fileType != getDownloadArchiveExtension();
if (skipNonExtractableBinaries) {
continue;
}
const availableVersionDetails = availableVersion[fileType];
const correttoVersion = this.getCorettoVersion(availableVersionDetails.resource);
availableVersions.push({
checksum: availableVersionDetails.checksum,
checksum_sha256: availableVersionDetails.checksum_sha256,
fileType,
resource: availableVersionDetails.resource,
downloadLink: `https://corretto.aws${availableVersionDetails.resource}`,
version: version,
correttoVersion
});
}
}
return availableVersions;
}
private printAvailableVersions(availableVersions: ICorettoAvailableVersions[]) {
core.startGroup('Print information about available versions');
console.timeEnd('coretto-retrieve-available-versions');
console.log(`Available versions: [${availableVersions.length}]`);
console.log(
availableVersions.map(item => `${item.version}: ${item.correttoVersion}`).join(', ')
);
core.endGroup();
}
private getPlatformOption(): string {
// Coretto has its own platform names so we need to map them
switch (process.platform) {
case 'darwin':
return 'macos';
case 'win32':
return 'windows';
default:
return process.platform;
}
}
private getCorettoVersion(resource: string): string {
const regex = /(\d+.+)\//;
const match = regex.exec(resource);
if (match === null) {
throw Error(`Could not parse corretto version from ${resource}`);
}
return match[1];
}
}

@ -0,0 +1,25 @@
export interface ICorrettoAllAvailableVersions {
[os: string]: {
[arch: string]: {
[distributionType: string]: {
[version: string]: {
[fileType: string]: {
checksum: string;
checksum_sha256: string;
resource: string;
};
};
};
};
};
}
export interface ICorettoAvailableVersions {
version: string;
fileType: string;
checksum: string;
checksum_sha256: string;
resource: string;
downloadLink: string;
correttoVersion: string;
}

@ -6,6 +6,7 @@ import { AdoptDistribution, AdoptImplementation } from './adopt/installer';
import { TemurinDistribution, TemurinImplementation } from './temurin/installer';
import { LibericaDistributions } from './liberica/installer';
import { MicrosoftDistributions } from './microsoft/installer';
import { CorrettoDistribution } from './corretto/installer';
enum JavaDistribution {
Adopt = 'adopt',
@ -15,7 +16,8 @@ enum JavaDistribution {
Zulu = 'zulu',
Liberica = 'liberica',
JdkFile = 'jdkfile',
Microsoft = 'microsoft'
Microsoft = 'microsoft',
Corretto = 'corretto'
}
export function getJavaDistribution(
@ -39,6 +41,8 @@ export function getJavaDistribution(
return new LibericaDistributions(installerOptions);
case JavaDistribution.Microsoft:
return new MicrosoftDistributions(installerOptions);
case JavaDistribution.Corretto:
return new CorrettoDistribution(installerOptions);
default:
return null;
}