mirror of
https://github.com/actions/setup-java.git
synced 2026-08-01 16:22:58 +00:00
Centralize OS/architecture capability validation (#1178)
* Centralize platform capability validation Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 10e35b75-928f-4ef7-984e-605895c5d88e * Address PR review feedback Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 10e35b75-928f-4ef7-984e-605895c5d88e * Regenerate dist after platform validation updates Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 10e35b75-928f-4ef7-984e-605895c5d88e
This commit is contained in:
@@ -260,6 +260,7 @@ describe('getAvailableVersions', () => {
|
||||
|
||||
it.each([
|
||||
['amd64', 'x64'],
|
||||
['arm', 'arm'],
|
||||
['arm64', 'aarch64']
|
||||
])(
|
||||
'defaults to os.arch(): %s mapped to distro arch: %s',
|
||||
|
||||
@@ -299,6 +299,19 @@ describe('getAvailableVersions', () => {
|
||||
expect(availableVersion.url).toBe(expectedLink);
|
||||
}
|
||||
);
|
||||
|
||||
it('keeps the canonical ARM runner value separate from the vendor value', () => {
|
||||
jest.spyOn(os, 'arch').mockReturnValue('arm');
|
||||
const distribution = new CorrettoDistribution({
|
||||
version: '11',
|
||||
architecture: '',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
expect(distribution['architecture']).toBe('armv7');
|
||||
expect(distribution['distributionArchitecture']()).toBe('arm');
|
||||
});
|
||||
});
|
||||
|
||||
const mockPlatform = (
|
||||
|
||||
@@ -4,6 +4,20 @@ import {
|
||||
JAVA_PACKAGE_CAPABILITIES,
|
||||
JavaDistribution
|
||||
} from '../../src/distributions/package-types.js';
|
||||
import os from 'os';
|
||||
import {validateJavaPlatform} from '../../src/distributions/platform-types.js';
|
||||
import {normalizeArchitecture} from '../../src/distributions/platform-types.js';
|
||||
|
||||
const supportedDistributionsOnCurrentPlatform = Object.values(
|
||||
JavaDistribution
|
||||
).filter(distributionName => {
|
||||
try {
|
||||
validateJavaPlatform(distributionName, process.platform, 'x64', '25');
|
||||
return distributionName !== JavaDistribution.JdkFile;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
const installerOptions = (packageType: string, version = '25') => ({
|
||||
version,
|
||||
@@ -13,41 +27,29 @@ const installerOptions = (packageType: string, version = '25') => ({
|
||||
});
|
||||
|
||||
describe('getJavaDistribution', () => {
|
||||
it.each([
|
||||
'adopt',
|
||||
'adopt-hotspot',
|
||||
'adopt-openj9',
|
||||
'temurin',
|
||||
'zulu',
|
||||
'liberica',
|
||||
'liberica-nik',
|
||||
'microsoft',
|
||||
'semeru',
|
||||
'corretto',
|
||||
'oracle',
|
||||
'dragonwell',
|
||||
'sapmachine',
|
||||
'graalvm',
|
||||
'graalvm-community',
|
||||
'jetbrains',
|
||||
'kona',
|
||||
'oracle-openjdk'
|
||||
])('uses the shared retrying HTTP client for %s', distributionName => {
|
||||
const distribution = getJavaDistribution(distributionName, {
|
||||
version: '21',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
it.each(supportedDistributionsOnCurrentPlatform)(
|
||||
'uses the shared retrying HTTP client for %s',
|
||||
distributionName => {
|
||||
const distribution = getJavaDistribution(distributionName, {
|
||||
version: '25',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
expect(distribution).not.toBeNull();
|
||||
expect(distribution!['http']).toBeInstanceOf(RetryingHttpClient);
|
||||
});
|
||||
expect(distribution).not.toBeNull();
|
||||
expect(distribution!['http']).toBeInstanceOf(RetryingHttpClient);
|
||||
}
|
||||
);
|
||||
|
||||
it.each(
|
||||
Object.entries(JAVA_PACKAGE_CAPABILITIES).flatMap(
|
||||
([distributionName, packageTypes]) =>
|
||||
packageTypes.map(packageType => [distributionName, packageType])
|
||||
supportedDistributionsOnCurrentPlatform.includes(
|
||||
distributionName as JavaDistribution
|
||||
) || distributionName === JavaDistribution.JdkFile
|
||||
? packageTypes.map(packageType => [distributionName, packageType])
|
||||
: []
|
||||
)
|
||||
)('accepts %s with java-package %s', (distributionName, packageType) => {
|
||||
expect(
|
||||
@@ -111,4 +113,36 @@ describe('getJavaDistribution', () => {
|
||||
)
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it.each([
|
||||
['amd64', 'x64'],
|
||||
['ia32', 'x86'],
|
||||
['arm64', 'aarch64']
|
||||
])('passes normalized architecture %s as %s', (input, expected) => {
|
||||
const normalized = getJavaDistribution(JavaDistribution.JdkFile, {
|
||||
...installerOptions('jdk'),
|
||||
architecture: input
|
||||
});
|
||||
|
||||
expect(normalized!['architecture']).toBe(expected);
|
||||
});
|
||||
|
||||
it('uses the runner architecture when the input is empty', () => {
|
||||
const distribution = getJavaDistribution(JavaDistribution.Temurin, {
|
||||
...installerOptions('jdk'),
|
||||
architecture: ''
|
||||
});
|
||||
|
||||
const expected = normalizeArchitecture(os.arch());
|
||||
expect(distribution!['architecture']).toBe(expected);
|
||||
});
|
||||
|
||||
it('rejects an unsupported combination before creating an HTTP client', () => {
|
||||
expect(() =>
|
||||
getJavaDistribution(JavaDistribution.Oracle, {
|
||||
...installerOptions('jdk'),
|
||||
architecture: 'x86'
|
||||
})
|
||||
).toThrow(/does not support operating system/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -291,6 +291,7 @@ describe('getAvailableVersions', () => {
|
||||
|
||||
it.each([
|
||||
['amd64', 'x64'],
|
||||
['arm', 'arm'],
|
||||
['arm64', 'aarch64']
|
||||
])(
|
||||
'defaults to os.arch(): %s mapped to distro arch: %s',
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import {
|
||||
JAVA_PLATFORM_CAPABILITIES,
|
||||
normalizeArchitecture,
|
||||
validateJavaPlatform
|
||||
} from '../src/distributions/platform-types.js';
|
||||
import {JavaDistribution} from '../src/distributions/package-types.js';
|
||||
|
||||
describe('Java platform capabilities', () => {
|
||||
it('declares a capability for every distribution', () => {
|
||||
expect(Object.keys(JAVA_PLATFORM_CAPABILITIES).sort()).toEqual(
|
||||
Object.values(JavaDistribution).sort()
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
['x64', 'x64'],
|
||||
['amd64', 'x64'],
|
||||
['x86', 'x86'],
|
||||
['ia32', 'x86'],
|
||||
['arm', 'armv7'],
|
||||
['aarch64', 'aarch64'],
|
||||
['arm64', 'aarch64'],
|
||||
['ppc64le', 'ppc64le'],
|
||||
['s390x', 's390x']
|
||||
])('normalizes architecture %s to %s', (input, expected) => {
|
||||
expect(normalizeArchitecture(input)).toBe(expected);
|
||||
});
|
||||
|
||||
it('uses the normalized architecture for validation', () => {
|
||||
expect(validateJavaPlatform('microsoft', 'linux', 'arm64', '25')).toBe(
|
||||
'aarch64'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects OS-specific restrictions with a consistent diagnostic', () => {
|
||||
expect(() =>
|
||||
validateJavaPlatform('oracle', 'win32', 'arm64', '21')
|
||||
).toThrow(
|
||||
"Distribution 'oracle' does not support operating system 'windows' with architecture 'aarch64' for Java version '21'. Supported combinations: linux (x64, aarch64); macos (x64, aarch64); windows (x64)."
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects version-dependent architecture restrictions', () => {
|
||||
expect(() =>
|
||||
validateJavaPlatform('corretto', 'linux', 'x86', '17')
|
||||
).toThrow(/x86 \(<12\)/);
|
||||
expect(() =>
|
||||
validateJavaPlatform('corretto', 'linux', 'x86', '17.0.2.8.1')
|
||||
).toThrow(/x86 \(<12\)/);
|
||||
expect(validateJavaPlatform('corretto', 'linux', 'x86', '11')).toBe('x86');
|
||||
});
|
||||
|
||||
it.each(['corretto', 'kona'])(
|
||||
'rejects Windows aarch64 for %s',
|
||||
distributionName => {
|
||||
expect(() =>
|
||||
validateJavaPlatform(distributionName, 'win32', 'arm64', '21')
|
||||
).toThrow(/does not support operating system 'windows'/);
|
||||
}
|
||||
);
|
||||
|
||||
it('keeps Adopt HotSpot aliases aligned with the Temurin-first resolver', () => {
|
||||
expect(validateJavaPlatform('adopt', 'darwin', 'arm64', '21')).toBe(
|
||||
'aarch64'
|
||||
);
|
||||
expect(validateJavaPlatform('adopt-hotspot', 'win32', 'arm64', '21')).toBe(
|
||||
'aarch64'
|
||||
);
|
||||
expect(() =>
|
||||
validateJavaPlatform('adopt-openj9', 'darwin', 'arm64', '16')
|
||||
).toThrow(/does not support operating system 'macos'/);
|
||||
});
|
||||
|
||||
it('allows local archives on any platform and architecture', () => {
|
||||
expect(validateJavaPlatform('jdkfile', 'aix', 'mips64', '21')).toBe(
|
||||
'mips64'
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps the documented architecture contract aligned', () => {
|
||||
const repositoryRoot = process.cwd();
|
||||
const readRepositoryFile = (filePath: string) =>
|
||||
fs.readFileSync(path.join(repositoryRoot, filePath), 'utf8');
|
||||
|
||||
for (const filePath of ['action.yml', 'README.md']) {
|
||||
const content = readRepositoryFile(filePath);
|
||||
for (const architecture of [
|
||||
'x86',
|
||||
'x64',
|
||||
'armv7',
|
||||
'aarch64',
|
||||
'ppc64le',
|
||||
'ppc64',
|
||||
's390x'
|
||||
]) {
|
||||
expect(content).toContain(architecture);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it.each(Object.entries(JAVA_PLATFORM_CAPABILITIES))(
|
||||
'keeps the advanced compatibility table aligned for %s',
|
||||
(distributionName, capability) => {
|
||||
const advancedUsage = fs.readFileSync(
|
||||
path.join(process.cwd(), 'docs/advanced-usage.md'),
|
||||
'utf8'
|
||||
);
|
||||
const compatibilityTable = advancedUsage.slice(
|
||||
advancedUsage.indexOf('## Platform and architecture compatibility')
|
||||
);
|
||||
const compatibilityRow = compatibilityTable
|
||||
.split('\n')
|
||||
.find(
|
||||
line =>
|
||||
line.startsWith('|') && line.includes(`\`${distributionName}\``)
|
||||
);
|
||||
|
||||
expect(compatibilityRow).toBeDefined();
|
||||
if (!('platforms' in capability)) {
|
||||
expect(compatibilityRow).toContain('Any');
|
||||
return;
|
||||
}
|
||||
|
||||
const architectures = new Set(
|
||||
Object.values(capability.platforms)
|
||||
.flat()
|
||||
.map(item => (typeof item === 'string' ? item : item.architecture))
|
||||
);
|
||||
for (const architecture of architectures) {
|
||||
expect(compatibilityRow).toContain(`\`${architecture}\``);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user