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 support for artifact proxy repositories #434

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Expand Up @@ -13,6 +13,7 @@ The `setup-java` action provides the following functionality for GitHub Actions
- Caching dependencies managed by Gradle
- Caching dependencies managed by sbt
- [Maven Toolchains declaration](https://maven.apache.org/guides/mini/guide-using-toolchains.html) for specified JDK versions
- support for enterpries that are using a system that is proxying a repository located on a remote server.

This action allows you to work with Java and Scala projects.

Expand Down Expand Up @@ -60,6 +61,12 @@ This action allows you to work with Java and Scala projects.

- `mvn-toolchain-vendor`: Name of Maven Toolchain Vendor if the default name of `${distribution}` is not wanted.

- `remote-repository-base-url`: The base url to the solution which houses and manages all the artifacts (ex: artifactory, nexus, etc.). If `remote-repository-base-url` is specified you also need to specify the `replace-download-link-base-url`.

- `replace-download-link-base-url`: The base url of the download link, extracted from the metadata file, which must be substituted with the remote-repository-base-url.

- `download-link-context`: Because the proxying of the artifacts it is higly dependent on the admin doing it, it might be that a context is needed to be postpended to the remote-repository-base-url.

### Basic Configuration

#### Eclipse Temurin
Expand Down Expand Up @@ -231,6 +238,8 @@ In the example above multiple JDKs are installed for the same job. The result af
- [Publishing using Gradle](docs/advanced-usage.md#Publishing-using-Gradle)
- [Hosted Tool Cache](docs/advanced-usage.md#Hosted-Tool-Cache)
- [Modifying Maven Toolchains](docs/advanced-usage.md#Modifying-Maven-Toolchains)
- [Modifying Maven Toolchains](docs/advanced-usage.md#Modifying-Maven-Toolchains)
- [Fetch binaries from the artifact proxy repository](docs/advanced-usage.md#Proxy-repositores)

## License

Expand Down
299 changes: 299 additions & 0 deletions __tests__/distributors/adopt-installer.test.ts
Expand Up @@ -217,3 +217,302 @@ describe('findPackageForDownload', () => {
);
});
});

describe('getAvailableVersionsFromProxy', () => {
let spyHttpClient: jest.SpyInstance;

beforeEach(() => {
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
spyHttpClient.mockReturnValue({
statusCode: 200,
headers: {},
result: []
});
});

afterEach(() => {
jest.resetAllMocks();
jest.clearAllMocks();
jest.restoreAllMocks();
});

it.each([
[
{
version: '11',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false,
remoteRepositoryBaseUrl: 'https://test.artifactory.com'
},
AdoptImplementation.Hotspot,
'os=mac&architecture=x64&image_type=jdk&release_type=ga&jvm_impl=hotspot&page_size=20&page=0'
],
[
{
version: '11',
architecture: 'x86',
packageType: 'jdk',
checkLatest: false,
remoteRepositoryBaseUrl: 'https://test.artifactory.com'
},
AdoptImplementation.Hotspot,
'os=mac&architecture=x86&image_type=jdk&release_type=ga&jvm_impl=hotspot&page_size=20&page=0'
],
[
{
version: '11',
architecture: 'x64',
packageType: 'jre',
checkLatest: false,
remoteRepositoryBaseUrl: 'https://test.artifactory.com'
},
AdoptImplementation.Hotspot,
'os=mac&architecture=x64&image_type=jre&release_type=ga&jvm_impl=hotspot&page_size=20&page=0'
],
[
{
version: '11-ea',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false,
remoteRepositoryBaseUrl: 'https://test.artifactory.com'
},
AdoptImplementation.Hotspot,
'os=mac&architecture=x64&image_type=jdk&release_type=ea&jvm_impl=hotspot&page_size=20&page=0'
],
[
{
version: '11',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false,
remoteRepositoryBaseUrl: 'https://test.artifactory.com'
},
AdoptImplementation.OpenJ9,
'os=mac&architecture=x64&image_type=jdk&release_type=ga&jvm_impl=openj9&page_size=20&page=0'
],
[
{
version: '11',
architecture: 'x86',
packageType: 'jdk',
checkLatest: false,
remoteRepositoryBaseUrl: 'https://test.artifactory.com'
},
AdoptImplementation.OpenJ9,
'os=mac&architecture=x86&image_type=jdk&release_type=ga&jvm_impl=openj9&page_size=20&page=0'
],
[
{
version: '11',
architecture: 'x64',
packageType: 'jre',
checkLatest: false,
remoteRepositoryBaseUrl: 'https://test.artifactory.com'
},
AdoptImplementation.OpenJ9,
'os=mac&architecture=x64&image_type=jre&release_type=ga&jvm_impl=openj9&page_size=20&page=0'
],
[
{
version: '11-ea',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false,
remoteRepositoryBaseUrl: 'https://test.artifactory.com'
},
AdoptImplementation.OpenJ9,
'os=mac&architecture=x64&image_type=jdk&release_type=ea&jvm_impl=openj9&page_size=20&page=0'
]
])(
'build correct url for %s',
async (
installerOptions: JavaInstallerOptions,
impl: AdoptImplementation,
expectedParameters
) => {
const distribution = new AdoptDistribution(installerOptions, impl);
const baseUrl = 'https://test.artifactory.com/v3/assets/version/%5B1.0,100.0%5D';
const expectedUrl = `${baseUrl}?project=jdk&vendor=adoptopenjdk&heap_size=normal&sort_method=DEFAULT&sort_order=DESC&${expectedParameters}`;
distribution['getPlatformOption'] = () => 'mac';

await distribution['getAvailableVersions']();

expect(spyHttpClient.mock.calls).toHaveLength(1);
expect(spyHttpClient.mock.calls[0][0]).toBe(expectedUrl);
}
);

it('load available versions', async () => {
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
spyHttpClient
.mockReturnValueOnce({
statusCode: 200,
headers: {},
result: manifestData
})
.mockReturnValueOnce({
statusCode: 200,
headers: {},
result: manifestData
})
.mockReturnValueOnce({
statusCode: 200,
headers: {},
result: []
});

const distribution = new AdoptDistribution(
{
version: '11',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false,
remoteRepositoryBaseUrl: 'https://test.artifactory.com'
},
AdoptImplementation.Hotspot
);
const availableVersions = await distribution['getAvailableVersions']();
expect(availableVersions).not.toBeNull();
expect(availableVersions.length).toBe(manifestData.length * 2);
});

it.each([
[AdoptImplementation.Hotspot, 'jdk', 'Java_Adopt_jdk'],
[AdoptImplementation.Hotspot, 'jre', 'Java_Adopt_jre'],
[AdoptImplementation.OpenJ9, 'jdk', 'Java_Adopt-OpenJ9_jdk'],
[AdoptImplementation.OpenJ9, 'jre', 'Java_Adopt-OpenJ9_jre']
])(
'find right toolchain folder',
(impl: AdoptImplementation, packageType: string, expected: string) => {
const distribution = new AdoptDistribution(
{
version: '11',
architecture: 'x64',
packageType: packageType,
checkLatest: false,
remoteRepositoryBaseUrl: 'https://test.artifactory.com'
},
impl
);

// @ts-ignore - because it is protected
expect(distribution.toolcacheFolderName).toBe(expected);
}
);

it.each([
['amd64', 'x64'],
['arm64', 'aarch64']
])(
'defaults to os.arch(): %s mapped to distro arch: %s',
async (osArch: string, distroArch: string) => {
jest.spyOn(os, 'arch').mockReturnValue(osArch);

const installerOptions: JavaInstallerOptions = {
version: '17',
architecture: '', // to get default value
packageType: 'jdk',
checkLatest: false,
remoteRepositoryBaseUrl: 'https://test.artifactory.com'
};

const expectedParameters = `os=mac&architecture=${distroArch}&image_type=jdk&release_type=ga&jvm_impl=hotspot&page_size=20&page=0`;

const distribution = new AdoptDistribution(installerOptions, AdoptImplementation.Hotspot);
const baseUrl = 'https://test.artifactory.com/v3/assets/version/%5B1.0,100.0%5D';
const expectedUrl = `${baseUrl}?project=jdk&vendor=adoptopenjdk&heap_size=normal&sort_method=DEFAULT&sort_order=DESC&${expectedParameters}`;
distribution['getPlatformOption'] = () => 'mac';

await distribution['getAvailableVersions']();

expect(spyHttpClient.mock.calls).toHaveLength(1);
expect(spyHttpClient.mock.calls[0][0]).toBe(expectedUrl);
}
);
});

describe('findPackageForDownload', () => {
it.each([
['9', '9.0.7+10'],
['15', '15.0.2+7'],
['15.0', '15.0.2+7'],
['15.0.2', '15.0.2+7'],
['15.0.1', '15.0.1+9.1'],
['11.x', '11.0.10+9'],
['x', '15.0.2+7'],
['12', '12.0.2+10.3'], // make sure that '12.0.2+10.1', '12.0.2+10.3', '12.0.2+10.2' are sorted correctly
['12.0.2+10.1', '12.0.2+10.1'],
['15.0.1+9', '15.0.1+9'],
['15.0.1+9.1', '15.0.1+9.1']
])('version is resolved correctly %s -> %s', async (input, expected) => {
const distribution = new AdoptDistribution(
{
version: '11',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false,
remoteRepositoryBaseUrl: 'https://test.artifactory.com',
replaceDownloadLinkBaseUrl: 'https://github.com/AdoptOpenJDK',
downloadLinkContext: '/AdoptOpenJDK'
},
AdoptImplementation.Hotspot
);
distribution['getAvailableVersions'] = async () => manifestData;
const resolvedVersion = await distribution['findPackageForDownload'](input);
expect(resolvedVersion.version).toBe(expected);
expect(resolvedVersion.url).toContain('https://test.artifactory.com/AdoptOpenJDK');
});

it('version is found but binaries list is empty', async () => {
const distribution = new AdoptDistribution(
{
version: '11',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false,
remoteRepositoryBaseUrl: 'https://test.artifactory.com'
},
AdoptImplementation.Hotspot
);
distribution['getAvailableVersions'] = async () => manifestData;
await expect(distribution['findPackageForDownload']('9.0.8')).rejects.toThrowError(
/Could not find satisfied version for SemVer */
);
});

it('version is not found', async () => {
const distribution = new AdoptDistribution(
{
version: '11',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false,
remoteRepositoryBaseUrl: 'https://test.artifactory.com'
},
AdoptImplementation.Hotspot
);
distribution['getAvailableVersions'] = async () => manifestData;
await expect(distribution['findPackageForDownload']('7.x')).rejects.toThrowError(
/Could not find satisfied version for SemVer */
);
});

it('version list is empty', async () => {
const distribution = new AdoptDistribution(
{
version: '11',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false,
remoteRepositoryBaseUrl: 'https://test.artifactory.com'
},
AdoptImplementation.Hotspot
);
distribution['getAvailableVersions'] = async () => [];
await expect(distribution['findPackageForDownload']('11')).rejects.toThrowError(
/Could not find satisfied version for SemVer */
);
});
});
6 changes: 6 additions & 0 deletions __tests__/distributors/base-installer.test.ts
Expand Up @@ -15,6 +15,8 @@ import {
import os from 'os';

class EmptyJavaBase extends JavaBase {
protected remoteMetadataBaseUrl = 'MUST STAY EMPTY';
protected remoteBaseUrl = 'MUST STAY EMPTY';
constructor(installerOptions: JavaInstallerOptions) {
super('Empty', installerOptions);
}
Expand All @@ -37,6 +39,10 @@ class EmptyJavaBase extends JavaBase {
url: `some/random_url/java/${availableVersion}`
};
}

protected baseUrl(): string {
throw new Error('Method already tested in all distribution installers');
}
}

describe('findInToolcache', () => {
Expand Down
9 changes: 9 additions & 0 deletions action.yml
Expand Up @@ -68,6 +68,15 @@ inputs:
mvn-toolchain-vendor:
description: 'Name of Maven Toolchain Vendor if the default name of "${distribution}" is not wanted. See examples of supported syntax in Advanced Usage file'
required: false
remote-repository-base-url:
description: 'The base url to the solution which houses and manages all the artifacts (ex: artifactory, nexus, etc.)'
required: false
replace-download-link-base-url:
description: 'The base url of the download link, extracted from the metadata file, which must be substituted with the remote-repository-base-url. Sometimes you might need to specify the download link context to have a proper download link of the distribution.'
required: false
download-link-context:
description: 'Because the proxying of the artifacts it is higly dependent on the admin doing it, it might be that a context is needed to be postpended to the remote-repository-base-url.'
required: false
outputs:
distribution:
description: 'Distribution of Java that has been installed'
Expand Down
5 changes: 4 additions & 1 deletion dist/cleanup/index.js
Expand Up @@ -68480,7 +68480,7 @@ else {
"use strict";

Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = exports.INPUT_MVN_TOOLCHAIN_VENDOR = exports.INPUT_MVN_TOOLCHAIN_ID = exports.MVN_TOOLCHAINS_FILE = exports.MVN_SETTINGS_FILE = exports.M2_DIR = exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_JOB_STATUS = exports.INPUT_CACHE = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION_FILE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0;
exports.DOWNLOAD_LINK_CONTEXT = exports.REPLACE_DOWNLOAD_LINK_BASE_URL = exports.REMOTE_REPOSITORY_BASE_URL = exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = exports.INPUT_MVN_TOOLCHAIN_VENDOR = exports.INPUT_MVN_TOOLCHAIN_ID = exports.MVN_TOOLCHAINS_FILE = exports.MVN_SETTINGS_FILE = exports.M2_DIR = exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_JOB_STATUS = exports.INPUT_CACHE = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION_FILE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0;
exports.MACOS_JAVA_CONTENT_POSTFIX = 'Contents/Home';
exports.INPUT_JAVA_VERSION = 'java-version';
exports.INPUT_JAVA_VERSION_FILE = 'java-version-file';
Expand All @@ -68507,6 +68507,9 @@ exports.MVN_TOOLCHAINS_FILE = 'toolchains.xml';
exports.INPUT_MVN_TOOLCHAIN_ID = 'mvn-toolchain-id';
exports.INPUT_MVN_TOOLCHAIN_VENDOR = 'mvn-toolchain-vendor';
exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = ['corretto'];
exports.REMOTE_REPOSITORY_BASE_URL = 'remote-repository-base-url';
exports.REPLACE_DOWNLOAD_LINK_BASE_URL = 'replace-download-link-base-url';
exports.DOWNLOAD_LINK_CONTEXT = 'download-link-context';


/***/ }),
Expand Down