mirror of
https://github.com/actions/setup-java.git
synced 2026-07-02 02:11:46 +00:00
Compare commits
17 Commits
f9a57c332c
...
651449a002
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
651449a002 | ||
|
|
b24df5bba5 | ||
|
|
43120bc3c3 | ||
|
|
ad9d6a6320 | ||
|
|
039af37997 | ||
|
|
1756ab6acd | ||
|
|
662bb59f48 | ||
|
|
1071fc12d6 | ||
|
|
576b821f29 | ||
|
|
307d3a25a0 | ||
|
|
491467dc7f | ||
|
|
1d68cf3e34 | ||
|
|
2194b50b27 | ||
|
|
b28c8117d5 | ||
|
|
b622de1dfa | ||
|
|
c76542e033 | ||
|
|
0756542bc5 |
26
.github/workflows/e2e-versions.yml
vendored
26
.github/workflows/e2e-versions.yml
vendored
@ -86,6 +86,32 @@ jobs:
|
|||||||
run: bash __tests__/verify-java.sh "${{ matrix.version }}" "${{ steps.setup-java.outputs.path }}"
|
run: bash __tests__/verify-java.sh "${{ matrix.version }}" "${{ steps.setup-java.outputs.path }}"
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
|
setup-java-alpine-linux:
|
||||||
|
name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-x64) - alpine-linux - ${{ matrix.os }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
container:
|
||||||
|
image: alpine:latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest]
|
||||||
|
distribution: ['temurin', 'sapmachine']
|
||||||
|
version: ['21', '17']
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
- name: Install bash
|
||||||
|
run: apk add --no-cache bash
|
||||||
|
- name: setup-java
|
||||||
|
uses: ./
|
||||||
|
id: setup-java
|
||||||
|
with:
|
||||||
|
java-version: ${{ matrix.version }}
|
||||||
|
distribution: ${{ matrix.distribution }}
|
||||||
|
- name: Verify Java
|
||||||
|
run: bash __tests__/verify-java.sh "${{ matrix.version }}" "${{ steps.setup-java.outputs.path }}"
|
||||||
|
shell: bash
|
||||||
|
|
||||||
setup-java-major-minor-versions:
|
setup-java-major-minor-versions:
|
||||||
name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-x64) - ${{ matrix.os }}
|
name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-x64) - ${{ matrix.os }}
|
||||||
needs: setup-java-major-versions
|
needs: setup-java-major-versions
|
||||||
|
|||||||
@ -14,3 +14,4 @@ allowed:
|
|||||||
reviewed:
|
reviewed:
|
||||||
npm:
|
npm:
|
||||||
- "@actions/http-client" # MIT (license text present), but detected as "other"
|
- "@actions/http-client" # MIT (license text present), but detected as "other"
|
||||||
|
- "argparse" # Python Software Foundation License (PSF), but detected as "other"
|
||||||
BIN
.licenses/npm/@actions/cache.dep.yml
generated
BIN
.licenses/npm/@actions/cache.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/core-1.11.1.dep.yml
generated
BIN
.licenses/npm/@actions/core-1.11.1.dep.yml
generated
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/@actions/exec-1.1.1.dep.yml
generated
BIN
.licenses/npm/@actions/exec-1.1.1.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/glob.dep.yml
generated
BIN
.licenses/npm/@actions/glob.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/http-client-2.2.3.dep.yml
generated
BIN
.licenses/npm/@actions/http-client-2.2.3.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/io-1.1.3.dep.yml
generated
BIN
.licenses/npm/@actions/io-1.1.3.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/tool-cache.dep.yml
generated
BIN
.licenses/npm/@actions/tool-cache.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@fastify/busboy.dep.yml
generated
BIN
.licenses/npm/@fastify/busboy.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@nodable/entities.dep.yml
generated
Normal file
BIN
.licenses/npm/@nodable/entities.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@oozcitak/dom.dep.yml
generated
BIN
.licenses/npm/@oozcitak/dom.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@oozcitak/infra.dep.yml
generated
BIN
.licenses/npm/@oozcitak/infra.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@oozcitak/url.dep.yml
generated
BIN
.licenses/npm/@oozcitak/url.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@oozcitak/util.dep.yml
generated
BIN
.licenses/npm/@oozcitak/util.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@types/node.dep.yml
generated
BIN
.licenses/npm/@types/node.dep.yml
generated
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/argparse.dep.yml
generated
BIN
.licenses/npm/argparse.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/brace-expansion.dep.yml
generated
BIN
.licenses/npm/brace-expansion.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/esprima.dep.yml
generated
BIN
.licenses/npm/esprima.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/fast-xml-builder.dep.yml
generated
BIN
.licenses/npm/fast-xml-builder.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/fast-xml-parser.dep.yml
generated
BIN
.licenses/npm/fast-xml-parser.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/js-yaml.dep.yml
generated
BIN
.licenses/npm/js-yaml.dep.yml
generated
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/sprintf-js.dep.yml
generated
BIN
.licenses/npm/sprintf-js.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/strnum.dep.yml
generated
BIN
.licenses/npm/strnum.dep.yml
generated
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/uuid.dep.yml
generated
BIN
.licenses/npm/uuid.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/xml-naming.dep.yml
generated
Normal file
BIN
.licenses/npm/xml-naming.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/xmlbuilder2.dep.yml
generated
BIN
.licenses/npm/xmlbuilder2.dep.yml
generated
Binary file not shown.
14
README.md
14
README.md
@ -55,7 +55,13 @@ For information about the latest releases, recent updates, and newly supported d
|
|||||||
#### Maven options
|
#### Maven options
|
||||||
The action has a bunch of inputs to generate maven's [settings.xml](https://maven.apache.org/settings.html) on the fly and pass the values to Apache Maven GPG Plugin as well as Apache Maven Toolchains. See [advanced usage](docs/advanced-usage.md) for more.
|
The action has a bunch of inputs to generate maven's [settings.xml](https://maven.apache.org/settings.html) on the fly and pass the values to Apache Maven GPG Plugin as well as Apache Maven Toolchains. See [advanced usage](docs/advanced-usage.md) for more.
|
||||||
|
|
||||||
- `overwrite-settings`: By default action overwrites the settings.xml. In order to skip generation of file if it exists, set this to `false`.
|
- `overwrite-settings`: By default action overwrites the settings.xml and adds a toolchain entry to toolchains.xml. In order to skip generation of settings.xml and skip adding a toolchain entry to toolchains.xml if the according file exists, set this to `false`.
|
||||||
|
|
||||||
|
- `update-env-javahome`: By default action updates `env.JAVA_HOME` with the path of java installed. In order to skip update of JAVA_HOME, set this to `false`. The creation of the env variable JAVA_HOME_{{ MAJOR_VERSION }}_{{ ARCHITECTURE }} is NOT affected by this item. That will be created for any setup.
|
||||||
|
|
||||||
|
- `update-env-path`: By default action adds `<java_install_dir>/bin` to `env.PATH`. In order to skip this, set this to `false`.
|
||||||
|
|
||||||
|
- `update-toolchains-only`: If set to true, then `overwrite-settings`, `update-env-javahome` and `update-env-path` are propagated to `false` if the specific one is not explicitly configured to `true`. Only a toolchain entry will be added to toolchains.xml. Default is `false`.
|
||||||
|
|
||||||
- `server-id`: ID of the distributionManagement repository in the pom.xml file. Default is `github`.
|
- `server-id`: ID of the distributionManagement repository in the pom.xml file. Default is `github`.
|
||||||
|
|
||||||
@ -129,6 +135,10 @@ Currently, the following distributions are supported:
|
|||||||
|
|
||||||
**NOTE:** To comply with the GraalVM Free Terms and Conditions (GFTC) license, it is recommended to use GraalVM JDK 17 version 17.0.12, as this is the only version of GraalVM JDK 17 available under the GFTC license. Additionally, it is encouraged to consider upgrading to GraalVM JDK 21, which offers the latest features and improvements.
|
**NOTE:** To comply with the GraalVM Free Terms and Conditions (GFTC) license, it is recommended to use GraalVM JDK 17 version 17.0.12, as this is the only version of GraalVM JDK 17 available under the GFTC license. Additionally, it is encouraged to consider upgrading to GraalVM JDK 21, which offers the latest features and improvements.
|
||||||
|
|
||||||
|
**NOTE:** Oracle JDK 17 licensing varies by patch level. As shown on the [JDK 17 Archive](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) (versions up to 17.0.12 are under the [NFTC](https://www.oracle.com/downloads/licenses/no-fee-license.html) license) and the [JDK 17.0.13+ Archive](https://www.oracle.com/java/technologies/javase/jdk17-0-13-later-archive-downloads.html) (versions 17.0.13 and later are under the [OTN](https://www.oracle.com/downloads/licenses/javase-license1.html) license). To stay on the free NFTC license, use `distribution: 'oracle'` with `java-version: '17.0.12'` (or earlier) instead of the floating `'17'`. Alternatively, upgrade to Oracle JDK 21+, which remains under the NFTC license.
|
||||||
|
|
||||||
|
**NOTE:** On Ubuntu runners, commands executed via `sudo` do not inherit the `JAVA_HOME` and `PATH` set by `setup-java` and will fall back to the runner image's system-default JDK.
|
||||||
|
|
||||||
### Caching packages dependencies
|
### Caching packages dependencies
|
||||||
The action has a built-in functionality for caching and restoring dependencies. It uses [toolkit/cache](https://github.com/actions/toolkit/tree/main/packages/cache) under hood for caching dependencies but requires less configuration settings. Supported package managers are gradle, maven and sbt. The format of the used cache key is `setup-java-${{ platform }}-${{ packageManager }}-${{ fileHash }}`, where the hash is based on the following files:
|
The action has a built-in functionality for caching and restoring dependencies. It uses [toolkit/cache](https://github.com/actions/toolkit/tree/main/packages/cache) under hood for caching dependencies but requires less configuration settings. Supported package managers are gradle, maven and sbt. The format of the used cache key is `setup-java-${{ platform }}-${{ packageManager }}-${{ fileHash }}`, where the hash is based on the following files:
|
||||||
|
|
||||||
@ -262,6 +272,8 @@ All configured Java versions are added to the PATH. The last one added to the PA
|
|||||||
15
|
15
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**NOTE:** An alternative option is to use multiple setup-java steps. In this case the behavior can be controlled more granular by making use of the input items `overwrite-settings`, `update-env-javahome`, `update-env-path` and `update-toolchains-only`.
|
||||||
|
|
||||||
### Using Maven Toolchains
|
### Using Maven Toolchains
|
||||||
In the example above multiple JDKs are installed for the same job. The result after the last JDK is installed is a Maven Toolchains declaration containing references to all three JDKs. The values for `id`, `version`, and `vendor` of the individual Toolchain entries are the given input values for `distribution` and `java-version` (`vendor` being the combination of `${distribution}_${java-version}`) by default.
|
In the example above multiple JDKs are installed for the same job. The result after the last JDK is installed is a Maven Toolchains declaration containing references to all three JDKs. The values for `id`, `version`, and `vendor` of the individual Toolchain entries are the given input values for `distribution` and `java-version` (`vendor` being the combination of `${distribution}_${java-version}`) by default.
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@ describe('dependency cache', () => {
|
|||||||
let spyWarning: jest.SpyInstance<void, Parameters<typeof core.warning>>;
|
let spyWarning: jest.SpyInstance<void, Parameters<typeof core.warning>>;
|
||||||
let spyDebug: jest.SpyInstance<void, Parameters<typeof core.debug>>;
|
let spyDebug: jest.SpyInstance<void, Parameters<typeof core.debug>>;
|
||||||
let spySaveState: jest.SpyInstance<void, Parameters<typeof core.saveState>>;
|
let spySaveState: jest.SpyInstance<void, Parameters<typeof core.saveState>>;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
workspace = mkdtempSync(join(tmpdir(), 'setup-java-cache-'));
|
workspace = mkdtempSync(join(tmpdir(), 'setup-java-cache-'));
|
||||||
@ -51,6 +52,10 @@ describe('dependency cache', () => {
|
|||||||
|
|
||||||
spySaveState = jest.spyOn(core, 'saveState');
|
spySaveState = jest.spyOn(core, 'saveState');
|
||||||
spySaveState.mockImplementation(() => null);
|
spySaveState.mockImplementation(() => null);
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -58,6 +63,10 @@ describe('dependency cache', () => {
|
|||||||
process.env['GITHUB_WORKSPACE'] = ORIGINAL_GITHUB_WORKSPACE;
|
process.env['GITHUB_WORKSPACE'] = ORIGINAL_GITHUB_WORKSPACE;
|
||||||
process.env['RUNNER_OS'] = ORIGINAL_RUNNER_OS;
|
process.env['RUNNER_OS'] = ORIGINAL_RUNNER_OS;
|
||||||
resetState();
|
resetState();
|
||||||
|
|
||||||
|
jest.resetAllMocks();
|
||||||
|
jest.clearAllMocks();
|
||||||
|
jest.restoreAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('restore', () => {
|
describe('restore', () => {
|
||||||
|
|||||||
@ -11,19 +11,32 @@ describe('cleanup', () => {
|
|||||||
Parameters<typeof cache.saveCache>
|
Parameters<typeof cache.saveCache>
|
||||||
>;
|
>;
|
||||||
let spyJobStatusSuccess: jest.SpyInstance;
|
let spyJobStatusSuccess: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyWarning = jest.spyOn(core, 'warning');
|
spyWarning = jest.spyOn(core, 'warning');
|
||||||
spyWarning.mockImplementation(() => null);
|
spyWarning.mockImplementation(() => null);
|
||||||
|
|
||||||
spyInfo = jest.spyOn(core, 'info');
|
spyInfo = jest.spyOn(core, 'info');
|
||||||
spyInfo.mockImplementation(() => null);
|
spyInfo.mockImplementation(() => null);
|
||||||
|
|
||||||
spyCacheSave = jest.spyOn(cache, 'saveCache');
|
spyCacheSave = jest.spyOn(cache, 'saveCache');
|
||||||
|
|
||||||
spyJobStatusSuccess = jest.spyOn(util, 'isJobStatusSuccess');
|
spyJobStatusSuccess = jest.spyOn(util, 'isJobStatusSuccess');
|
||||||
spyJobStatusSuccess.mockReturnValue(true);
|
spyJobStatusSuccess.mockReturnValue(true);
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
|
|
||||||
createStateForSuccessfulRestore();
|
createStateForSuccessfulRestore();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
resetState();
|
resetState();
|
||||||
|
jest.resetAllMocks();
|
||||||
|
jest.clearAllMocks();
|
||||||
|
jest.restoreAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not fail nor warn even when the save process throws a ReserveCacheError', async () => {
|
it('does not fail nor warn even when the save process throws a ReserveCacheError', async () => {
|
||||||
|
|||||||
@ -4,14 +4,18 @@ import {
|
|||||||
AdoptDistribution,
|
AdoptDistribution,
|
||||||
AdoptImplementation
|
AdoptImplementation
|
||||||
} from '../../src/distributions/adopt/installer';
|
} from '../../src/distributions/adopt/installer';
|
||||||
|
import {TemurinDistribution} from '../../src/distributions/temurin/installer';
|
||||||
import {JavaInstallerOptions} from '../../src/distributions/base-models';
|
import {JavaInstallerOptions} from '../../src/distributions/base-models';
|
||||||
|
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
|
||||||
import manifestData from '../data/adopt.json';
|
import manifestData from '../data/adopt.json';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
describe('getAvailableVersions', () => {
|
describe('getAvailableVersions', () => {
|
||||||
let spyHttpClient: jest.SpyInstance;
|
let spyHttpClient: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
let spyCoreWarning: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
@ -20,6 +24,12 @@ describe('getAvailableVersions', () => {
|
|||||||
headers: {},
|
headers: {},
|
||||||
result: []
|
result: []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
|
spyCoreWarning = jest.spyOn(core, 'warning');
|
||||||
|
spyCoreWarning.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -130,22 +140,19 @@ describe('getAvailableVersions', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
it('load available versions', async () => {
|
it('load available versions', async () => {
|
||||||
|
const nextPageUrl =
|
||||||
|
'https://api.adoptopenjdk.net/v3/assets/version/%5B1.0,100.0%5D?page=1&page_size=20';
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
spyHttpClient
|
spyHttpClient
|
||||||
.mockReturnValueOnce({
|
.mockReturnValueOnce({
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
headers: {},
|
headers: {link: `<${nextPageUrl}>; rel="next"`},
|
||||||
result: manifestData as any
|
result: manifestData as any
|
||||||
})
|
})
|
||||||
.mockReturnValueOnce({
|
.mockReturnValueOnce({
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
headers: {},
|
headers: {},
|
||||||
result: manifestData as any
|
result: manifestData as any
|
||||||
})
|
|
||||||
.mockReturnValueOnce({
|
|
||||||
statusCode: 200,
|
|
||||||
headers: {},
|
|
||||||
result: []
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const distribution = new AdoptDistribution(
|
const distribution = new AdoptDistribution(
|
||||||
@ -160,6 +167,34 @@ describe('getAvailableVersions', () => {
|
|||||||
const availableVersions = await distribution['getAvailableVersions']();
|
const availableVersions = await distribution['getAvailableVersions']();
|
||||||
expect(availableVersions).not.toBeNull();
|
expect(availableVersions).not.toBeNull();
|
||||||
expect(availableVersions.length).toBe(manifestData.length * 2);
|
expect(availableVersions.length).toBe(manifestData.length * 2);
|
||||||
|
expect(spyHttpClient).toHaveBeenNthCalledWith(2, nextPageUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('stops pagination after 1000 pages as a safeguard', async () => {
|
||||||
|
const nextPageUrl =
|
||||||
|
'https://api.adoptopenjdk.net/v3/assets/version/%5B1.0,100.0%5D?page=2&page_size=20';
|
||||||
|
spyHttpClient.mockReturnValue({
|
||||||
|
statusCode: 200,
|
||||||
|
headers: {link: `<${nextPageUrl}>; rel="next"`},
|
||||||
|
result: [{version_data: {semver: '17.0.1'}, binaries: []}] as any
|
||||||
|
});
|
||||||
|
|
||||||
|
const distribution = new AdoptDistribution(
|
||||||
|
{
|
||||||
|
version: '11',
|
||||||
|
architecture: 'x64',
|
||||||
|
packageType: 'jdk',
|
||||||
|
checkLatest: false
|
||||||
|
},
|
||||||
|
AdoptImplementation.Hotspot
|
||||||
|
);
|
||||||
|
|
||||||
|
await distribution['getAvailableVersions']();
|
||||||
|
|
||||||
|
expect(spyHttpClient).toHaveBeenCalledTimes(1000);
|
||||||
|
expect(spyCoreWarning).toHaveBeenCalledWith(
|
||||||
|
expect.stringContaining('Reached pagination safeguard limit (1000 pages)')
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
@ -222,6 +257,38 @@ describe('getAvailableVersions', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('findPackageForDownload', () => {
|
describe('findPackageForDownload', () => {
|
||||||
|
it('returns Temurin result and does not query Adopt API when Temurin succeeds', async () => {
|
||||||
|
const temurinRelease = {
|
||||||
|
version: '11.0.31+11',
|
||||||
|
url: 'https://example.test/temurin-11.tar.gz'
|
||||||
|
};
|
||||||
|
const temurinFindPackageForDownload = jest
|
||||||
|
.fn()
|
||||||
|
.mockResolvedValue(temurinRelease);
|
||||||
|
const temurinDistribution = {
|
||||||
|
findPackageForDownload: temurinFindPackageForDownload
|
||||||
|
} as unknown as TemurinDistribution;
|
||||||
|
|
||||||
|
const distribution = new AdoptDistribution(
|
||||||
|
{
|
||||||
|
version: '11',
|
||||||
|
architecture: 'x64',
|
||||||
|
packageType: 'jdk',
|
||||||
|
checkLatest: false
|
||||||
|
},
|
||||||
|
AdoptImplementation.Hotspot,
|
||||||
|
temurinDistribution
|
||||||
|
);
|
||||||
|
const adoptLookupSpy = jest.fn();
|
||||||
|
distribution['getAvailableVersions'] = adoptLookupSpy;
|
||||||
|
|
||||||
|
const resolvedVersion = await distribution['findPackageForDownload']('11');
|
||||||
|
|
||||||
|
expect(resolvedVersion).toEqual(temurinRelease);
|
||||||
|
expect(temurinFindPackageForDownload).toHaveBeenCalledWith('11');
|
||||||
|
expect(adoptLookupSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
['9', '9.0.7+10'],
|
['9', '9.0.7+10'],
|
||||||
['15', '15.0.2+7'],
|
['15', '15.0.2+7'],
|
||||||
@ -244,6 +311,11 @@ describe('findPackageForDownload', () => {
|
|||||||
},
|
},
|
||||||
AdoptImplementation.Hotspot
|
AdoptImplementation.Hotspot
|
||||||
);
|
);
|
||||||
|
// Mock Temurin to fail so fallback to AdoptOpenJDK is tested
|
||||||
|
distribution['temurinDistribution']!['findPackageForDownload'] =
|
||||||
|
async () => {
|
||||||
|
throw new Error('No matching version found for SemVer');
|
||||||
|
};
|
||||||
distribution['getAvailableVersions'] = async () => manifestData as any;
|
distribution['getAvailableVersions'] = async () => manifestData as any;
|
||||||
const resolvedVersion = await distribution['findPackageForDownload'](input);
|
const resolvedVersion = await distribution['findPackageForDownload'](input);
|
||||||
expect(resolvedVersion.version).toBe(expected);
|
expect(resolvedVersion.version).toBe(expected);
|
||||||
@ -259,10 +331,15 @@ describe('findPackageForDownload', () => {
|
|||||||
},
|
},
|
||||||
AdoptImplementation.Hotspot
|
AdoptImplementation.Hotspot
|
||||||
);
|
);
|
||||||
|
// Mock Temurin to fail so fallback to AdoptOpenJDK is tested
|
||||||
|
distribution['temurinDistribution']!['findPackageForDownload'] =
|
||||||
|
async () => {
|
||||||
|
throw new Error('No matching version found for SemVer');
|
||||||
|
};
|
||||||
distribution['getAvailableVersions'] = async () => manifestData as any;
|
distribution['getAvailableVersions'] = async () => manifestData as any;
|
||||||
await expect(
|
await expect(
|
||||||
distribution['findPackageForDownload']('9.0.8')
|
distribution['findPackageForDownload']('9.0.8')
|
||||||
).rejects.toThrow(/Could not find satisfied version for SemVer */);
|
).rejects.toThrow(/No matching version found for SemVer */);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('version is not found', async () => {
|
it('version is not found', async () => {
|
||||||
@ -275,9 +352,14 @@ describe('findPackageForDownload', () => {
|
|||||||
},
|
},
|
||||||
AdoptImplementation.Hotspot
|
AdoptImplementation.Hotspot
|
||||||
);
|
);
|
||||||
|
// Mock Temurin to fail so fallback to AdoptOpenJDK is tested
|
||||||
|
distribution['temurinDistribution']!['findPackageForDownload'] =
|
||||||
|
async () => {
|
||||||
|
throw new Error('No matching version found for SemVer');
|
||||||
|
};
|
||||||
distribution['getAvailableVersions'] = async () => manifestData as any;
|
distribution['getAvailableVersions'] = async () => manifestData as any;
|
||||||
await expect(distribution['findPackageForDownload']('7.x')).rejects.toThrow(
|
await expect(distribution['findPackageForDownload']('7.x')).rejects.toThrow(
|
||||||
/Could not find satisfied version for SemVer */
|
/No matching version found for SemVer */
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -291,9 +373,14 @@ describe('findPackageForDownload', () => {
|
|||||||
},
|
},
|
||||||
AdoptImplementation.Hotspot
|
AdoptImplementation.Hotspot
|
||||||
);
|
);
|
||||||
|
// Mock Temurin to fail so fallback to AdoptOpenJDK is tested
|
||||||
|
distribution['temurinDistribution']!['findPackageForDownload'] =
|
||||||
|
async () => {
|
||||||
|
throw new Error('No matching version found for SemVer');
|
||||||
|
};
|
||||||
distribution['getAvailableVersions'] = async () => [];
|
distribution['getAvailableVersions'] = async () => [];
|
||||||
await expect(distribution['findPackageForDownload']('11')).rejects.toThrow(
|
await expect(distribution['findPackageForDownload']('11')).rejects.toThrow(
|
||||||
/Could not find satisfied version for SemVer */
|
/No matching version found for SemVer */
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -38,7 +38,7 @@ class EmptyJavaBase extends JavaBase {
|
|||||||
): Promise<JavaDownloadRelease> {
|
): Promise<JavaDownloadRelease> {
|
||||||
const availableVersion = '11.0.9';
|
const availableVersion = '11.0.9';
|
||||||
if (!semver.satisfies(availableVersion, range)) {
|
if (!semver.satisfies(availableVersion, range)) {
|
||||||
throw new Error('Available version not found');
|
throw this.createVersionNotFoundError(range, [availableVersion]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -248,6 +248,7 @@ describe('setupJava', () => {
|
|||||||
let spyCoreExportVariable: jest.SpyInstance;
|
let spyCoreExportVariable: jest.SpyInstance;
|
||||||
let spyCoreAddPath: jest.SpyInstance;
|
let spyCoreAddPath: jest.SpyInstance;
|
||||||
let spyCoreSetOutput: jest.SpyInstance;
|
let spyCoreSetOutput: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyGetToolcachePath = jest.spyOn(util, 'getToolcachePath');
|
spyGetToolcachePath = jest.spyOn(util, 'getToolcachePath');
|
||||||
@ -287,6 +288,10 @@ describe('setupJava', () => {
|
|||||||
spyCoreSetOutput = jest.spyOn(core, 'setOutput');
|
spyCoreSetOutput = jest.spyOn(core, 'setOutput');
|
||||||
spyCoreSetOutput.mockImplementation(() => undefined);
|
spyCoreSetOutput.mockImplementation(() => undefined);
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => undefined);
|
||||||
|
|
||||||
jest.spyOn(os, 'arch').mockReturnValue('x86' as ReturnType<typeof os.arch>);
|
jest.spyOn(os, 'arch').mockReturnValue('x86' as ReturnType<typeof os.arch>);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -530,19 +535,16 @@ describe('setupJava', () => {
|
|||||||
checkLatest: false
|
checkLatest: false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
])(
|
])('should throw an error for version not found for %s', async input => {
|
||||||
'should throw an error for Available version not found for %s',
|
mockJavaBase = new EmptyJavaBase(input);
|
||||||
async input => {
|
await expect(mockJavaBase.setupJava()).rejects.toThrow(
|
||||||
mockJavaBase = new EmptyJavaBase(input);
|
`No matching version found for SemVer '${input.version}'`
|
||||||
await expect(mockJavaBase.setupJava()).rejects.toThrow(
|
);
|
||||||
'Available version not found'
|
expect(spyTcFindAllVersions).toHaveBeenCalled();
|
||||||
);
|
expect(spyCoreAddPath).not.toHaveBeenCalled();
|
||||||
expect(spyTcFindAllVersions).toHaveBeenCalled();
|
expect(spyCoreExportVariable).not.toHaveBeenCalled();
|
||||||
expect(spyCoreAddPath).not.toHaveBeenCalled();
|
expect(spyCoreSetOutput).not.toHaveBeenCalled();
|
||||||
expect(spyCoreExportVariable).not.toHaveBeenCalled();
|
});
|
||||||
expect(spyCoreSetOutput).not.toHaveBeenCalled();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('normalizeVersion', () => {
|
describe('normalizeVersion', () => {
|
||||||
@ -570,6 +572,97 @@ describe('normalizeVersion', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('createVersionNotFoundError', () => {
|
||||||
|
it('should include all required fields in error message without available versions', () => {
|
||||||
|
const mockJavaBase = new EmptyJavaBase({
|
||||||
|
version: '17.0.5',
|
||||||
|
architecture: 'x64',
|
||||||
|
packageType: 'jdk',
|
||||||
|
checkLatest: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const error = (mockJavaBase as any).createVersionNotFoundError('17.0.5');
|
||||||
|
|
||||||
|
expect(error.message).toContain(
|
||||||
|
"No matching version found for SemVer '17.0.5'"
|
||||||
|
);
|
||||||
|
expect(error.message).toContain('Distribution: Empty');
|
||||||
|
expect(error.message).toContain('Package type: jdk');
|
||||||
|
expect(error.message).toContain('Architecture: x64');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should include available versions when provided', () => {
|
||||||
|
const mockJavaBase = new EmptyJavaBase({
|
||||||
|
version: '17.0.5',
|
||||||
|
architecture: 'x64',
|
||||||
|
packageType: 'jdk',
|
||||||
|
checkLatest: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const availableVersions = ['11.0.1', '11.0.2', '17.0.1', '17.0.2'];
|
||||||
|
const error = (mockJavaBase as any).createVersionNotFoundError(
|
||||||
|
'17.0.5',
|
||||||
|
availableVersions
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(error.message).toContain(
|
||||||
|
"No matching version found for SemVer '17.0.5'"
|
||||||
|
);
|
||||||
|
expect(error.message).toContain('Distribution: Empty');
|
||||||
|
expect(error.message).toContain('Package type: jdk');
|
||||||
|
expect(error.message).toContain('Architecture: x64');
|
||||||
|
expect(error.message).toContain(
|
||||||
|
'Available versions: 11.0.1, 11.0.2, 17.0.1, 17.0.2'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should truncate available versions when there are many', () => {
|
||||||
|
const mockJavaBase = new EmptyJavaBase({
|
||||||
|
version: '17.0.5',
|
||||||
|
architecture: 'x64',
|
||||||
|
packageType: 'jdk',
|
||||||
|
checkLatest: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create 60 versions to test truncation
|
||||||
|
const availableVersions = Array.from({length: 60}, (_, i) => `11.0.${i}`);
|
||||||
|
const error = (mockJavaBase as any).createVersionNotFoundError(
|
||||||
|
'17.0.5',
|
||||||
|
availableVersions
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(error.message).toContain('Available versions:');
|
||||||
|
expect(error.message).toContain('...');
|
||||||
|
expect(error.message).toContain('(showing first 50 of 60 versions');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should include additional context when provided', () => {
|
||||||
|
const mockJavaBase = new EmptyJavaBase({
|
||||||
|
version: '17.0.5',
|
||||||
|
architecture: 'x64',
|
||||||
|
packageType: 'jdk',
|
||||||
|
checkLatest: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const availableVersions = ['11.0.1', '11.0.2'];
|
||||||
|
const additionalContext = 'Platform: linux';
|
||||||
|
const error = (mockJavaBase as any).createVersionNotFoundError(
|
||||||
|
'17.0.5',
|
||||||
|
availableVersions,
|
||||||
|
additionalContext
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(error.message).toContain(
|
||||||
|
"No matching version found for SemVer '17.0.5'"
|
||||||
|
);
|
||||||
|
expect(error.message).toContain('Distribution: Empty');
|
||||||
|
expect(error.message).toContain('Package type: jdk');
|
||||||
|
expect(error.message).toContain('Architecture: x64');
|
||||||
|
expect(error.message).toContain('Platform: linux');
|
||||||
|
expect(error.message).toContain('Available versions: 11.0.1, 11.0.2');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('getToolcacheVersionName', () => {
|
describe('getToolcacheVersionName', () => {
|
||||||
const DummyJavaBase = JavaBase as any;
|
const DummyJavaBase = JavaBase as any;
|
||||||
|
|
||||||
|
|||||||
@ -4,13 +4,14 @@ import {JavaInstallerOptions} from '../../src/distributions/base-models';
|
|||||||
import {CorrettoDistribution} from '../../src/distributions/corretto/installer';
|
import {CorrettoDistribution} from '../../src/distributions/corretto/installer';
|
||||||
import * as util from '../../src/util';
|
import * as util from '../../src/util';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
import {isGeneratorFunction} from 'util/types';
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
import manifestData from '../data/corretto.json';
|
import manifestData from '../data/corretto.json';
|
||||||
|
|
||||||
describe('getAvailableVersions', () => {
|
describe('getAvailableVersions', () => {
|
||||||
let spyHttpClient: jest.SpyInstance;
|
let spyHttpClient: jest.SpyInstance;
|
||||||
let spyGetDownloadArchiveExtension: jest.SpyInstance;
|
let spyGetDownloadArchiveExtension: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
@ -23,6 +24,10 @@ describe('getAvailableVersions', () => {
|
|||||||
util,
|
util,
|
||||||
'getDownloadArchiveExtension'
|
'getDownloadArchiveExtension'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -198,7 +203,7 @@ describe('getAvailableVersions', () => {
|
|||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
distribution['findPackageForDownload'](version)
|
distribution['findPackageForDownload'](version)
|
||||||
).rejects.toThrow("Could not find satisfied version for SemVer '4'");
|
).rejects.toThrow("No matching version found for SemVer '4'");
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
import {HttpClient} from '@actions/http-client';
|
import {HttpClient} from '@actions/http-client';
|
||||||
import {DragonwellDistribution} from '../../src/distributions/dragonwell/installer';
|
import {DragonwellDistribution} from '../../src/distributions/dragonwell/installer';
|
||||||
import * as utils from '../../src/util';
|
import * as utils from '../../src/util';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
import manifestData from '../data/dragonwell.json';
|
import manifestData from '../data/dragonwell.json';
|
||||||
|
|
||||||
describe('getAvailableVersions', () => {
|
describe('getAvailableVersions', () => {
|
||||||
let spyHttpClient: jest.SpyInstance;
|
let spyHttpClient: jest.SpyInstance;
|
||||||
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
|
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
@ -21,6 +23,10 @@ describe('getAvailableVersions', () => {
|
|||||||
'getDownloadArchiveExtension'
|
'getDownloadArchiveExtension'
|
||||||
);
|
);
|
||||||
spyUtilGetDownloadArchiveExtension.mockReturnValue('tar.gz');
|
spyUtilGetDownloadArchiveExtension.mockReturnValue('tar.gz');
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -232,7 +238,7 @@ describe('getAvailableVersions', () => {
|
|||||||
await expect(
|
await expect(
|
||||||
distribution['findPackageForDownload'](jdkVersion)
|
distribution['findPackageForDownload'](jdkVersion)
|
||||||
).rejects.toThrow(
|
).rejects.toThrow(
|
||||||
`Couldn't find any satisfied version for the specified java-version: "${jdkVersion}" and architecture: "${arch}".`
|
`No matching version found for SemVer '${jdkVersion}'`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@ -42,6 +42,7 @@ beforeAll(() => {
|
|||||||
describe('GraalVMDistribution', () => {
|
describe('GraalVMDistribution', () => {
|
||||||
let distribution: GraalVMDistribution;
|
let distribution: GraalVMDistribution;
|
||||||
let mockHttpClient: jest.Mocked<http.HttpClient>;
|
let mockHttpClient: jest.Mocked<http.HttpClient>;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
const defaultOptions: JavaInstallerOptions = {
|
const defaultOptions: JavaInstallerOptions = {
|
||||||
version: '17',
|
version: '17',
|
||||||
@ -59,6 +60,10 @@ describe('GraalVMDistribution', () => {
|
|||||||
(distribution as any).http = mockHttpClient;
|
(distribution as any).http = mockHttpClient;
|
||||||
|
|
||||||
(util.getDownloadArchiveExtension as jest.Mock).mockReturnValue('tar.gz');
|
(util.getDownloadArchiveExtension as jest.Mock).mockReturnValue('tar.gz');
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
@ -348,11 +353,19 @@ describe('GraalVMDistribution', () => {
|
|||||||
} as http.HttpClientResponse;
|
} as http.HttpClientResponse;
|
||||||
mockHttpClient.head.mockResolvedValue(mockResponse);
|
mockHttpClient.head.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
// Verify the error is thrown with the expected message
|
||||||
await expect(
|
await expect(
|
||||||
(distribution as any).findPackageForDownload('17.0.99')
|
(distribution as any).findPackageForDownload('17.0.99')
|
||||||
).rejects.toThrow(
|
).rejects.toThrow("No matching version found for SemVer '17.0.99'");
|
||||||
'Could not find GraalVM for SemVer 17.0.99. Please check if this version is available at https://download.oracle.com/graalvm'
|
// Verify distribution info is included
|
||||||
);
|
await expect(
|
||||||
|
(distribution as any).findPackageForDownload('17.0.99')
|
||||||
|
).rejects.toThrow('GraalVM');
|
||||||
|
|
||||||
|
// Verify the hint about checking the base URL is included
|
||||||
|
await expect(
|
||||||
|
(distribution as any).findPackageForDownload('17.0.99')
|
||||||
|
).rejects.toThrow('https://www.graalvm.org/downloads/');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw error for unauthorized access (401)', async () => {
|
it('should throw error for unauthorized access (401)', async () => {
|
||||||
@ -496,12 +509,19 @@ describe('GraalVMDistribution', () => {
|
|||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
(distribution as any).findPackageForDownload('23')
|
(distribution as any).findPackageForDownload('23')
|
||||||
).rejects.toThrow("Unable to find latest version for '23-ea'");
|
).rejects.toThrow("No matching version found for SemVer '23-ea'");
|
||||||
|
|
||||||
// Verify error logging
|
await expect(
|
||||||
expect(core.error).toHaveBeenCalledWith(
|
(distribution as any).findPackageForDownload('23')
|
||||||
'Available versions: 23-ea-20240716'
|
).rejects.toThrow(
|
||||||
|
'Note: No EA build is marked as latest for this version.'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
(distribution as any).findPackageForDownload('23')
|
||||||
|
).rejects.toThrow('23-ea-20240716');
|
||||||
|
|
||||||
|
// Verify error logging - removed as we now use the helper method which doesn't call core.error
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw error when no matching file for architecture in EA build', async () => {
|
it('should throw error when no matching file for architecture in EA build', async () => {
|
||||||
@ -708,11 +728,19 @@ describe('GraalVMDistribution', () => {
|
|||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
(distribution as any).findEABuildDownloadUrl('23-ea')
|
(distribution as any).findEABuildDownloadUrl('23-ea')
|
||||||
).rejects.toThrow("Unable to find latest version for '23-ea'");
|
).rejects.toThrow("No matching version found for SemVer '23-ea'");
|
||||||
|
|
||||||
expect(core.error).toHaveBeenCalledWith(
|
await expect(
|
||||||
'Available versions: 23-ea-20240716, 23-ea-20240709'
|
(distribution as any).findEABuildDownloadUrl('23-ea')
|
||||||
|
).rejects.toThrow(
|
||||||
|
'Note: No EA build is marked as latest for this version.'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
(distribution as any).findEABuildDownloadUrl('23-ea')
|
||||||
|
).rejects.toThrow('23-ea-20240716');
|
||||||
|
|
||||||
|
// Verify error logging - removed as we now use the helper method which doesn't call core.error
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw error when no matching file for architecture', async () => {
|
it('should throw error when no matching file for architecture', async () => {
|
||||||
|
|||||||
@ -4,9 +4,11 @@ import {JetBrainsDistribution} from '../../src/distributions/jetbrains/installer
|
|||||||
|
|
||||||
import manifestData from '../data/jetbrains.json';
|
import manifestData from '../data/jetbrains.json';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
describe('getAvailableVersions', () => {
|
describe('getAvailableVersions', () => {
|
||||||
let spyHttpClient: jest.SpyInstance;
|
let spyHttpClient: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
@ -15,6 +17,10 @@ describe('getAvailableVersions', () => {
|
|||||||
headers: {},
|
headers: {},
|
||||||
result: []
|
result: []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -98,7 +104,7 @@ describe('findPackageForDownload', () => {
|
|||||||
});
|
});
|
||||||
distribution['getAvailableVersions'] = async () => manifestData as any;
|
distribution['getAvailableVersions'] = async () => manifestData as any;
|
||||||
await expect(distribution['findPackageForDownload']('8.x')).rejects.toThrow(
|
await expect(distribution['findPackageForDownload']('8.x')).rejects.toThrow(
|
||||||
/Could not find satisfied version for SemVer */
|
/No matching version found for SemVer */
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -111,7 +117,7 @@ describe('findPackageForDownload', () => {
|
|||||||
});
|
});
|
||||||
distribution['getAvailableVersions'] = async () => [];
|
distribution['getAvailableVersions'] = async () => [];
|
||||||
await expect(distribution['findPackageForDownload']('8')).rejects.toThrow(
|
await expect(distribution['findPackageForDownload']('8')).rejects.toThrow(
|
||||||
/Could not find satisfied version for SemVer */
|
/No matching version found for SemVer */
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,11 +5,13 @@ import {
|
|||||||
} from '../../src/distributions/liberica/models';
|
} from '../../src/distributions/liberica/models';
|
||||||
import {HttpClient} from '@actions/http-client';
|
import {HttpClient} from '@actions/http-client';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
import manifestData from '../data/liberica.json';
|
import manifestData from '../data/liberica.json';
|
||||||
|
|
||||||
describe('getAvailableVersions', () => {
|
describe('getAvailableVersions', () => {
|
||||||
let spyHttpClient: jest.SpyInstance;
|
let spyHttpClient: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
@ -18,6 +20,10 @@ describe('getAvailableVersions', () => {
|
|||||||
headers: {},
|
headers: {},
|
||||||
result: manifestData as LibericaVersion[]
|
result: manifestData as LibericaVersion[]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -209,7 +215,7 @@ describe('findPackageForDownload', () => {
|
|||||||
|
|
||||||
it('should throw an error', async () => {
|
it('should throw an error', async () => {
|
||||||
await expect(distribution['findPackageForDownload']('17')).rejects.toThrow(
|
await expect(distribution['findPackageForDownload']('17')).rejects.toThrow(
|
||||||
/Could not find satisfied version for semver */
|
/No matching version found for SemVer/
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,11 +5,13 @@ import {
|
|||||||
} from '../../src/distributions/liberica/models';
|
} from '../../src/distributions/liberica/models';
|
||||||
import {HttpClient} from '@actions/http-client';
|
import {HttpClient} from '@actions/http-client';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
import manifestData from '../data/liberica-linux.json';
|
import manifestData from '../data/liberica-linux.json';
|
||||||
|
|
||||||
describe('getAvailableVersions', () => {
|
describe('getAvailableVersions', () => {
|
||||||
let spyHttpClient: jest.SpyInstance;
|
let spyHttpClient: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
@ -18,6 +20,10 @@ describe('getAvailableVersions', () => {
|
|||||||
headers: {},
|
headers: {},
|
||||||
result: manifestData as LibericaVersion[]
|
result: manifestData as LibericaVersion[]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -209,7 +215,7 @@ describe('findPackageForDownload', () => {
|
|||||||
|
|
||||||
it('should throw an error', async () => {
|
it('should throw an error', async () => {
|
||||||
await expect(distribution['findPackageForDownload']('18')).rejects.toThrow(
|
await expect(distribution['findPackageForDownload']('18')).rejects.toThrow(
|
||||||
/Could not find satisfied version for semver */
|
/No matching version found for SemVer/
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,11 +5,13 @@ import {
|
|||||||
} from '../../src/distributions/liberica/models';
|
} from '../../src/distributions/liberica/models';
|
||||||
import {HttpClient} from '@actions/http-client';
|
import {HttpClient} from '@actions/http-client';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
import manifestData from '../data/liberica-windows.json';
|
import manifestData from '../data/liberica-windows.json';
|
||||||
|
|
||||||
describe('getAvailableVersions', () => {
|
describe('getAvailableVersions', () => {
|
||||||
let spyHttpClient: jest.SpyInstance;
|
let spyHttpClient: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
@ -18,6 +20,9 @@ describe('getAvailableVersions', () => {
|
|||||||
headers: {},
|
headers: {},
|
||||||
result: manifestData as LibericaVersion[]
|
result: manifestData as LibericaVersion[]
|
||||||
});
|
});
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -209,7 +214,7 @@ describe('findPackageForDownload', () => {
|
|||||||
|
|
||||||
it('should throw an error', async () => {
|
it('should throw an error', async () => {
|
||||||
await expect(distribution['findPackageForDownload']('18')).rejects.toThrow(
|
await expect(distribution['findPackageForDownload']('18')).rejects.toThrow(
|
||||||
/Could not find satisfied version for semver */
|
/No matching version found for SemVer/
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -27,6 +27,7 @@ describe('setupJava', () => {
|
|||||||
let spyFsReadDir: jest.SpyInstance;
|
let spyFsReadDir: jest.SpyInstance;
|
||||||
let spyUtilsExtractJdkFile: jest.SpyInstance;
|
let spyUtilsExtractJdkFile: jest.SpyInstance;
|
||||||
let spyPathResolve: jest.SpyInstance;
|
let spyPathResolve: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
const expectedJdkFile = 'JavaLocalJdkFile';
|
const expectedJdkFile = 'JavaLocalJdkFile';
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -93,6 +94,10 @@ describe('setupJava', () => {
|
|||||||
// Spy on path methods
|
// Spy on path methods
|
||||||
spyPathResolve = jest.spyOn(path, 'resolve');
|
spyPathResolve = jest.spyOn(path, 'resolve');
|
||||||
spyPathResolve.mockImplementation((path: string) => path);
|
spyPathResolve.mockImplementation((path: string) => path);
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ describe('findPackageForDownload', () => {
|
|||||||
let distribution: MicrosoftDistributions;
|
let distribution: MicrosoftDistributions;
|
||||||
let spyGetManifestFromRepo: jest.SpyInstance;
|
let spyGetManifestFromRepo: jest.SpyInstance;
|
||||||
let spyDebug: jest.SpyInstance;
|
let spyDebug: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
distribution = new MicrosoftDistributions({
|
distribution = new MicrosoftDistributions({
|
||||||
@ -26,6 +27,10 @@ describe('findPackageForDownload', () => {
|
|||||||
|
|
||||||
spyDebug = jest.spyOn(core, 'debug');
|
spyDebug = jest.spyOn(core, 'debug');
|
||||||
spyDebug.mockImplementation(() => {});
|
spyDebug.mockImplementation(() => {});
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
@ -174,7 +179,7 @@ describe('findPackageForDownload', () => {
|
|||||||
|
|
||||||
it('should throw an error', async () => {
|
it('should throw an error', async () => {
|
||||||
await expect(distribution['findPackageForDownload']('8')).rejects.toThrow(
|
await expect(distribution['findPackageForDownload']('8')).rejects.toThrow(
|
||||||
/Could not find satisfied version for SemVer */
|
/No matching version found for SemVer */
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -8,6 +8,7 @@ describe('findPackageForDownload', () => {
|
|||||||
let distribution: OracleDistribution;
|
let distribution: OracleDistribution;
|
||||||
let spyDebug: jest.SpyInstance;
|
let spyDebug: jest.SpyInstance;
|
||||||
let spyHttpClient: jest.SpyInstance;
|
let spyHttpClient: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
distribution = new OracleDistribution({
|
distribution = new OracleDistribution({
|
||||||
@ -19,6 +20,10 @@ describe('findPackageForDownload', () => {
|
|||||||
|
|
||||||
spyDebug = jest.spyOn(core, 'debug');
|
spyDebug = jest.spyOn(core, 'debug');
|
||||||
spyDebug.mockImplementation(() => {});
|
spyDebug.mockImplementation(() => {});
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
import {HttpClient} from '@actions/http-client';
|
import {HttpClient} from '@actions/http-client';
|
||||||
import {SapMachineDistribution} from '../../src/distributions/sapmachine/installer';
|
import {SapMachineDistribution} from '../../src/distributions/sapmachine/installer';
|
||||||
import * as utils from '../../src/util';
|
import * as utils from '../../src/util';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
import manifestData from '../data/sapmachine.json';
|
import manifestData from '../data/sapmachine.json';
|
||||||
|
|
||||||
describe('getAvailableVersions', () => {
|
describe('getAvailableVersions', () => {
|
||||||
let spyHttpClient: jest.SpyInstance;
|
let spyHttpClient: jest.SpyInstance;
|
||||||
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
|
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
@ -21,6 +23,10 @@ describe('getAvailableVersions', () => {
|
|||||||
'getDownloadArchiveExtension'
|
'getDownloadArchiveExtension'
|
||||||
);
|
);
|
||||||
spyUtilGetDownloadArchiveExtension.mockReturnValue('tar.gz');
|
spyUtilGetDownloadArchiveExtension.mockReturnValue('tar.gz');
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -266,7 +272,7 @@ describe('getAvailableVersions', () => {
|
|||||||
await expect(
|
await expect(
|
||||||
distribution['findPackageForDownload'](normalizedVersion)
|
distribution['findPackageForDownload'](normalizedVersion)
|
||||||
).rejects.toThrow(
|
).rejects.toThrow(
|
||||||
`Couldn't find any satisfied version for the specified java-version: "${normalizedVersion}" and architecture: "${arch}".`
|
`No matching version found for SemVer '${normalizedVersion}'`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@ -4,9 +4,12 @@ import {JavaInstallerOptions} from '../../src/distributions/base-models';
|
|||||||
import {SemeruDistribution} from '../../src/distributions/semeru/installer';
|
import {SemeruDistribution} from '../../src/distributions/semeru/installer';
|
||||||
|
|
||||||
import manifestData from '../data/semeru.json';
|
import manifestData from '../data/semeru.json';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
describe('getAvailableVersions', () => {
|
describe('getAvailableVersions', () => {
|
||||||
let spyHttpClient: jest.SpyInstance;
|
let spyHttpClient: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
let spyCoreWarning: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
@ -15,6 +18,11 @@ describe('getAvailableVersions', () => {
|
|||||||
headers: {},
|
headers: {},
|
||||||
result: []
|
result: []
|
||||||
});
|
});
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
|
spyCoreWarning = jest.spyOn(core, 'warning');
|
||||||
|
spyCoreWarning.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -77,22 +85,19 @@ describe('getAvailableVersions', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
it('load available versions', async () => {
|
it('load available versions', async () => {
|
||||||
|
const nextPageUrl =
|
||||||
|
'https://api.adoptopenjdk.net/v3/assets/version/%5B1.0,100.0%5D?page=1&page_size=20';
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
spyHttpClient
|
spyHttpClient
|
||||||
.mockReturnValueOnce({
|
.mockReturnValueOnce({
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
headers: {},
|
headers: {link: `<${nextPageUrl}>; rel="next"`},
|
||||||
result: manifestData as any
|
result: manifestData as any
|
||||||
})
|
})
|
||||||
.mockReturnValueOnce({
|
.mockReturnValueOnce({
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
headers: {},
|
headers: {},
|
||||||
result: manifestData as any
|
result: manifestData as any
|
||||||
})
|
|
||||||
.mockReturnValueOnce({
|
|
||||||
statusCode: 200,
|
|
||||||
headers: {},
|
|
||||||
result: []
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const distribution = new SemeruDistribution({
|
const distribution = new SemeruDistribution({
|
||||||
@ -104,6 +109,31 @@ describe('getAvailableVersions', () => {
|
|||||||
const availableVersions = await distribution['getAvailableVersions']();
|
const availableVersions = await distribution['getAvailableVersions']();
|
||||||
expect(availableVersions).not.toBeNull();
|
expect(availableVersions).not.toBeNull();
|
||||||
expect(availableVersions.length).toBe(manifestData.length * 2);
|
expect(availableVersions.length).toBe(manifestData.length * 2);
|
||||||
|
expect(spyHttpClient).toHaveBeenNthCalledWith(2, nextPageUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('stops pagination after 1000 pages as a safeguard', async () => {
|
||||||
|
const nextPageUrl =
|
||||||
|
'https://api.adoptopenjdk.net/v3/assets/version/%5B1.0,100.0%5D?page=2&page_size=20';
|
||||||
|
spyHttpClient.mockReturnValue({
|
||||||
|
statusCode: 200,
|
||||||
|
headers: {link: `<${nextPageUrl}>; rel="next"`},
|
||||||
|
result: [{version_data: {semver: '17.0.1'}, binaries: []}] as any
|
||||||
|
});
|
||||||
|
|
||||||
|
const distribution = new SemeruDistribution({
|
||||||
|
version: '8',
|
||||||
|
architecture: 'x64',
|
||||||
|
packageType: 'jdk',
|
||||||
|
checkLatest: false
|
||||||
|
});
|
||||||
|
|
||||||
|
await distribution['getAvailableVersions']();
|
||||||
|
|
||||||
|
expect(spyHttpClient).toHaveBeenCalledTimes(1000);
|
||||||
|
expect(spyCoreWarning).toHaveBeenCalledWith(
|
||||||
|
expect.stringContaining('Reached pagination safeguard limit (1000 pages)')
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
@ -152,7 +182,7 @@ describe('findPackageForDownload', () => {
|
|||||||
distribution['getAvailableVersions'] = async () => manifestData as any;
|
distribution['getAvailableVersions'] = async () => manifestData as any;
|
||||||
await expect(
|
await expect(
|
||||||
distribution['findPackageForDownload']('9.0.8')
|
distribution['findPackageForDownload']('9.0.8')
|
||||||
).rejects.toThrow(/Could not find satisfied version for SemVer */);
|
).rejects.toThrow(/No matching version found for SemVer */);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('version is not found', async () => {
|
it('version is not found', async () => {
|
||||||
@ -164,7 +194,7 @@ describe('findPackageForDownload', () => {
|
|||||||
});
|
});
|
||||||
distribution['getAvailableVersions'] = async () => manifestData as any;
|
distribution['getAvailableVersions'] = async () => manifestData as any;
|
||||||
await expect(distribution['findPackageForDownload']('7.x')).rejects.toThrow(
|
await expect(distribution['findPackageForDownload']('7.x')).rejects.toThrow(
|
||||||
/Could not find satisfied version for SemVer */
|
/No matching version found for SemVer */
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -177,7 +207,7 @@ describe('findPackageForDownload', () => {
|
|||||||
});
|
});
|
||||||
distribution['getAvailableVersions'] = async () => [];
|
distribution['getAvailableVersions'] = async () => [];
|
||||||
await expect(distribution['findPackageForDownload']('8')).rejects.toThrow(
|
await expect(distribution['findPackageForDownload']('8')).rejects.toThrow(
|
||||||
/Could not find satisfied version for SemVer */
|
/No matching version found for SemVer */
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -7,9 +7,12 @@ import {
|
|||||||
import {JavaInstallerOptions} from '../../src/distributions/base-models';
|
import {JavaInstallerOptions} from '../../src/distributions/base-models';
|
||||||
|
|
||||||
import manifestData from '../data/temurin.json';
|
import manifestData from '../data/temurin.json';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
describe('getAvailableVersions', () => {
|
describe('getAvailableVersions', () => {
|
||||||
let spyHttpClient: jest.SpyInstance;
|
let spyHttpClient: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
let spyCoreWarning: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
@ -18,6 +21,11 @@ describe('getAvailableVersions', () => {
|
|||||||
headers: {},
|
headers: {},
|
||||||
result: []
|
result: []
|
||||||
});
|
});
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
|
spyCoreWarning = jest.spyOn(core, 'warning');
|
||||||
|
spyCoreWarning.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -88,22 +96,19 @@ describe('getAvailableVersions', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
it('load available versions', async () => {
|
it('load available versions', async () => {
|
||||||
|
const nextPageUrl =
|
||||||
|
'https://api.adoptium.net/v3/assets/version/%5B1.0,100.0%5D?page=1&page_size=20';
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
spyHttpClient
|
spyHttpClient
|
||||||
.mockReturnValueOnce({
|
.mockReturnValueOnce({
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
headers: {},
|
headers: {link: `<${nextPageUrl}>; rel="next"`},
|
||||||
result: manifestData as any
|
result: manifestData as any
|
||||||
})
|
})
|
||||||
.mockReturnValueOnce({
|
.mockReturnValueOnce({
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
headers: {},
|
headers: {},
|
||||||
result: manifestData as any
|
result: manifestData as any
|
||||||
})
|
|
||||||
.mockReturnValueOnce({
|
|
||||||
statusCode: 200,
|
|
||||||
headers: {},
|
|
||||||
result: []
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const distribution = new TemurinDistribution(
|
const distribution = new TemurinDistribution(
|
||||||
@ -118,6 +123,34 @@ describe('getAvailableVersions', () => {
|
|||||||
const availableVersions = await distribution['getAvailableVersions']();
|
const availableVersions = await distribution['getAvailableVersions']();
|
||||||
expect(availableVersions).not.toBeNull();
|
expect(availableVersions).not.toBeNull();
|
||||||
expect(availableVersions.length).toBe(manifestData.length * 2);
|
expect(availableVersions.length).toBe(manifestData.length * 2);
|
||||||
|
expect(spyHttpClient).toHaveBeenNthCalledWith(2, nextPageUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('stops pagination after 1000 pages as a safeguard', async () => {
|
||||||
|
const nextPageUrl =
|
||||||
|
'https://api.adoptium.net/v3/assets/version/%5B1.0,100.0%5D?page=2&page_size=20';
|
||||||
|
spyHttpClient.mockReturnValue({
|
||||||
|
statusCode: 200,
|
||||||
|
headers: {link: `<${nextPageUrl}>; rel="next"`},
|
||||||
|
result: [{version_data: {semver: '17.0.1'}, binaries: []}] as any
|
||||||
|
});
|
||||||
|
|
||||||
|
const distribution = new TemurinDistribution(
|
||||||
|
{
|
||||||
|
version: '8',
|
||||||
|
architecture: 'x64',
|
||||||
|
packageType: 'jdk',
|
||||||
|
checkLatest: false
|
||||||
|
},
|
||||||
|
TemurinImplementation.Hotspot
|
||||||
|
);
|
||||||
|
|
||||||
|
await distribution['getAvailableVersions']();
|
||||||
|
|
||||||
|
expect(spyHttpClient).toHaveBeenCalledTimes(1000);
|
||||||
|
expect(spyCoreWarning).toHaveBeenCalledWith(
|
||||||
|
expect.stringContaining('Reached pagination safeguard limit (1000 pages)')
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
@ -213,7 +246,7 @@ describe('findPackageForDownload', () => {
|
|||||||
distribution['getAvailableVersions'] = async () => manifestData as any;
|
distribution['getAvailableVersions'] = async () => manifestData as any;
|
||||||
await expect(
|
await expect(
|
||||||
distribution['findPackageForDownload']('9.0.8')
|
distribution['findPackageForDownload']('9.0.8')
|
||||||
).rejects.toThrow(/Could not find satisfied version for SemVer */);
|
).rejects.toThrow(/No matching version found for SemVer */);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('version is not found', async () => {
|
it('version is not found', async () => {
|
||||||
@ -228,7 +261,7 @@ describe('findPackageForDownload', () => {
|
|||||||
);
|
);
|
||||||
distribution['getAvailableVersions'] = async () => manifestData as any;
|
distribution['getAvailableVersions'] = async () => manifestData as any;
|
||||||
await expect(distribution['findPackageForDownload']('7.x')).rejects.toThrow(
|
await expect(distribution['findPackageForDownload']('7.x')).rejects.toThrow(
|
||||||
/Could not find satisfied version for SemVer */
|
/No matching version found for SemVer */
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -244,7 +277,7 @@ describe('findPackageForDownload', () => {
|
|||||||
);
|
);
|
||||||
distribution['getAvailableVersions'] = async () => [];
|
distribution['getAvailableVersions'] = async () => [];
|
||||||
await expect(distribution['findPackageForDownload']('8')).rejects.toThrow(
|
await expect(distribution['findPackageForDownload']('8')).rejects.toThrow(
|
||||||
/Could not find satisfied version for SemVer */
|
/No matching version found for SemVer */
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,12 +3,14 @@ import {ZuluDistribution} from '../../src/distributions/zulu/installer';
|
|||||||
import {IZuluVersions} from '../../src/distributions/zulu/models';
|
import {IZuluVersions} from '../../src/distributions/zulu/models';
|
||||||
import * as utils from '../../src/util';
|
import * as utils from '../../src/util';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
import manifestData from '../data/zulu-releases-default.json';
|
import manifestData from '../data/zulu-releases-default.json';
|
||||||
|
|
||||||
describe('getAvailableVersions', () => {
|
describe('getAvailableVersions', () => {
|
||||||
let spyHttpClient: jest.SpyInstance;
|
let spyHttpClient: jest.SpyInstance;
|
||||||
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
|
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
@ -23,6 +25,10 @@ describe('getAvailableVersions', () => {
|
|||||||
'getDownloadArchiveExtension'
|
'getDownloadArchiveExtension'
|
||||||
);
|
);
|
||||||
spyUtilGetDownloadArchiveExtension.mockReturnValue('tar.gz');
|
spyUtilGetDownloadArchiveExtension.mockReturnValue('tar.gz');
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -225,6 +231,6 @@ describe('findPackageForDownload', () => {
|
|||||||
distribution['getAvailableVersions'] = async () => manifestData;
|
distribution['getAvailableVersions'] = async () => manifestData;
|
||||||
await expect(
|
await expect(
|
||||||
distribution['findPackageForDownload'](distribution['version'])
|
distribution['findPackageForDownload'](distribution['version'])
|
||||||
).rejects.toThrow(/Could not find satisfied version for semver */);
|
).rejects.toThrow(/No matching version found for SemVer/);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -4,12 +4,14 @@ import {ZuluDistribution} from '../../src/distributions/zulu/installer';
|
|||||||
import {IZuluVersions} from '../../src/distributions/zulu/models';
|
import {IZuluVersions} from '../../src/distributions/zulu/models';
|
||||||
import * as utils from '../../src/util';
|
import * as utils from '../../src/util';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
import manifestData from '../data/zulu-linux.json';
|
import manifestData from '../data/zulu-linux.json';
|
||||||
|
|
||||||
describe('getAvailableVersions', () => {
|
describe('getAvailableVersions', () => {
|
||||||
let spyHttpClient: jest.SpyInstance;
|
let spyHttpClient: jest.SpyInstance;
|
||||||
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
|
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
@ -24,6 +26,10 @@ describe('getAvailableVersions', () => {
|
|||||||
'getDownloadArchiveExtension'
|
'getDownloadArchiveExtension'
|
||||||
);
|
);
|
||||||
spyUtilGetDownloadArchiveExtension.mockReturnValue('zip');
|
spyUtilGetDownloadArchiveExtension.mockReturnValue('zip');
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -228,6 +234,6 @@ describe('findPackageForDownload', () => {
|
|||||||
distribution['getAvailableVersions'] = async () => manifestData;
|
distribution['getAvailableVersions'] = async () => manifestData;
|
||||||
await expect(
|
await expect(
|
||||||
distribution['findPackageForDownload'](distribution['version'])
|
distribution['findPackageForDownload'](distribution['version'])
|
||||||
).rejects.toThrow(/Could not find satisfied version for semver */);
|
).rejects.toThrow(/No matching version found for SemVer/);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -4,12 +4,14 @@ import {ZuluDistribution} from '../../src/distributions/zulu/installer';
|
|||||||
import {IZuluVersions} from '../../src/distributions/zulu/models';
|
import {IZuluVersions} from '../../src/distributions/zulu/models';
|
||||||
import * as utils from '../../src/util';
|
import * as utils from '../../src/util';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
import manifestData from '../data/zulu-windows.json';
|
import manifestData from '../data/zulu-windows.json';
|
||||||
|
|
||||||
describe('getAvailableVersions', () => {
|
describe('getAvailableVersions', () => {
|
||||||
let spyHttpClient: jest.SpyInstance;
|
let spyHttpClient: jest.SpyInstance;
|
||||||
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
|
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
|
||||||
|
let spyCoreError: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||||
@ -24,6 +26,10 @@ describe('getAvailableVersions', () => {
|
|||||||
'getDownloadArchiveExtension'
|
'getDownloadArchiveExtension'
|
||||||
);
|
);
|
||||||
spyUtilGetDownloadArchiveExtension.mockReturnValue('zip');
|
spyUtilGetDownloadArchiveExtension.mockReturnValue('zip');
|
||||||
|
|
||||||
|
// Mock core.error to suppress error logs
|
||||||
|
spyCoreError = jest.spyOn(core, 'error');
|
||||||
|
spyCoreError.mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -226,6 +232,6 @@ describe('findPackageForDownload', () => {
|
|||||||
distribution['getAvailableVersions'] = async () => manifestData;
|
distribution['getAvailableVersions'] = async () => manifestData;
|
||||||
await expect(
|
await expect(
|
||||||
distribution['findPackageForDownload'](distribution['version'])
|
distribution['findPackageForDownload'](distribution['version'])
|
||||||
).rejects.toThrow(/Could not find satisfied version for semver */);
|
).rejects.toThrow(/No matching version found for SemVer/);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -4,10 +4,12 @@ import * as fs from 'fs';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import {
|
import {
|
||||||
convertVersionToSemver,
|
convertVersionToSemver,
|
||||||
|
getNextPageUrlFromLinkHeader,
|
||||||
getVersionFromFileContent,
|
getVersionFromFileContent,
|
||||||
isVersionSatisfies,
|
isVersionSatisfies,
|
||||||
isCacheFeatureAvailable,
|
isCacheFeatureAvailable,
|
||||||
isGhes
|
isGhes,
|
||||||
|
validatePaginationUrl
|
||||||
} from '../src/util';
|
} from '../src/util';
|
||||||
|
|
||||||
jest.mock('@actions/cache');
|
jest.mock('@actions/cache');
|
||||||
@ -85,6 +87,78 @@ describe('convertVersionToSemver', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getNextPageUrlFromLinkHeader', () => {
|
||||||
|
it.each([
|
||||||
|
[
|
||||||
|
{
|
||||||
|
link: '<https://api.adoptium.net/v3/info/release_versions?page=1&page_size=10>; rel="next"'
|
||||||
|
},
|
||||||
|
'https://api.adoptium.net/v3/info/release_versions?page=1&page_size=10'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
Link: '<https://example.com/last?page=5>; rel="last", <https://example.com/next?page=2>; rel="next"'
|
||||||
|
},
|
||||||
|
'https://example.com/next?page=2'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
link: '<https://api.adoptium.net/v3/versions?page=3>; type="application/json"; rel="next"'
|
||||||
|
},
|
||||||
|
'https://api.adoptium.net/v3/versions?page=3'
|
||||||
|
],
|
||||||
|
[{link: '<https://example.com/last?page=5>; rel="last"'}, null],
|
||||||
|
[{link: '<https://example.com/page?p=2>; rel="nextsomething"'}, null],
|
||||||
|
[undefined, null]
|
||||||
|
])('returns %s -> %s', (headers, expected) => {
|
||||||
|
expect(getNextPageUrlFromLinkHeader(headers)).toBe(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('validatePaginationUrl', () => {
|
||||||
|
it('accepts URL with matching origin', () => {
|
||||||
|
expect(
|
||||||
|
validatePaginationUrl(
|
||||||
|
'https://api.adoptium.net/v3/assets?page=2',
|
||||||
|
'https://api.adoptium.net'
|
||||||
|
)
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects URL with different host', () => {
|
||||||
|
expect(
|
||||||
|
validatePaginationUrl(
|
||||||
|
'https://evil.example.com/steal?data=1',
|
||||||
|
'https://api.adoptium.net'
|
||||||
|
)
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects URL with different protocol', () => {
|
||||||
|
expect(
|
||||||
|
validatePaginationUrl(
|
||||||
|
'http://api.adoptium.net/v3/assets?page=2',
|
||||||
|
'https://api.adoptium.net'
|
||||||
|
)
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false for invalid URL', () => {
|
||||||
|
expect(validatePaginationUrl('not-a-url', 'https://api.adoptium.net')).toBe(
|
||||||
|
false
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('accepts URL with explicit default port', () => {
|
||||||
|
expect(
|
||||||
|
validatePaginationUrl(
|
||||||
|
'https://api.adoptium.net:443/v3/assets?page=2',
|
||||||
|
'https://api.adoptium.net'
|
||||||
|
)
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('getVersionFromFileContent', () => {
|
describe('getVersionFromFileContent', () => {
|
||||||
describe('.sdkmanrc', () => {
|
describe('.sdkmanrc', () => {
|
||||||
it.each([
|
it.each([
|
||||||
|
|||||||
16
action.yml
16
action.yml
@ -43,9 +43,21 @@ inputs:
|
|||||||
description: 'Path to where the settings.xml file will be written. Default is ~/.m2.'
|
description: 'Path to where the settings.xml file will be written. Default is ~/.m2.'
|
||||||
required: false
|
required: false
|
||||||
overwrite-settings:
|
overwrite-settings:
|
||||||
description: 'Overwrite the settings.xml file if it exists. Default is "true".'
|
description: 'Overwrite the settings.xml file if it exists. Default is "!update-toolchains-only". If explcitly set "true", it will update settings.xml regardless of "update-toolchains-only"'
|
||||||
required: false
|
required: false
|
||||||
default: true
|
# DO NOT set a default here! The default will be propagated from input 'update-toolchains-only'!
|
||||||
|
update-toolchains-only:
|
||||||
|
description: 'Update toolchains.xml only. Default is "false". No update of settings.xml, no update of JAVA_HOME, no adding to PATH by default - unless "overwrite-settings", "update-env-javahome" or "add-to-env-path" are not explicitly set "true"'
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
update-env-javahome:
|
||||||
|
description: 'Update the JAVA_HOME environment variable. Default is "!update-toolchains-only"'
|
||||||
|
required: false
|
||||||
|
# DO NOT set a default here! The default will be propagated from input 'update-toolchains-only'!
|
||||||
|
add-to-env-path:
|
||||||
|
description: 'Add "<JDK home>/bin" to the PATH environment variable. Default is "!update-toolchains-only"'
|
||||||
|
required: false
|
||||||
|
# DO NOT set a default here! The default will be propagated from input 'update-toolchains-only'!
|
||||||
gpg-private-key:
|
gpg-private-key:
|
||||||
description: 'GPG private key to import. Default is empty string.'
|
description: 'GPG private key to import. Default is empty string.'
|
||||||
required: false
|
required: false
|
||||||
|
|||||||
58638
dist/cleanup/index.js
vendored
58638
dist/cleanup/index.js
vendored
File diff suppressed because one or more lines are too long
93035
dist/setup/index.js
vendored
93035
dist/setup/index.js
vendored
File diff suppressed because one or more lines are too long
3923
package-lock.json
generated
3923
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
30
package.json
30
package.json
@ -29,31 +29,31 @@
|
|||||||
"author": "GitHub",
|
"author": "GitHub",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/cache": "^5.0.1",
|
"@actions/cache": "^5.0.5",
|
||||||
"@actions/core": "^1.10.0",
|
"@actions/core": "^2.0.3",
|
||||||
"@actions/exec": "^1.0.4",
|
"@actions/exec": "^2.0.0",
|
||||||
"@actions/glob": "^0.5.0",
|
"@actions/glob": "^0.5.1",
|
||||||
"@actions/http-client": "^2.2.3",
|
"@actions/http-client": "^3.0.2",
|
||||||
"@actions/io": "^1.0.2",
|
"@actions/io": "^2.0.0",
|
||||||
"@actions/tool-cache": "^2.0.1",
|
"@actions/tool-cache": "^3.0.1",
|
||||||
"semver": "^7.6.0",
|
"semver": "^7.6.0",
|
||||||
"xmlbuilder2": "^2.4.0"
|
"xmlbuilder2": "^4.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^30.0.0",
|
||||||
"@types/node": "^24.1.0",
|
"@types/node": "^25.9.3",
|
||||||
"@types/semver": "^7.5.8",
|
"@types/semver": "^7.5.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.35.1",
|
"@typescript-eslint/eslint-plugin": "^8.48.0",
|
||||||
"@typescript-eslint/parser": "^8.35.1",
|
"@typescript-eslint/parser": "^8.35.1",
|
||||||
"@vercel/ncc": "^0.38.1",
|
"@vercel/ncc": "^0.38.1",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-prettier": "^8.6.0",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-jest": "^29.0.1",
|
"eslint-plugin-jest": "^29.0.1",
|
||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^30.4.2",
|
||||||
"jest-circus": "^29.7.0",
|
"jest-circus": "^30.4.2",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"ts-jest": "^29.3.0",
|
"ts-jest": "^29.4.11",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
|||||||
@ -10,17 +10,13 @@ import * as constants from './constants';
|
|||||||
import * as gpg from './gpg';
|
import * as gpg from './gpg';
|
||||||
import {getBooleanInput} from './util';
|
import {getBooleanInput} from './util';
|
||||||
|
|
||||||
export async function configureAuthentication() {
|
export async function configureAuthentication(overwriteSettings: boolean) {
|
||||||
const id = core.getInput(constants.INPUT_SERVER_ID);
|
const id = core.getInput(constants.INPUT_SERVER_ID);
|
||||||
const username = core.getInput(constants.INPUT_SERVER_USERNAME);
|
const username = core.getInput(constants.INPUT_SERVER_USERNAME);
|
||||||
const password = core.getInput(constants.INPUT_SERVER_PASSWORD);
|
const password = core.getInput(constants.INPUT_SERVER_PASSWORD);
|
||||||
const settingsDirectory =
|
const settingsDirectory =
|
||||||
core.getInput(constants.INPUT_SETTINGS_PATH) ||
|
core.getInput(constants.INPUT_SETTINGS_PATH) ||
|
||||||
path.join(os.homedir(), constants.M2_DIR);
|
path.join(os.homedir(), constants.M2_DIR);
|
||||||
const overwriteSettings = getBooleanInput(
|
|
||||||
constants.INPUT_OVERWRITE_SETTINGS,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
const gpgPrivateKey =
|
const gpgPrivateKey =
|
||||||
core.getInput(constants.INPUT_GPG_PRIVATE_KEY) ||
|
core.getInput(constants.INPUT_GPG_PRIVATE_KEY) ||
|
||||||
constants.INPUT_DEFAULT_GPG_PRIVATE_KEY;
|
constants.INPUT_DEFAULT_GPG_PRIVATE_KEY;
|
||||||
|
|||||||
@ -11,6 +11,9 @@ export const INPUT_SERVER_USERNAME = 'server-username';
|
|||||||
export const INPUT_SERVER_PASSWORD = 'server-password';
|
export const INPUT_SERVER_PASSWORD = 'server-password';
|
||||||
export const INPUT_SETTINGS_PATH = 'settings-path';
|
export const INPUT_SETTINGS_PATH = 'settings-path';
|
||||||
export const INPUT_OVERWRITE_SETTINGS = 'overwrite-settings';
|
export const INPUT_OVERWRITE_SETTINGS = 'overwrite-settings';
|
||||||
|
export const INPUT_UPDATE_TOOLCHAINS_ONLY = 'update-toolchains-only';
|
||||||
|
export const INPUT_UPDATE_JAVA_HOME = 'update-env-javahome';
|
||||||
|
export const INPUT_ADD_TO_PATH = 'add-to-env-path';
|
||||||
export const INPUT_GPG_PRIVATE_KEY = 'gpg-private-key';
|
export const INPUT_GPG_PRIVATE_KEY = 'gpg-private-key';
|
||||||
export const INPUT_GPG_PASSPHRASE = 'gpg-passphrase';
|
export const INPUT_GPG_PASSPHRASE = 'gpg-passphrase';
|
||||||
|
|
||||||
|
|||||||
@ -14,10 +14,14 @@ import {
|
|||||||
} from '../base-models';
|
} from '../base-models';
|
||||||
import {
|
import {
|
||||||
extractJdkFile,
|
extractJdkFile,
|
||||||
|
getNextPageUrlFromLinkHeader,
|
||||||
getDownloadArchiveExtension,
|
getDownloadArchiveExtension,
|
||||||
isVersionSatisfies,
|
isVersionSatisfies,
|
||||||
renameWinArchive
|
renameWinArchive,
|
||||||
|
MAX_PAGINATION_PAGES,
|
||||||
|
validatePaginationUrl
|
||||||
} from '../../util';
|
} from '../../util';
|
||||||
|
import {TemurinDistribution, TemurinImplementation} from '../temurin/installer';
|
||||||
|
|
||||||
export enum AdoptImplementation {
|
export enum AdoptImplementation {
|
||||||
Hotspot = 'Hotspot',
|
Hotspot = 'Hotspot',
|
||||||
@ -25,15 +29,72 @@ export enum AdoptImplementation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class AdoptDistribution extends JavaBase {
|
export class AdoptDistribution extends JavaBase {
|
||||||
|
private readonly temurinDistribution: TemurinDistribution | null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
installerOptions: JavaInstallerOptions,
|
installerOptions: JavaInstallerOptions,
|
||||||
private readonly jvmImpl: AdoptImplementation
|
private readonly jvmImpl: AdoptImplementation,
|
||||||
|
temurinDistribution: TemurinDistribution | null = null
|
||||||
) {
|
) {
|
||||||
super(`Adopt-${jvmImpl}`, installerOptions);
|
super(`Adopt-${jvmImpl}`, installerOptions);
|
||||||
|
|
||||||
|
if (
|
||||||
|
temurinDistribution !== null &&
|
||||||
|
jvmImpl !== AdoptImplementation.Hotspot
|
||||||
|
) {
|
||||||
|
throw new Error('Only Hotspot JVM is supported by Temurin.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only use the temurin repo for Hotspot JVMs
|
||||||
|
this.temurinDistribution =
|
||||||
|
temurinDistribution ??
|
||||||
|
(jvmImpl === AdoptImplementation.Hotspot
|
||||||
|
? new TemurinDistribution(
|
||||||
|
installerOptions,
|
||||||
|
TemurinImplementation.Hotspot
|
||||||
|
)
|
||||||
|
: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async findPackageForDownload(
|
protected async findPackageForDownload(
|
||||||
version: string
|
version: string
|
||||||
|
): Promise<JavaDownloadRelease> {
|
||||||
|
if (this.jvmImpl === AdoptImplementation.Hotspot) {
|
||||||
|
core.notice(
|
||||||
|
"AdoptOpenJDK has moved to Eclipse Temurin https://github.com/actions/setup-java#supported-distributions please consider changing to the 'temurin' distribution type in your setup-java configuration."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.jvmImpl === AdoptImplementation.Hotspot &&
|
||||||
|
this.temurinDistribution !== null
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
return await this.temurinDistribution.findPackageForDownload(version);
|
||||||
|
} catch (error) {
|
||||||
|
// Log the failure but always fall back to legacy AdoptOpenJDK for resilience
|
||||||
|
const errorMessage =
|
||||||
|
error instanceof Error ? error.message : String(error);
|
||||||
|
if (error instanceof Error && error.name === 'VersionNotFoundError') {
|
||||||
|
core.notice(
|
||||||
|
'The JVM you are looking for could not be found in the Temurin repository, this likely indicates ' +
|
||||||
|
'that you are using an out of date version of Java, consider updating and moving to using the Temurin distribution type in setup-java.'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Log other errors for debugging but gracefully fall back
|
||||||
|
core.debug(
|
||||||
|
`Temurin lookup failed: ${errorMessage}. Falling back to AdoptOpenJDK API.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// failed to find a Temurin version, so fall back to AdoptOpenJDK
|
||||||
|
return this.findPackageForDownloadOldAdoptOpenJdk(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async findPackageForDownloadOldAdoptOpenJdk(
|
||||||
|
version: string
|
||||||
): Promise<JavaDownloadRelease> {
|
): Promise<JavaDownloadRelease> {
|
||||||
const availableVersionsRaw = await this.getAvailableVersions();
|
const availableVersionsRaw = await this.getAvailableVersions();
|
||||||
const availableVersionsWithBinaries = availableVersionsRaw
|
const availableVersionsWithBinaries = availableVersionsRaw
|
||||||
@ -54,15 +115,10 @@ export class AdoptDistribution extends JavaBase {
|
|||||||
const resolvedFullVersion =
|
const resolvedFullVersion =
|
||||||
satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
|
satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
|
||||||
if (!resolvedFullVersion) {
|
if (!resolvedFullVersion) {
|
||||||
const availableOptions = availableVersionsWithBinaries
|
const availableVersionStrings = availableVersionsWithBinaries.map(
|
||||||
.map(item => item.version)
|
item => item.version
|
||||||
.join(', ');
|
|
||||||
const availableOptionsMessage = availableOptions
|
|
||||||
? `\nAvailable versions: ${availableOptions}`
|
|
||||||
: '';
|
|
||||||
throw new Error(
|
|
||||||
`Could not find satisfied version for SemVer '${version}'. ${availableOptionsMessage}`
|
|
||||||
);
|
);
|
||||||
|
throw this.createVersionNotFoundError(version, availableVersionStrings);
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolvedFullVersion;
|
return resolvedFullVersion;
|
||||||
@ -130,30 +186,46 @@ export class AdoptDistribution extends JavaBase {
|
|||||||
`jvm_impl=${this.jvmImpl.toLowerCase()}`
|
`jvm_impl=${this.jvmImpl.toLowerCase()}`
|
||||||
].join('&');
|
].join('&');
|
||||||
|
|
||||||
// need to iterate through all pages to retrieve the list of all versions
|
const requestArguments = `${baseRequestArguments}&page_size=20&page=0`;
|
||||||
// Adopt API doesn't provide way to retrieve the count of pages to iterate so infinity loop
|
let availableVersionsUrl: string | null =
|
||||||
let page_index = 0;
|
`https://api.adoptopenjdk.net/v3/assets/version/${versionRange}?${requestArguments}`;
|
||||||
const availableVersions: IAdoptAvailableVersions[] = [];
|
const availableVersions: IAdoptAvailableVersions[] = [];
|
||||||
while (true) {
|
let pageCount = 0;
|
||||||
const requestArguments = `${baseRequestArguments}&page_size=20&page=${page_index}`;
|
if (core.isDebug()) {
|
||||||
const availableVersionsUrl = `https://api.adoptopenjdk.net/v3/assets/version/${versionRange}?${requestArguments}`;
|
core.debug(`Gathering available versions from '${availableVersionsUrl}'`);
|
||||||
if (core.isDebug() && page_index === 0) {
|
}
|
||||||
// url is identical except page_index so print it once for debug
|
|
||||||
core.debug(
|
|
||||||
`Gathering available versions from '${availableVersionsUrl}'`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const paginationPage = (
|
while (availableVersionsUrl) {
|
||||||
await this.http.getJson<IAdoptAvailableVersions[]>(availableVersionsUrl)
|
pageCount++;
|
||||||
).result;
|
const response =
|
||||||
|
await this.http.getJson<IAdoptAvailableVersions[]>(
|
||||||
|
availableVersionsUrl
|
||||||
|
);
|
||||||
|
const paginationPage = response.result;
|
||||||
|
const nextUrl = getNextPageUrlFromLinkHeader(response.headers);
|
||||||
|
if (
|
||||||
|
nextUrl &&
|
||||||
|
!validatePaginationUrl(nextUrl, 'https://api.adoptopenjdk.net')
|
||||||
|
) {
|
||||||
|
core.warning(
|
||||||
|
`Ignoring pagination link with unexpected origin: ${nextUrl}`
|
||||||
|
);
|
||||||
|
availableVersionsUrl = null;
|
||||||
|
} else {
|
||||||
|
availableVersionsUrl = nextUrl;
|
||||||
|
}
|
||||||
if (paginationPage === null || paginationPage.length === 0) {
|
if (paginationPage === null || paginationPage.length === 0) {
|
||||||
// break infinity loop because we have reached end of pagination
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
availableVersions.push(...paginationPage);
|
availableVersions.push(...paginationPage);
|
||||||
page_index++;
|
|
||||||
|
if (pageCount >= MAX_PAGINATION_PAGES) {
|
||||||
|
core.warning(
|
||||||
|
`Reached pagination safeguard limit (${MAX_PAGINATION_PAGES} pages) while listing Adopt releases.`
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (core.isDebug()) {
|
if (core.isDebug()) {
|
||||||
|
|||||||
@ -10,7 +10,11 @@ import {
|
|||||||
JavaInstallerOptions,
|
JavaInstallerOptions,
|
||||||
JavaInstallerResults
|
JavaInstallerResults
|
||||||
} from './base-models';
|
} from './base-models';
|
||||||
import {MACOS_JAVA_CONTENT_POSTFIX} from '../constants';
|
import {
|
||||||
|
MACOS_JAVA_CONTENT_POSTFIX,
|
||||||
|
INPUT_UPDATE_JAVA_HOME,
|
||||||
|
INPUT_ADD_TO_PATH
|
||||||
|
} from '../constants';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
|
||||||
export abstract class JavaBase {
|
export abstract class JavaBase {
|
||||||
@ -20,6 +24,8 @@ export abstract class JavaBase {
|
|||||||
protected packageType: string;
|
protected packageType: string;
|
||||||
protected stable: boolean;
|
protected stable: boolean;
|
||||||
protected checkLatest: boolean;
|
protected checkLatest: boolean;
|
||||||
|
protected updateEnvJavaHome: boolean;
|
||||||
|
protected addToEnvPath: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected distribution: string,
|
protected distribution: string,
|
||||||
@ -36,6 +42,8 @@ export abstract class JavaBase {
|
|||||||
this.architecture = installerOptions.architecture || os.arch();
|
this.architecture = installerOptions.architecture || os.arch();
|
||||||
this.packageType = installerOptions.packageType;
|
this.packageType = installerOptions.packageType;
|
||||||
this.checkLatest = installerOptions.checkLatest;
|
this.checkLatest = installerOptions.checkLatest;
|
||||||
|
this.updateEnvJavaHome = installerOptions.updateEnvJavaHome;
|
||||||
|
this.addToEnvPath = installerOptions.addToEnvPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract downloadTool(
|
protected abstract downloadTool(
|
||||||
@ -259,10 +267,58 @@ export abstract class JavaBase {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected createVersionNotFoundError(
|
||||||
|
versionOrRange: string,
|
||||||
|
availableVersions?: string[],
|
||||||
|
additionalContext?: string
|
||||||
|
): Error {
|
||||||
|
const parts = [
|
||||||
|
`No matching version found for SemVer '${versionOrRange}'.`,
|
||||||
|
`Distribution: ${this.distribution}`,
|
||||||
|
`Package type: ${this.packageType}`,
|
||||||
|
`Architecture: ${this.architecture}`
|
||||||
|
];
|
||||||
|
|
||||||
|
// Add additional context if provided (e.g., platform/OS info)
|
||||||
|
if (additionalContext) {
|
||||||
|
parts.push(additionalContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (availableVersions && availableVersions.length > 0) {
|
||||||
|
const maxVersionsToShow = core.isDebug() ? availableVersions.length : 50;
|
||||||
|
const versionsToShow = availableVersions.slice(0, maxVersionsToShow);
|
||||||
|
const truncated = availableVersions.length > maxVersionsToShow;
|
||||||
|
|
||||||
|
parts.push(
|
||||||
|
`Available versions: ${versionsToShow.join(', ')}${truncated ? ', ...' : ''}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (truncated) {
|
||||||
|
parts.push(
|
||||||
|
`(showing first ${maxVersionsToShow} of ${availableVersions.length} versions, enable debug mode to see all)`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const error = new Error(parts.join('\n'));
|
||||||
|
error.name = 'VersionNotFoundError';
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
protected setJavaDefault(version: string, toolPath: string) {
|
protected setJavaDefault(version: string, toolPath: string) {
|
||||||
const majorVersion = version.split('.')[0];
|
const majorVersion = version.split('.')[0];
|
||||||
core.exportVariable('JAVA_HOME', toolPath);
|
if (this.updateEnvJavaHome) {
|
||||||
core.addPath(path.join(toolPath, 'bin'));
|
core.exportVariable('JAVA_HOME', toolPath);
|
||||||
|
} else {
|
||||||
|
core.info(
|
||||||
|
`Skip updating env.JAVA_HOME according to ${INPUT_UPDATE_JAVA_HOME}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (this.addToEnvPath) {
|
||||||
|
core.addPath(path.join(toolPath, 'bin'));
|
||||||
|
} else {
|
||||||
|
core.info(`Skip adding to env.PATH according to ${INPUT_ADD_TO_PATH}`);
|
||||||
|
}
|
||||||
core.setOutput('distribution', this.distribution);
|
core.setOutput('distribution', this.distribution);
|
||||||
core.setOutput('path', toolPath);
|
core.setOutput('path', toolPath);
|
||||||
core.setOutput('version', version);
|
core.setOutput('version', version);
|
||||||
|
|||||||
@ -3,6 +3,8 @@ export interface JavaInstallerOptions {
|
|||||||
architecture: string;
|
architecture: string;
|
||||||
packageType: string;
|
packageType: string;
|
||||||
checkLatest: boolean;
|
checkLatest: boolean;
|
||||||
|
updateEnvJavaHome: boolean;
|
||||||
|
addToEnvPath: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface JavaInstallerResults {
|
export interface JavaInstallerResults {
|
||||||
|
|||||||
@ -75,15 +75,10 @@ export class CorrettoDistribution extends JavaBase {
|
|||||||
const resolvedVersion =
|
const resolvedVersion =
|
||||||
matchingVersions.length > 0 ? matchingVersions[0] : null;
|
matchingVersions.length > 0 ? matchingVersions[0] : null;
|
||||||
if (!resolvedVersion) {
|
if (!resolvedVersion) {
|
||||||
const availableOptions = availableVersions
|
const availableVersionStrings = availableVersions.map(
|
||||||
.map(item => item.version)
|
item => item.version
|
||||||
.join(', ');
|
|
||||||
const availableOptionsMessage = availableOptions
|
|
||||||
? `\nAvailable versions: ${availableOptions}`
|
|
||||||
: '';
|
|
||||||
throw new Error(
|
|
||||||
`Could not find satisfied version for SemVer '${version}'. ${availableOptionsMessage}`
|
|
||||||
);
|
);
|
||||||
|
throw this.createVersionNotFoundError(version, availableVersionStrings);
|
||||||
}
|
}
|
||||||
return resolvedVersion;
|
return resolvedVersion;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,9 +51,10 @@ export class DragonwellDistribution extends JavaBase {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!matchedVersions.length) {
|
if (!matchedVersions.length) {
|
||||||
throw new Error(
|
const availableVersionStrings = availableVersions.map(
|
||||||
`Couldn't find any satisfied version for the specified java-version: "${version}" and architecture: "${this.architecture}".`
|
item => item.jdk_version
|
||||||
);
|
);
|
||||||
|
throw this.createVersionNotFoundError(version, availableVersionStrings);
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolvedVersion = matchedVersions[0];
|
const resolvedVersion = matchedVersions[0];
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import {
|
|||||||
} from '../../util';
|
} from '../../util';
|
||||||
|
|
||||||
const GRAALVM_DL_BASE = 'https://download.oracle.com/graalvm';
|
const GRAALVM_DL_BASE = 'https://download.oracle.com/graalvm';
|
||||||
|
const GRAALVM_DOWNLOAD_URL = 'https://www.graalvm.org/downloads/';
|
||||||
const IS_WINDOWS = process.platform === 'win32';
|
const IS_WINDOWS = process.platform === 'win32';
|
||||||
const GRAALVM_PLATFORM = IS_WINDOWS ? 'windows' : process.platform;
|
const GRAALVM_PLATFORM = IS_WINDOWS ? 'windows' : process.platform;
|
||||||
const GRAALVM_MIN_VERSION = 17;
|
const GRAALVM_MIN_VERSION = 17;
|
||||||
@ -149,9 +150,10 @@ export class GraalVMDistribution extends JavaBase {
|
|||||||
const statusCode = response.message.statusCode;
|
const statusCode = response.message.statusCode;
|
||||||
|
|
||||||
if (statusCode === HttpCodes.NotFound) {
|
if (statusCode === HttpCodes.NotFound) {
|
||||||
throw new Error(
|
// Create the standard error with additional hint about checking the download URL
|
||||||
`Could not find GraalVM for SemVer ${range}. Please check if this version is available at ${GRAALVM_DL_BASE}`
|
const error = this.createVersionNotFoundError(range);
|
||||||
);
|
error.message += `\nPlease check if this version is available at ${GRAALVM_DOWNLOAD_URL} . Pick a version from the list.`;
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -180,10 +182,12 @@ export class GraalVMDistribution extends JavaBase {
|
|||||||
|
|
||||||
const latestVersion = versions.find(v => v.latest);
|
const latestVersion = versions.find(v => v.latest);
|
||||||
if (!latestVersion) {
|
if (!latestVersion) {
|
||||||
core.error(
|
const availableVersions = versions.map(v => v.version);
|
||||||
`Available versions: ${versions.map(v => v.version).join(', ')}`
|
throw this.createVersionNotFoundError(
|
||||||
|
javaEaVersion,
|
||||||
|
availableVersions,
|
||||||
|
'Note: No EA build is marked as latest for this version.'
|
||||||
);
|
);
|
||||||
throw new Error(`Unable to find latest version for '${javaEaVersion}'`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
core.debug(`Latest version found: ${latestVersion.version}`);
|
core.debug(`Latest version found: ${latestVersion.version}`);
|
||||||
|
|||||||
@ -44,15 +44,10 @@ export class JetBrainsDistribution extends JavaBase {
|
|||||||
const resolvedFullVersion =
|
const resolvedFullVersion =
|
||||||
satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
|
satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
|
||||||
if (!resolvedFullVersion) {
|
if (!resolvedFullVersion) {
|
||||||
const availableOptions = versionsRaw
|
const availableVersionStrings = versionsRaw.map(
|
||||||
.map(item => `${item.tag_name} (${item.semver}+${item.build})`)
|
item => `${item.tag_name} (${item.semver}+${item.build})`
|
||||||
.join(', ');
|
|
||||||
const availableOptionsMessage = availableOptions
|
|
||||||
? `\nAvailable versions: ${availableOptions}`
|
|
||||||
: '';
|
|
||||||
throw new Error(
|
|
||||||
`Could not find satisfied version for SemVer '${range}'. ${availableOptionsMessage}`
|
|
||||||
);
|
);
|
||||||
|
throw this.createVersionNotFoundError(range, availableVersionStrings);
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolvedFullVersion;
|
return resolvedFullVersion;
|
||||||
|
|||||||
@ -69,15 +69,10 @@ export class LibericaDistributions extends JavaBase {
|
|||||||
.sort((a, b) => -semver.compareBuild(a.version, b.version))[0];
|
.sort((a, b) => -semver.compareBuild(a.version, b.version))[0];
|
||||||
|
|
||||||
if (!satisfiedVersion) {
|
if (!satisfiedVersion) {
|
||||||
const availableOptions = availableVersions
|
const availableVersionStrings = availableVersions.map(
|
||||||
.map(item => item.version)
|
item => item.version
|
||||||
.join(', ');
|
|
||||||
const availableOptionsMessage = availableOptions
|
|
||||||
? `\nAvailable versions: ${availableOptions}`
|
|
||||||
: '';
|
|
||||||
throw new Error(
|
|
||||||
`Could not find satisfied version for semver ${range}. ${availableOptionsMessage}`
|
|
||||||
);
|
);
|
||||||
|
throw this.createVersionNotFoundError(range, availableVersionStrings);
|
||||||
}
|
}
|
||||||
|
|
||||||
return satisfiedVersion;
|
return satisfiedVersion;
|
||||||
|
|||||||
@ -76,11 +76,8 @@ export class MicrosoftDistributions extends JavaBase {
|
|||||||
const foundRelease = await tc.findFromManifest(range, true, manifest, arch);
|
const foundRelease = await tc.findFromManifest(range, true, manifest, arch);
|
||||||
|
|
||||||
if (!foundRelease) {
|
if (!foundRelease) {
|
||||||
throw new Error(
|
const availableVersionStrings = manifest.map(item => item.version);
|
||||||
`Could not find satisfied version for SemVer ${range}.\nAvailable versions: ${manifest
|
throw this.createVersionNotFoundError(range, availableVersionStrings);
|
||||||
.map(item => item.version)
|
|
||||||
.join(', ')}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -112,7 +112,7 @@ export class OracleDistribution extends JavaBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(`Could not find Oracle JDK for SemVer ${range}`);
|
throw this.createVersionNotFoundError(range);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPlatform(platform: NodeJS.Platform = process.platform): OsVersions {
|
public getPlatform(platform: NodeJS.Platform = process.platform): OsVersions {
|
||||||
|
|||||||
@ -49,9 +49,10 @@ export class SapMachineDistribution extends JavaBase {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!matchedVersions.length) {
|
if (!matchedVersions.length) {
|
||||||
throw new Error(
|
const availableVersionStrings = availableVersions.map(
|
||||||
`Couldn't find any satisfied version for the specified java-version: "${version}" and architecture: "${this.architecture}".`
|
item => item.version
|
||||||
);
|
);
|
||||||
|
throw this.createVersionNotFoundError(version, availableVersionStrings);
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolvedVersion = matchedVersions[0];
|
const resolvedVersion = matchedVersions[0];
|
||||||
|
|||||||
@ -7,9 +7,12 @@ import {
|
|||||||
import semver from 'semver';
|
import semver from 'semver';
|
||||||
import {
|
import {
|
||||||
extractJdkFile,
|
extractJdkFile,
|
||||||
|
getNextPageUrlFromLinkHeader,
|
||||||
getDownloadArchiveExtension,
|
getDownloadArchiveExtension,
|
||||||
isVersionSatisfies,
|
isVersionSatisfies,
|
||||||
renameWinArchive
|
renameWinArchive,
|
||||||
|
MAX_PAGINATION_PAGES,
|
||||||
|
validatePaginationUrl
|
||||||
} from '../../util';
|
} from '../../util';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import * as tc from '@actions/tool-cache';
|
import * as tc from '@actions/tool-cache';
|
||||||
@ -79,14 +82,16 @@ export class SemeruDistribution extends JavaBase {
|
|||||||
const resolvedFullVersion =
|
const resolvedFullVersion =
|
||||||
satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
|
satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
|
||||||
if (!resolvedFullVersion) {
|
if (!resolvedFullVersion) {
|
||||||
const availableOptions = availableVersionsWithBinaries
|
const availableVersionStrings = availableVersionsWithBinaries.map(
|
||||||
.map(item => item.version)
|
item => item.version
|
||||||
.join(', ');
|
);
|
||||||
const availableOptionsMessage = availableOptions
|
// Include platform context to help users understand OS-specific version availability
|
||||||
? `\nAvailable versions: ${availableOptions}`
|
// IBM Semeru builds are OS-specific, so platform info aids in troubleshooting
|
||||||
: '';
|
const platformContext = `Platform: ${process.platform}`;
|
||||||
throw new Error(
|
throw this.createVersionNotFoundError(
|
||||||
`Could not find satisfied version for SemVer version '${version}' for your current OS version for ${this.architecture} architecture ${availableOptionsMessage}`
|
version,
|
||||||
|
availableVersionStrings,
|
||||||
|
platformContext
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,32 +158,46 @@ export class SemeruDistribution extends JavaBase {
|
|||||||
`jvm_impl=openj9`
|
`jvm_impl=openj9`
|
||||||
].join('&');
|
].join('&');
|
||||||
|
|
||||||
// need to iterate through all pages to retrieve the list of all versions
|
const requestArguments = `${baseRequestArguments}&page_size=20&page=0`;
|
||||||
// Adoptium API doesn't provide way to retrieve the count of pages to iterate so infinity loop
|
let availableVersionsUrl: string | null =
|
||||||
let page_index = 0;
|
`https://api.adoptopenjdk.net/v3/assets/version/${versionRange}?${requestArguments}`;
|
||||||
const availableVersions: ISemeruAvailableVersions[] = [];
|
const availableVersions: ISemeruAvailableVersions[] = [];
|
||||||
while (true) {
|
let pageCount = 0;
|
||||||
const requestArguments = `${baseRequestArguments}&page_size=20&page=${page_index}`;
|
if (core.isDebug()) {
|
||||||
const availableVersionsUrl = `https://api.adoptopenjdk.net/v3/assets/version/${versionRange}?${requestArguments}`;
|
core.debug(`Gathering available versions from '${availableVersionsUrl}'`);
|
||||||
if (core.isDebug() && page_index === 0) {
|
}
|
||||||
// url is identical except page_index so print it once for debug
|
|
||||||
core.debug(
|
|
||||||
`Gathering available versions from '${availableVersionsUrl}'`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const paginationPage = (
|
while (availableVersionsUrl) {
|
||||||
|
pageCount++;
|
||||||
|
const response =
|
||||||
await this.http.getJson<ISemeruAvailableVersions[]>(
|
await this.http.getJson<ISemeruAvailableVersions[]>(
|
||||||
availableVersionsUrl
|
availableVersionsUrl
|
||||||
)
|
);
|
||||||
).result;
|
const paginationPage = response.result;
|
||||||
|
const nextUrl = getNextPageUrlFromLinkHeader(response.headers);
|
||||||
|
if (
|
||||||
|
nextUrl &&
|
||||||
|
!validatePaginationUrl(nextUrl, 'https://api.adoptopenjdk.net')
|
||||||
|
) {
|
||||||
|
core.warning(
|
||||||
|
`Ignoring pagination link with unexpected origin: ${nextUrl}`
|
||||||
|
);
|
||||||
|
availableVersionsUrl = null;
|
||||||
|
} else {
|
||||||
|
availableVersionsUrl = nextUrl;
|
||||||
|
}
|
||||||
if (paginationPage === null || paginationPage.length === 0) {
|
if (paginationPage === null || paginationPage.length === 0) {
|
||||||
// break infinity loop because we have reached end of pagination
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
availableVersions.push(...paginationPage);
|
availableVersions.push(...paginationPage);
|
||||||
page_index++;
|
|
||||||
|
if (pageCount >= MAX_PAGINATION_PAGES) {
|
||||||
|
core.warning(
|
||||||
|
`Reached pagination safeguard limit (${MAX_PAGINATION_PAGES} pages) while listing Semeru releases.`
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (core.isDebug()) {
|
if (core.isDebug()) {
|
||||||
|
|||||||
@ -14,9 +14,12 @@ import {
|
|||||||
} from '../base-models';
|
} from '../base-models';
|
||||||
import {
|
import {
|
||||||
extractJdkFile,
|
extractJdkFile,
|
||||||
|
getNextPageUrlFromLinkHeader,
|
||||||
getDownloadArchiveExtension,
|
getDownloadArchiveExtension,
|
||||||
isVersionSatisfies,
|
isVersionSatisfies,
|
||||||
renameWinArchive
|
renameWinArchive,
|
||||||
|
MAX_PAGINATION_PAGES,
|
||||||
|
validatePaginationUrl
|
||||||
} from '../../util';
|
} from '../../util';
|
||||||
|
|
||||||
export enum TemurinImplementation {
|
export enum TemurinImplementation {
|
||||||
@ -31,7 +34,10 @@ export class TemurinDistribution extends JavaBase {
|
|||||||
super(`Temurin-${jvmImpl}`, installerOptions);
|
super(`Temurin-${jvmImpl}`, installerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async findPackageForDownload(
|
/**
|
||||||
|
* @internal For cross-distribution reuse only. Not intended as a public API.
|
||||||
|
*/
|
||||||
|
public async findPackageForDownload(
|
||||||
version: string
|
version: string
|
||||||
): Promise<JavaDownloadRelease> {
|
): Promise<JavaDownloadRelease> {
|
||||||
const availableVersionsRaw = await this.getAvailableVersions();
|
const availableVersionsRaw = await this.getAvailableVersions();
|
||||||
@ -57,15 +63,10 @@ export class TemurinDistribution extends JavaBase {
|
|||||||
const resolvedFullVersion =
|
const resolvedFullVersion =
|
||||||
satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
|
satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
|
||||||
if (!resolvedFullVersion) {
|
if (!resolvedFullVersion) {
|
||||||
const availableOptions = availableVersionsWithBinaries
|
const availableVersionStrings = availableVersionsWithBinaries.map(
|
||||||
.map(item => item.version)
|
item => item.version
|
||||||
.join(', ');
|
|
||||||
const availableOptionsMessage = availableOptions
|
|
||||||
? `\nAvailable versions: ${availableOptions}`
|
|
||||||
: '';
|
|
||||||
throw new Error(
|
|
||||||
`Could not find satisfied version for SemVer '${version}'. ${availableOptionsMessage}`
|
|
||||||
);
|
);
|
||||||
|
throw this.createVersionNotFoundError(version, availableVersionStrings);
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolvedFullVersion;
|
return resolvedFullVersion;
|
||||||
@ -128,32 +129,47 @@ export class TemurinDistribution extends JavaBase {
|
|||||||
`jvm_impl=${this.jvmImpl.toLowerCase()}`
|
`jvm_impl=${this.jvmImpl.toLowerCase()}`
|
||||||
].join('&');
|
].join('&');
|
||||||
|
|
||||||
// need to iterate through all pages to retrieve the list of all versions
|
const requestArguments = `${baseRequestArguments}&page_size=20&page=0`;
|
||||||
// Adoptium API doesn't provide way to retrieve the count of pages to iterate so infinity loop
|
let availableVersionsUrl: string | null =
|
||||||
let page_index = 0;
|
`https://api.adoptium.net/v3/assets/version/${versionRange}?${requestArguments}`;
|
||||||
const availableVersions: ITemurinAvailableVersions[] = [];
|
const availableVersions: ITemurinAvailableVersions[] = [];
|
||||||
while (true) {
|
let pageCount = 0;
|
||||||
const requestArguments = `${baseRequestArguments}&page_size=20&page=${page_index}`;
|
if (core.isDebug()) {
|
||||||
const availableVersionsUrl = `https://api.adoptium.net/v3/assets/version/${versionRange}?${requestArguments}`;
|
core.debug(`Gathering available versions from '${availableVersionsUrl}'`);
|
||||||
if (core.isDebug() && page_index === 0) {
|
}
|
||||||
// url is identical except page_index so print it once for debug
|
|
||||||
core.debug(
|
|
||||||
`Gathering available versions from '${availableVersionsUrl}'`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const paginationPage = (
|
while (availableVersionsUrl) {
|
||||||
|
pageCount++;
|
||||||
|
const response =
|
||||||
await this.http.getJson<ITemurinAvailableVersions[]>(
|
await this.http.getJson<ITemurinAvailableVersions[]>(
|
||||||
availableVersionsUrl
|
availableVersionsUrl
|
||||||
)
|
);
|
||||||
).result;
|
const paginationPage = response.result;
|
||||||
|
const nextUrl = getNextPageUrlFromLinkHeader(response.headers);
|
||||||
|
if (
|
||||||
|
nextUrl &&
|
||||||
|
!validatePaginationUrl(nextUrl, 'https://api.adoptium.net')
|
||||||
|
) {
|
||||||
|
core.warning(
|
||||||
|
`Ignoring pagination link with unexpected origin: ${nextUrl}`
|
||||||
|
);
|
||||||
|
availableVersionsUrl = null;
|
||||||
|
} else {
|
||||||
|
availableVersionsUrl = nextUrl;
|
||||||
|
}
|
||||||
|
|
||||||
if (paginationPage === null || paginationPage.length === 0) {
|
if (paginationPage === null || paginationPage.length === 0) {
|
||||||
// break infinity loop because we have reached end of pagination
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
availableVersions.push(...paginationPage);
|
availableVersions.push(...paginationPage);
|
||||||
page_index++;
|
|
||||||
|
if (pageCount >= MAX_PAGINATION_PAGES) {
|
||||||
|
core.warning(
|
||||||
|
`Reached pagination safeguard limit (${MAX_PAGINATION_PAGES} pages) while listing Temurin releases.`
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (core.isDebug()) {
|
if (core.isDebug()) {
|
||||||
@ -176,6 +192,11 @@ export class TemurinDistribution extends JavaBase {
|
|||||||
return 'mac';
|
return 'mac';
|
||||||
case 'win32':
|
case 'win32':
|
||||||
return 'windows';
|
return 'windows';
|
||||||
|
case 'linux':
|
||||||
|
if (fs.existsSync('/etc/alpine-release')) {
|
||||||
|
return 'alpine-linux';
|
||||||
|
}
|
||||||
|
return 'linux';
|
||||||
default:
|
default:
|
||||||
return process.platform;
|
return process.platform;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,15 +57,10 @@ export class ZuluDistribution extends JavaBase {
|
|||||||
const resolvedFullVersion =
|
const resolvedFullVersion =
|
||||||
satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
|
satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
|
||||||
if (!resolvedFullVersion) {
|
if (!resolvedFullVersion) {
|
||||||
const availableOptions = availableVersions
|
const availableVersionStrings = availableVersions.map(
|
||||||
.map(item => item.version)
|
item => item.version
|
||||||
.join(', ');
|
|
||||||
const availableOptionsMessage = availableOptions
|
|
||||||
? `\nAvailable versions: ${availableOptions}`
|
|
||||||
: '';
|
|
||||||
throw new Error(
|
|
||||||
`Could not find satisfied version for semver ${version}. ${availableOptionsMessage}`
|
|
||||||
);
|
);
|
||||||
|
throw this.createVersionNotFoundError(version, availableVersionStrings);
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolvedFullVersion;
|
return resolvedFullVersion;
|
||||||
|
|||||||
@ -13,6 +13,19 @@ import * as path from 'path';
|
|||||||
import {getJavaDistribution} from './distributions/distribution-factory';
|
import {getJavaDistribution} from './distributions/distribution-factory';
|
||||||
import {JavaInstallerOptions} from './distributions/base-models';
|
import {JavaInstallerOptions} from './distributions/base-models';
|
||||||
|
|
||||||
|
interface IInstallerInputsOptions {
|
||||||
|
architecture: string;
|
||||||
|
packageType: string;
|
||||||
|
checkLatest: boolean;
|
||||||
|
distributionName: string;
|
||||||
|
jdkFile: string;
|
||||||
|
toolchainIds: Array<string>;
|
||||||
|
updateToolchainsOnly: boolean;
|
||||||
|
overwriteSettings: boolean;
|
||||||
|
updateEnvJavaHome: boolean;
|
||||||
|
addToEnvPath: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
try {
|
try {
|
||||||
const versions = core.getMultilineInput(constants.INPUT_JAVA_VERSION);
|
const versions = core.getMultilineInput(constants.INPUT_JAVA_VERSION);
|
||||||
@ -28,6 +41,23 @@ async function run() {
|
|||||||
constants.INPUT_CACHE_DEPENDENCY_PATH
|
constants.INPUT_CACHE_DEPENDENCY_PATH
|
||||||
);
|
);
|
||||||
const checkLatest = getBooleanInput(constants.INPUT_CHECK_LATEST, false);
|
const checkLatest = getBooleanInput(constants.INPUT_CHECK_LATEST, false);
|
||||||
|
const updateToolchainsOnly = getBooleanInput(
|
||||||
|
constants.INPUT_UPDATE_TOOLCHAINS_ONLY,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
const overwriteSettings = getBooleanInput(
|
||||||
|
constants.INPUT_OVERWRITE_SETTINGS,
|
||||||
|
!updateToolchainsOnly
|
||||||
|
);
|
||||||
|
const updateEnvJavaHome = getBooleanInput(
|
||||||
|
constants.INPUT_UPDATE_JAVA_HOME,
|
||||||
|
!updateToolchainsOnly
|
||||||
|
);
|
||||||
|
const addToEnvPath = getBooleanInput(
|
||||||
|
constants.INPUT_ADD_TO_PATH,
|
||||||
|
!updateToolchainsOnly
|
||||||
|
);
|
||||||
|
|
||||||
let toolchainIds = core.getMultilineInput(constants.INPUT_MVN_TOOLCHAIN_ID);
|
let toolchainIds = core.getMultilineInput(constants.INPUT_MVN_TOOLCHAIN_ID);
|
||||||
|
|
||||||
core.startGroup('Installed distributions');
|
core.startGroup('Installed distributions');
|
||||||
@ -40,13 +70,17 @@ async function run() {
|
|||||||
throw new Error('java-version or java-version-file input expected');
|
throw new Error('java-version or java-version-file input expected');
|
||||||
}
|
}
|
||||||
|
|
||||||
const installerInputsOptions: installerInputsOptions = {
|
const installerInputsOptions: IInstallerInputsOptions = {
|
||||||
architecture,
|
architecture,
|
||||||
packageType,
|
packageType,
|
||||||
checkLatest,
|
checkLatest,
|
||||||
distributionName,
|
distributionName,
|
||||||
jdkFile,
|
jdkFile,
|
||||||
toolchainIds
|
toolchainIds,
|
||||||
|
updateToolchainsOnly,
|
||||||
|
overwriteSettings,
|
||||||
|
updateEnvJavaHome,
|
||||||
|
addToEnvPath
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!versions.length) {
|
if (!versions.length) {
|
||||||
@ -78,7 +112,7 @@ async function run() {
|
|||||||
const matchersPath = path.join(__dirname, '..', '..', '.github');
|
const matchersPath = path.join(__dirname, '..', '..', '.github');
|
||||||
core.info(`##[add-matcher]${path.join(matchersPath, 'java.json')}`);
|
core.info(`##[add-matcher]${path.join(matchersPath, 'java.json')}`);
|
||||||
|
|
||||||
await auth.configureAuthentication();
|
await auth.configureAuthentication(overwriteSettings);
|
||||||
if (cache && isCacheFeatureAvailable()) {
|
if (cache && isCacheFeatureAvailable()) {
|
||||||
await restore(cache, cacheDependencyPath);
|
await restore(cache, cacheDependencyPath);
|
||||||
}
|
}
|
||||||
@ -91,7 +125,7 @@ run();
|
|||||||
|
|
||||||
async function installVersion(
|
async function installVersion(
|
||||||
version: string,
|
version: string,
|
||||||
options: installerInputsOptions,
|
options: IInstallerInputsOptions,
|
||||||
toolchainId = 0
|
toolchainId = 0
|
||||||
) {
|
) {
|
||||||
const {
|
const {
|
||||||
@ -100,14 +134,20 @@ async function installVersion(
|
|||||||
architecture,
|
architecture,
|
||||||
packageType,
|
packageType,
|
||||||
checkLatest,
|
checkLatest,
|
||||||
toolchainIds
|
toolchainIds,
|
||||||
|
updateToolchainsOnly,
|
||||||
|
overwriteSettings,
|
||||||
|
updateEnvJavaHome,
|
||||||
|
addToEnvPath
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
const installerOptions: JavaInstallerOptions = {
|
const installerOptions: JavaInstallerOptions = {
|
||||||
|
version,
|
||||||
architecture,
|
architecture,
|
||||||
packageType,
|
packageType,
|
||||||
checkLatest,
|
checkLatest,
|
||||||
version
|
updateEnvJavaHome,
|
||||||
|
addToEnvPath
|
||||||
};
|
};
|
||||||
|
|
||||||
const distribution = getJavaDistribution(
|
const distribution = getJavaDistribution(
|
||||||
@ -126,6 +166,7 @@ async function installVersion(
|
|||||||
version,
|
version,
|
||||||
distributionName,
|
distributionName,
|
||||||
result.path,
|
result.path,
|
||||||
|
overwriteSettings || updateToolchainsOnly,
|
||||||
toolchainIds[toolchainId]
|
toolchainIds[toolchainId]
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -136,12 +177,3 @@ async function installVersion(
|
|||||||
core.info(` Path: ${result.path}`);
|
core.info(` Path: ${result.path}`);
|
||||||
core.info('');
|
core.info('');
|
||||||
}
|
}
|
||||||
|
|
||||||
interface installerInputsOptions {
|
|
||||||
architecture: string;
|
|
||||||
packageType: string;
|
|
||||||
checkLatest: boolean;
|
|
||||||
distributionName: string;
|
|
||||||
jdkFile: string;
|
|
||||||
toolchainIds: Array<string>;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@ export async function configureToolchains(
|
|||||||
version: string,
|
version: string,
|
||||||
distributionName: string,
|
distributionName: string,
|
||||||
jdkHome: string,
|
jdkHome: string,
|
||||||
|
updateToolchains: boolean,
|
||||||
toolchainId?: string
|
toolchainId?: string
|
||||||
) {
|
) {
|
||||||
const vendor =
|
const vendor =
|
||||||
@ -27,10 +28,6 @@ export async function configureToolchains(
|
|||||||
const settingsDirectory =
|
const settingsDirectory =
|
||||||
core.getInput(constants.INPUT_SETTINGS_PATH) ||
|
core.getInput(constants.INPUT_SETTINGS_PATH) ||
|
||||||
path.join(os.homedir(), constants.M2_DIR);
|
path.join(os.homedir(), constants.M2_DIR);
|
||||||
const overwriteSettings = getBooleanInput(
|
|
||||||
constants.INPUT_OVERWRITE_SETTINGS,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
await createToolchainsSettings({
|
await createToolchainsSettings({
|
||||||
jdkInfo: {
|
jdkInfo: {
|
||||||
@ -40,21 +37,21 @@ export async function configureToolchains(
|
|||||||
jdkHome
|
jdkHome
|
||||||
},
|
},
|
||||||
settingsDirectory,
|
settingsDirectory,
|
||||||
overwriteSettings
|
updateToolchains
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createToolchainsSettings({
|
export async function createToolchainsSettings({
|
||||||
jdkInfo,
|
jdkInfo,
|
||||||
settingsDirectory,
|
settingsDirectory,
|
||||||
overwriteSettings
|
updateToolchains
|
||||||
}: {
|
}: {
|
||||||
jdkInfo: JdkInfo;
|
jdkInfo: JdkInfo;
|
||||||
settingsDirectory: string;
|
settingsDirectory: string;
|
||||||
overwriteSettings: boolean;
|
updateToolchains: boolean;
|
||||||
}) {
|
}) {
|
||||||
core.info(
|
core.info(
|
||||||
`Creating ${constants.MVN_TOOLCHAINS_FILE} for JDK version ${jdkInfo.version} from ${jdkInfo.vendor}`
|
`Adding a toolchain entry in ${constants.MVN_TOOLCHAINS_FILE} for JDK version ${jdkInfo.version} from ${jdkInfo.vendor}`
|
||||||
);
|
);
|
||||||
// when an alternate m2 location is specified use only that location (no .m2 directory)
|
// when an alternate m2 location is specified use only that location (no .m2 directory)
|
||||||
// otherwise use the home/.m2/ path
|
// otherwise use the home/.m2/ path
|
||||||
@ -71,7 +68,7 @@ export async function createToolchainsSettings({
|
|||||||
await writeToolchainsFileToDisk(
|
await writeToolchainsFileToDisk(
|
||||||
settingsDirectory,
|
settingsDirectory,
|
||||||
updatedToolchains,
|
updatedToolchains,
|
||||||
overwriteSettings
|
updateToolchains
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,17 +143,17 @@ async function readExistingToolchainsFile(directory: string) {
|
|||||||
async function writeToolchainsFileToDisk(
|
async function writeToolchainsFileToDisk(
|
||||||
directory: string,
|
directory: string,
|
||||||
settings: string,
|
settings: string,
|
||||||
overwriteSettings: boolean
|
updateToolchains: boolean
|
||||||
) {
|
) {
|
||||||
const location = path.join(directory, constants.MVN_TOOLCHAINS_FILE);
|
const location = path.join(directory, constants.MVN_TOOLCHAINS_FILE);
|
||||||
const settingsExists = fs.existsSync(location);
|
const toolchainsExists = fs.existsSync(location);
|
||||||
if (settingsExists && overwriteSettings) {
|
if (toolchainsExists && updateToolchains) {
|
||||||
core.info(`Overwriting existing file ${location}`);
|
core.info(`Updating existing file ${location}`);
|
||||||
} else if (!settingsExists) {
|
} else if (!toolchainsExists) {
|
||||||
core.info(`Writing to ${location}`);
|
core.info(`Creating file ${location}`);
|
||||||
} else {
|
} else {
|
||||||
core.info(
|
core.info(
|
||||||
`Skipping generation of ${location} because file already exists and overwriting is not enabled`
|
`Skipping update of ${location} since file already exists and updating is not enabled`
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
49
src/util.ts
49
src/util.ts
@ -201,6 +201,55 @@ export function getGitHubHttpHeaders(): OutgoingHttpHeaders {
|
|||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const MAX_PAGINATION_PAGES = 1000;
|
||||||
|
|
||||||
|
export function getNextPageUrlFromLinkHeader(
|
||||||
|
headers?: Record<string, string | string[] | undefined>
|
||||||
|
): string | null {
|
||||||
|
if (!headers) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const linkHeader = headers.link ?? headers.Link;
|
||||||
|
if (!linkHeader) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizedLinkHeader = Array.isArray(linkHeader)
|
||||||
|
? linkHeader.join(',')
|
||||||
|
: linkHeader;
|
||||||
|
|
||||||
|
// Split into individual link-values and find the one with rel="next"
|
||||||
|
// RFC 8288 allows rel to appear anywhere among the parameters
|
||||||
|
const linkValues = normalizedLinkHeader.split(/,(?=\s*<)/);
|
||||||
|
for (const linkValue of linkValues) {
|
||||||
|
const urlMatch = linkValue.match(/<([^>]+)>/);
|
||||||
|
if (!urlMatch) continue;
|
||||||
|
|
||||||
|
const params = linkValue.slice(urlMatch[0].length);
|
||||||
|
// Use word boundary to match "next" as a standalone relation type
|
||||||
|
// RFC 8288 allows space-separated relation types like rel="next prev"
|
||||||
|
if (/;\s*rel="?[^"]*\bnext\b/i.test(params)) {
|
||||||
|
return urlMatch[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validatePaginationUrl(
|
||||||
|
url: string,
|
||||||
|
allowedOrigin: string
|
||||||
|
): boolean {
|
||||||
|
try {
|
||||||
|
const parsed = new URL(url);
|
||||||
|
const allowed = new URL(allowedOrigin);
|
||||||
|
return parsed.origin === allowed.origin;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Rename archive to add extension because after downloading
|
// Rename archive to add extension because after downloading
|
||||||
// archive does not contain extension type and it leads to some issues
|
// archive does not contain extension type and it leads to some issues
|
||||||
// on Windows runners without PowerShell Core.
|
// on Windows runners without PowerShell Core.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user