Files
setup-java/__tests__/util.test.ts

434 lines
14 KiB
TypeScript
Raw Normal View History

import {
jest,
describe,
it,
expect,
beforeEach,
afterAll,
afterEach
} from '@jest/globals';
import {fileURLToPath} from 'url';
import * as fs from 'fs';
import * as path from 'path';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// Mock @actions/cache
jest.unstable_mockModule('@actions/cache', () => ({
isFeatureAvailable: jest.fn(),
saveCache: jest.fn(),
restoreCache: jest.fn()
}));
// Mock @actions/core
jest.unstable_mockModule('@actions/core', () => ({
getInput: jest.fn(),
getBooleanInput: jest.fn(),
getMultilineInput: jest.fn(),
setOutput: jest.fn(),
setFailed: jest.fn(),
warning: jest.fn(),
info: jest.fn(),
debug: jest.fn(),
error: jest.fn(),
notice: jest.fn(),
startGroup: jest.fn(),
endGroup: jest.fn(),
addPath: jest.fn(),
exportVariable: jest.fn(),
saveState: jest.fn(),
getState: jest.fn(),
setSecret: jest.fn(),
isDebug: jest.fn(() => false),
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
toPlatformPath: jest.fn((p: string) => p),
toWin32Path: jest.fn((p: string) => p),
toPosixPath: jest.fn((p: string) => p)
}));
const cache = await import('@actions/cache');
const core = await import('@actions/core');
const {
convertVersionToSemver,
Implement pagination with link headers for Adoptium based apis (#1014) * Use Link headers for Adoptium pagination * Fix nullable pagination URL types and rebuild dist * Add 1000-page safeguard for JetBrains pagination * Adjust plan for pagination safeguard scope * Move pagination safeguard to non-JetBrains installers * Add 1000-page safeguard to Adopt Temurin and Semeru pagination * Fix Prettier formatting in adopt, semeru, and temurin installer files * Fix CI audit failure by updating vulnerable transitive deps * Address PR review: RFC-compliant Link parsing, SSRF validation, centralized constant - Make getNextPageUrlFromLinkHeader RFC 8288 compliant by splitting link-values and checking for rel=next anywhere in the parameters, not just as the first parameter after the semicolon. - Add validatePaginationUrl utility to reject pagination URLs that point to unexpected origins (SSRF mitigation). - Centralize MAX_PAGINATION_PAGES in util.ts instead of duplicating across Adopt, Semeru, and Temurin installers. - Add tests for rel not being the first parameter, and for URL origin validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address code review feedback on pagination implementation - Tighten rel regex with word boundary to prevent false positives (e.g., rel="nextsomething" no longer matches). - Use parsed.origin comparison in validatePaginationUrl to correctly handle explicit default ports (e.g., :443 for HTTPS). - Fix pagination safeguard tests to use same-origin URLs so they actually exercise the 1000-page limit instead of being rejected by origin validation on the first request. - Add test for rel="nextsomething" not matching. - Add test for explicit default port acceptance. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix prettier formatting in util.test.ts * Rebuild dist/ to fix check-dist CI failure --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-12 11:50:16 +01:00
getNextPageUrlFromLinkHeader,
getVersionFromFileContent,
isVersionSatisfies,
2024-10-21 19:57:52 +02:00
isCacheFeatureAvailable,
Implement pagination with link headers for Adoptium based apis (#1014) * Use Link headers for Adoptium pagination * Fix nullable pagination URL types and rebuild dist * Add 1000-page safeguard for JetBrains pagination * Adjust plan for pagination safeguard scope * Move pagination safeguard to non-JetBrains installers * Add 1000-page safeguard to Adopt Temurin and Semeru pagination * Fix Prettier formatting in adopt, semeru, and temurin installer files * Fix CI audit failure by updating vulnerable transitive deps * Address PR review: RFC-compliant Link parsing, SSRF validation, centralized constant - Make getNextPageUrlFromLinkHeader RFC 8288 compliant by splitting link-values and checking for rel=next anywhere in the parameters, not just as the first parameter after the semicolon. - Add validatePaginationUrl utility to reject pagination URLs that point to unexpected origins (SSRF mitigation). - Centralize MAX_PAGINATION_PAGES in util.ts instead of duplicating across Adopt, Semeru, and Temurin installers. - Add tests for rel not being the first parameter, and for URL origin validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address code review feedback on pagination implementation - Tighten rel regex with word boundary to prevent false positives (e.g., rel="nextsomething" no longer matches). - Use parsed.origin comparison in validatePaginationUrl to correctly handle explicit default ports (e.g., :443 for HTTPS). - Fix pagination safeguard tests to use same-origin URLs so they actually exercise the 1000-page limit instead of being rejected by origin validation on the first request. - Add test for rel="nextsomething" not matching. - Add test for explicit default port acceptance. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix prettier formatting in util.test.ts * Rebuild dist/ to fix check-dist CI failure --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-12 11:50:16 +01:00
isGhes,
Support pinning java-version as "latest" (#1093) * Support pinning java-version as "latest" Add a `latest` alias for the `java-version` input that floats to the newest available stable (GA) release. It is normalized to the SemVer wildcard at the base-installer layer and always resolves from remote (like `check-latest: true`). List-based distributions resolve it automatically via the existing newest-first matching. Corretto selects its newest available major; Oracle and GraalVM look up the newest GA major via the Adoptium API and request it, failing with an actionable error if that major isn't published yet. The jdkfile distribution rejects `latest`. Closes #832 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Clarify latest note for oracle/graalvm version resolution vs download Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * graalvm-community: float latest to its own newest GA release GraalVM Community publishes its releases on GitHub, so the `latest` alias now matches against that real release list using the SemVer wildcard instead of asking the Adoptium API for the newest GA major. This prevents `latest` from hard-failing when GraalVM lags behind a freshly released Java major (e.g. Adoptium reports 26 before GraalVM ships it). Oracle GraalVM has no listing endpoint, so it keeps deriving the newest major from Adoptium and errors clearly if that major is not yet published. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Give latest+qualifier inputs (e.g. latest-ea) a targeted error Inputs like 'latest-ea' had their '-ea' suffix stripped and fell through to the generic SemVer validation, failing with a confusing "'latest' is not valid SemVer" message even though 'latest' is supported. Add an explicit guard so any 'latest*' value other than exactly 'latest' throws a targeted error explaining that 'latest' resolves GA releases only and cannot be combined with '-ea' or other qualifiers. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-09 20:11:03 -04:00
validatePaginationUrl,
getLatestMajorVersion
} = await import('../src/util.js');
Merge "v2-preview" branch into "main" (#150) * actions/setup-java@v2 - Support different distributions (#132) * Implement support for custom vendors in setup-java * minor improvements * minor refactoring * Add unit tests and e2e tests * Update documentation for setup-java@v2 release * minor improvements * regenerate dist * fix comments * resolve comments * resolve comments * fix tests * Update README.md Co-authored-by: George Adams <george.adams@microsoft.com> * Apply suggestions from code review Co-authored-by: Konrad Pabjan <konradpabjan@github.com> * fix minor nitpicks * handle 4th digit * pull latest main * Update README.md * rename adoptium to adopt * rename adoptium to adopt * rename adoptium to adopt * Update README.md * make java-version and distribution required for action * update readme * fix tests * fix e2e tests Co-authored-by: George Adams <george.adams@microsoft.com> Co-authored-by: Konrad Pabjan <konradpabjan@github.com> * Add "overwrite-settings" input parameter (#136) * add overwrite-settings parameter * fix e2e tests * print debug * fix e2e tests * add comment * remove comment * Add "Contents/Home" postfix on macOS if provider creates it (#139) * Update e2e-versions.yml * Update e2e-versions.yml * implement fix * Update e2e-versions.yml * Update installer.ts * fix filter logic * Update e2e-versions.yml * remove extra logic * Update e2e-versions.yml * Add check-latest flag (#141) * add changes for check-latest * run prerelease script * resolving comments * fixing tests * fix spelling * improve core.info messages * run format * run prerelease * change version to fix test * resolve comment for check-latest * Update README.md * added hosted tool cache section * Apply suggestions from code review Co-authored-by: Maxim Lobanov <v-malob@microsoft.com> Co-authored-by: Konrad Pabjan <konradpabjan@github.com> * Avoid "+" sign in Java path in v2-preview (#145) * try to handle _ versions * more logs * more debug * test 1 * more fixes * fix typo * Update e2e-versions.yml * add unit-tests * remove debug info from tests * debug pre-cached versions * change e2e tests to ubuntu-latest * update npm licenses Co-authored-by: George Adams <george.adams@microsoft.com> Co-authored-by: Konrad Pabjan <konradpabjan@github.com> Co-authored-by: Dmitry Shibanov <dmitry-shibanov@github.com>
2021-04-05 13:02:27 +03:00
describe('isVersionSatisfies', () => {
it.each([
['x', '11.0.0', true],
['3', '3.7.1', true],
['3', '3.7.2', true],
['3', '3.7.2+4', true],
['2.5', '2.5.0', true],
['2.5', '2.5.0+1', true],
['2.5', '2.6.1', false],
['2.5.1', '2.5.0', false],
['2.5.1+3', '2.5.0', false],
['2.5.1+3', '2.5.1+3', true],
['2.5.1+3', '2.5.1+2', false],
['15.0.0+14', '15.0.0+14.1.202003190635', false],
['15.0.0+14.1.202003190635', '15.0.0+14.1.202003190635', true],
// 4-segment versions (e.g. JetBrains Runtime '17.0.8.1+1080.1') are not
// valid semver — they should be rejected, not throw.
['25.0.3+480.61', '17.0.8.1+1080.1', false],
['17', '17.0.8.1+1080.1', false]
])(
'%s, %s -> %s',
(inputRange: string, inputVersion: string, expected: boolean) => {
const actual = isVersionSatisfies(inputRange, inputVersion);
expect(actual).toBe(expected);
}
);
2020-05-02 04:33:15 -07:00
});
describe('isCacheFeatureAvailable', () => {
it('isCacheFeatureAvailable disabled on GHES', () => {
(cache.isFeatureAvailable as jest.Mock<any>).mockImplementation(
() => false
);
const infoMock = core.warning as jest.Mock;
const message =
'Caching is only supported on GHES version >= 3.5. If you are on a version >= 3.5, please check with your GHES admin if the Actions cache service is enabled or not.';
try {
process.env['GITHUB_SERVER_URL'] = 'http://example.com';
expect(isCacheFeatureAvailable()).toBeFalsy();
expect(infoMock).toHaveBeenCalledWith(message);
} finally {
delete process.env['GITHUB_SERVER_URL'];
}
});
it('isCacheFeatureAvailable disabled on dotcom', () => {
(cache.isFeatureAvailable as jest.Mock<any>).mockImplementation(
() => false
);
const infoMock = core.warning as jest.Mock;
const message =
'The runner was not able to contact the cache service. Caching will be skipped';
try {
process.env['GITHUB_SERVER_URL'] = 'http://github.com';
expect(isCacheFeatureAvailable()).toBe(false);
expect(infoMock).toHaveBeenCalledWith(message);
} finally {
delete process.env['GITHUB_SERVER_URL'];
}
});
it('isCacheFeatureAvailable is enabled', () => {
(cache.isFeatureAvailable as jest.Mock<any>).mockImplementation(() => true);
expect(isCacheFeatureAvailable()).toBe(true);
});
afterEach(() => {
jest.resetAllMocks();
jest.clearAllMocks();
});
});
describe('convertVersionToSemver', () => {
it.each([
['12', '12'],
['12.0', '12.0'],
['12.0.2', '12.0.2'],
['12.0.2.1', '12.0.2+1'],
['12.0.2.1.0', '12.0.2+1.0']
])('%s -> %s', (input: string, expected: string) => {
const actual = convertVersionToSemver(input);
expect(actual).toBe(expected);
});
});
2024-10-21 19:57:52 +02:00
Implement pagination with link headers for Adoptium based apis (#1014) * Use Link headers for Adoptium pagination * Fix nullable pagination URL types and rebuild dist * Add 1000-page safeguard for JetBrains pagination * Adjust plan for pagination safeguard scope * Move pagination safeguard to non-JetBrains installers * Add 1000-page safeguard to Adopt Temurin and Semeru pagination * Fix Prettier formatting in adopt, semeru, and temurin installer files * Fix CI audit failure by updating vulnerable transitive deps * Address PR review: RFC-compliant Link parsing, SSRF validation, centralized constant - Make getNextPageUrlFromLinkHeader RFC 8288 compliant by splitting link-values and checking for rel=next anywhere in the parameters, not just as the first parameter after the semicolon. - Add validatePaginationUrl utility to reject pagination URLs that point to unexpected origins (SSRF mitigation). - Centralize MAX_PAGINATION_PAGES in util.ts instead of duplicating across Adopt, Semeru, and Temurin installers. - Add tests for rel not being the first parameter, and for URL origin validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address code review feedback on pagination implementation - Tighten rel regex with word boundary to prevent false positives (e.g., rel="nextsomething" no longer matches). - Use parsed.origin comparison in validatePaginationUrl to correctly handle explicit default ports (e.g., :443 for HTTPS). - Fix pagination safeguard tests to use same-origin URLs so they actually exercise the 1000-page limit instead of being rejected by origin validation on the first request. - Add test for rel="nextsomething" not matching. - Add test for explicit default port acceptance. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix prettier formatting in util.test.ts * Rebuild dist/ to fix check-dist CI failure --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-12 11:50:16 +01:00
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('.sdkmanrc', () => {
it.each([
['java=11.0.20.1-tem', '11.0.20', 'temurin'],
['java = 11.0.20.1-tem', '11.0.20', 'temurin'],
['java=11.0.20.1-tem # a comment in sdkmanrc', '11.0.20', 'temurin'],
['java=11.0.20.1-tem\n#java=21.0.20.1-tem\n', '11.0.20', 'temurin'], // choose first match
['java=11.0.20.1-tem\njava=21.0.20.1-tem\n', '11.0.20', 'temurin'], // choose first match
['#java=11.0.20.1-tem\njava=21.0.20.1-tem\n', '21.0.20', 'temurin'], // first one is 'commented' in .sdkmanrc
['java=21.0.5-zulu', '21.0.5', 'zulu'],
['java=17.0.13-albba', '17.0.13', 'dragonwell'],
['java=17.0.13-amzn', '17', 'corretto'],
['java=21.0.5-graal', '21.0.5', 'graalvm'],
['java=17.0.9-graalce', '17.0.9', 'graalvm'],
['java=11.0.25-librca', '11.0.25', 'liberica'],
['java=11.0.25-ms', '11.0.25', 'microsoft'],
['java=21.0.5-oracle', '21.0.5', 'oracle'],
['java=11.0.25-sapmchn', '11.0.25', 'sapmachine'],
['java=21.0.5-jbr', '21.0.5', 'jetbrains'],
['java=11.0.25-sem', '11.0.25', 'semeru'],
['java=17.0.13-dragonwell', '17.0.13', 'dragonwell'],
['java=21.0.5-kona', '21.0.5', 'kona']
])(
'parsing %s should return version %s and distribution %s',
(content: string, expectedVersion: string, expectedDist: string) => {
const actual = getVersionFromFileContent(
content,
'openjdk',
'.sdkmanrc'
);
expect(actual?.version).toBe(expectedVersion);
expect(actual?.distribution).toBe(expectedDist);
}
);
it('should warn and return undefined distribution for unknown identifier', () => {
const warnSpy = jest.spyOn(core, 'warning');
const actual = getVersionFromFileContent(
'java=21.0.5-unknown',
'temurin',
'.sdkmanrc'
);
expect(actual?.version).toBe('21.0.5');
expect(actual?.distribution).toBeUndefined();
expect(warnSpy).toHaveBeenCalledWith(
expect.stringContaining('Unknown SDKMAN distribution identifier')
);
});
it('should return version without distribution when no suffix provided', () => {
const actual = getVersionFromFileContent(
'java=11.0.20',
'temurin',
'.sdkmanrc'
);
expect(actual?.version).toBe('11.0.20');
expect(actual?.distribution).toBeUndefined();
});
describe('known versions', () => {
const csv = fs.readFileSync(
path.join(__dirname, 'data/sdkman-java-versions.csv'),
'utf8'
);
const versions = csv.split('\n').map(r => r.split(', '));
it.each(versions)(
'parsing %s should return %s',
(sdkmanJavaVersion: string, expected: string) => {
const asContent = `java=${sdkmanJavaVersion}`;
const actual = getVersionFromFileContent(
asContent,
'openjdk',
'.sdkmanrc'
);
expect(actual?.version).toBe(expected);
}
);
});
});
describe('.tool-versions', () => {
it.each([
['java temurin-17.0.3+7', '17.0.3+7', 'temurin'],
['java temurin-jre-17.0.3+7', '17.0.3+7', 'temurin'],
['java adoptopenjdk-11.0.16+8', '11.0.16+8', 'temurin'],
['java adoptopenjdk-openj9-11.0.16+8', '11.0.16+8', 'temurin'],
['java zulu-11.56.19', '11.56.19', 'zulu'],
['java corretto-17.0.13.11.1', '17', 'corretto'], // corretto -> major only
['java liberica-11.0.15+10', '11.0.15+10', 'liberica'],
['java microsoft-11.0.13.8.1', '11.0.13', 'microsoft'],
['java semeru-openj9-11.0.25+9', '11.0.25+9', 'semeru'],
['java ibm-openj9-11.0.25+9', '11.0.25+9', 'semeru'],
['java dragonwell-17.0.13.0.13+11', '17.0.13', 'dragonwell'],
['java graalvm-22.3.0+java17', '22.3.0+java17', 'graalvm'],
['java graalvm-community-22.3.0', '22.3.0', 'graalvm-community'],
['java oracle-graalvm-21.0.5', '21.0.5', 'graalvm'],
['java oracle-21.0.5', '21.0.5', 'oracle'],
['java sapmachine-21.0.5', '21.0.5', 'sapmachine'],
['java kona-17.0.13', '17.0.13', 'kona'],
['java jetbrains-21.0.5', '21.0.5', 'jetbrains']
])(
'parsing %s should return version %s and distribution %s',
(content: string, expectedVersion: string, expectedDist: string) => {
const actual = getVersionFromFileContent(
content,
'openjdk',
'.tool-versions'
);
expect(actual?.version).toBe(expectedVersion);
expect(actual?.distribution).toBe(expectedDist);
}
);
it.each([
['java 17.0.7', '17.0.7'],
['java 17', '17'],
['java 1.8', '8'],
['java 21-ea', '21-ea']
])(
'parsing prefix-less %s should return version %s and no distribution',
(content: string, expectedVersion: string) => {
const actual = getVersionFromFileContent(
content,
'temurin',
'.tool-versions'
);
expect(actual?.version).toBe(expectedVersion);
expect(actual?.distribution).toBeUndefined();
}
);
it('should warn and return undefined distribution for unsupported vendor', () => {
const warnSpy = jest.spyOn(core, 'warning');
const actual = getVersionFromFileContent(
'java openjdk-17.0.7',
'temurin',
'.tool-versions'
);
expect(actual?.version).toBe('17.0.7');
expect(actual?.distribution).toBeUndefined();
expect(warnSpy).toHaveBeenCalledWith(
expect.stringContaining('Unknown asdf distribution identifier')
);
});
});
});
2024-10-21 19:57:52 +02:00
describe('isGhes', () => {
const pristineEnv = process.env;
beforeEach(() => {
process.env = {...pristineEnv};
});
afterAll(() => {
process.env = pristineEnv;
});
it('returns false when the GITHUB_SERVER_URL environment variable is not defined', async () => {
delete process.env['GITHUB_SERVER_URL'];
expect(isGhes()).toBeFalsy();
});
it('returns false when the GITHUB_SERVER_URL environment variable is set to github.com', async () => {
process.env['GITHUB_SERVER_URL'] = 'https://github.com';
expect(isGhes()).toBeFalsy();
});
it('returns false when the GITHUB_SERVER_URL environment variable is set to a GitHub Enterprise Cloud-style URL', async () => {
process.env['GITHUB_SERVER_URL'] = 'https://contoso.ghe.com';
expect(isGhes()).toBeFalsy();
});
it('returns false when the GITHUB_SERVER_URL environment variable has a .localhost suffix', async () => {
process.env['GITHUB_SERVER_URL'] = 'https://mock-github.localhost';
expect(isGhes()).toBeFalsy();
});
it('returns true when the GITHUB_SERVER_URL environment variable is set to some other URL', async () => {
process.env['GITHUB_SERVER_URL'] = 'https://src.onpremise.fabrikam.com';
expect(isGhes()).toBeTruthy();
});
});
Support pinning java-version as "latest" (#1093) * Support pinning java-version as "latest" Add a `latest` alias for the `java-version` input that floats to the newest available stable (GA) release. It is normalized to the SemVer wildcard at the base-installer layer and always resolves from remote (like `check-latest: true`). List-based distributions resolve it automatically via the existing newest-first matching. Corretto selects its newest available major; Oracle and GraalVM look up the newest GA major via the Adoptium API and request it, failing with an actionable error if that major isn't published yet. The jdkfile distribution rejects `latest`. Closes #832 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Clarify latest note for oracle/graalvm version resolution vs download Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * graalvm-community: float latest to its own newest GA release GraalVM Community publishes its releases on GitHub, so the `latest` alias now matches against that real release list using the SemVer wildcard instead of asking the Adoptium API for the newest GA major. This prevents `latest` from hard-failing when GraalVM lags behind a freshly released Java major (e.g. Adoptium reports 26 before GraalVM ships it). Oracle GraalVM has no listing endpoint, so it keeps deriving the newest major from Adoptium and errors clearly if that major is not yet published. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Give latest+qualifier inputs (e.g. latest-ea) a targeted error Inputs like 'latest-ea' had their '-ea' suffix stripped and fell through to the generic SemVer validation, failing with a confusing "'latest' is not valid SemVer" message even though 'latest' is supported. Add an explicit guard so any 'latest*' value other than exactly 'latest' throws a targeted error explaining that 'latest' resolves GA releases only and cannot be combined with '-ea' or other qualifiers. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-09 20:11:03 -04:00
describe('getLatestMajorVersion', () => {
const makeHttp = (getJson: jest.Mock) =>
({getJson}) as unknown as import('@actions/http-client').HttpClient;
it('returns most_recent_feature_release from the Adoptium API', async () => {
const getJson = jest.fn(async () => ({
statusCode: 200,
result: {most_recent_feature_release: 25},
headers: {}
}));
await expect(getLatestMajorVersion(makeHttp(getJson))).resolves.toBe(25);
expect(getJson).toHaveBeenCalledWith(
'https://api.adoptium.net/v3/info/available_releases'
);
});
it('throws when the response does not contain a usable value', async () => {
const getJson = jest.fn(async () => ({
statusCode: 200,
result: {},
headers: {}
}));
await expect(getLatestMajorVersion(makeHttp(getJson))).rejects.toThrow(
'Could not determine the latest available Java major version'
);
});
});