mirror of
https://gitea.com/actions/setup-java.git
synced 2026-07-10 19:31:55 +08:00
Compare commits
1 Commits
brunoborge
...
copilot/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2cb7bd967e |
13
.github/java.json
vendored
13
.github/java.json
vendored
@@ -21,19 +21,6 @@
|
||||
"message": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "maven-javac",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^\\[(WARNING|ERROR)\\]\\s+(.+?\\.java):\\[(\\d+),(\\d+)\\]\\s+(.+)$",
|
||||
"severity": 1,
|
||||
"file": 2,
|
||||
"line": 3,
|
||||
"column": 4,
|
||||
"message": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
5
.github/workflows/e2e-local-file.yml
vendored
5
.github/workflows/e2e-local-file.yml
vendored
@@ -47,7 +47,7 @@ jobs:
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'jdkfile'
|
||||
jdk-file: ${{ runner.temp }}/${{ env.LocalFilename }}
|
||||
jdkFile: ${{ runner.temp }}/${{ env.LocalFilename }}
|
||||
java-version: '11.0.0-ea'
|
||||
architecture: x64
|
||||
- name: Verify Java version
|
||||
@@ -88,7 +88,7 @@ jobs:
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'jdkfile'
|
||||
jdk-file: ${{ runner.temp }}/${{ env.LocalFilename }}
|
||||
jdkFile: ${{ runner.temp }}/${{ env.LocalFilename }}
|
||||
java-version: '11.0.0-ea'
|
||||
architecture: x64
|
||||
- name: Verify Java version
|
||||
@@ -129,7 +129,6 @@ jobs:
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'jdkfile'
|
||||
# Intentionally uses the deprecated `jdkFile` alias to keep it covered.
|
||||
jdkFile: ${{ runner.temp }}/${{ env.LocalFilename }}
|
||||
java-version: '11.0.0-ea'
|
||||
architecture: x64
|
||||
|
||||
24
README.md
24
README.md
@@ -18,9 +18,9 @@ The `setup-java` action provides the following functionality for GitHub Actions
|
||||
|
||||
This action allows you to work with Java and Scala projects.
|
||||
|
||||
## What's new in V6
|
||||
## Breaking changes in V6
|
||||
|
||||
- **Migrated to ESM** to enable support for the latest `@actions/*` package versions. This is an internal implementation change only. No changes are required to your workflow configuration, and the action's behavior is unchanged. Existing workflows continue to work as before.
|
||||
- **Migrated to ESM** to enable support for the latest `@actions/*` package versions.
|
||||
|
||||
## Breaking changes in V5
|
||||
|
||||
@@ -41,7 +41,7 @@ For more details, see the full release notes on the [releases page](https://git
|
||||
|
||||
- `architecture`: The target architecture of the package. Possible values: `x86`, `x64`, `armv7`, `aarch64`, `ppc64le`. Default value: Derived from the runner machine.
|
||||
|
||||
- `jdk-file`: If a use-case requires a custom distribution setup-java uses the compressed JDK from the location pointed by this input and will take care of the installation and caching on the VM. Note: `distribution` must be set to 'jdkfile' (case-sensitive; all lowercase) when using this option. (The camelCase `jdkFile` input is still accepted as a deprecated alias and may be removed in a future release.)
|
||||
- `jdkFile`: If a use-case requires a custom distribution setup-java uses the compressed JDK from the location pointed by this input and will take care of the installation and caching on the VM. Note: `distribution` must be set to 'jdkfile' (case-sensitive; all lowercase) when using this option.
|
||||
|
||||
- `check-latest`: Setting this option makes the action to check for the latest available version for the version spec.
|
||||
|
||||
@@ -104,16 +104,7 @@ steps:
|
||||
The `java-version` input supports an exact version or a version range using [SemVer](https://semver.org/) notation. The values below are examples, not an exhaustive list:
|
||||
- major versions, such as: `8`, `11`, `16`, `17`, `21`, `25`
|
||||
- more specific versions: `8.0.282+8`, `8.0.232`, `11.0`, `11.0.4`, `17.0`
|
||||
- multi-field Java versions (JEP 322), such as: `11.0.9.1`, `18.0.1.1`
|
||||
- early access (EA) versions: `15-ea`, `15.0.0-ea`
|
||||
- the `latest` alias, which floats to the newest available stable (GA) release
|
||||
|
||||
> [!NOTE]
|
||||
> - `latest` always resolves the newest version from the distribution's remote metadata (it behaves like `check-latest: true`), so it ignores any older version already present in the runner tool cache. This has the same performance trade-off described in [Check latest](#check-latest).
|
||||
> - `latest` is only supported through the `java-version` input, not through `java-version-file`, and it resolves stable (GA) releases only — it cannot be combined with `-ea`.
|
||||
> - The `jdkfile` distribution does not support `latest`, as it installs from a local file.
|
||||
> - For `oracle` and `graalvm` (Oracle GraalVM), `latest` uses the Adoptium API only to determine the newest GA **major version number** — the JDK binary itself is still downloaded from the Oracle / GraalVM servers for that major. Because these distributions have no endpoint to list their own releases, if their servers haven't published the resolved major yet, the action fails and asks you to specify a concrete version. Note the Oracle JDK license caveat below still applies to a floating `latest`.
|
||||
> - For `graalvm-community`, `latest` floats to the newest GA release published on GitHub, so it never depends on the Adoptium API and always resolves to the newest major that GraalVM Community actually ships.
|
||||
|
||||
#### Supported distributions
|
||||
Currently, the following distributions are supported:
|
||||
@@ -158,8 +149,6 @@ When the option `cache-dependency-path` is specified, the hash is based on the m
|
||||
|
||||
The workflow output `cache-hit` is set to indicate if an exact match was found for the key [as actions/cache does](https://github.com/actions/cache/tree/main#outputs).
|
||||
|
||||
The workflow output `cache-primary-key` exposes the primary cache key computed by the action for the configured build tool. It is useful for composing with [`actions/cache`](https://github.com/actions/cache) or [`actions/cache/restore`](https://github.com/actions/cache/tree/main/restore) in later steps or dependent jobs that need to reuse the exact same key. It is empty when caching is not enabled or when caching is skipped (for example, when the cache service is unavailable).
|
||||
|
||||
The cache input is optional, and caching is turned off by default.
|
||||
|
||||
**Maven Wrapper:** when `cache: 'maven'` is enabled, the action also caches and restores the Maven Wrapper distribution downloaded to `~/.m2/wrapper/dists` (in addition to the local repository), so wrapper-based (`./mvnw`) builds don't re-download the wrapper on every run. This is keyed on `**/.mvn/wrapper/maven-wrapper.properties` as shown above.
|
||||
@@ -198,13 +187,6 @@ steps:
|
||||
run: mvn -B package --file pom.xml
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Maven resolves plugin dependencies lazily, so a cache created by a "thin" goal
|
||||
> (e.g. `mvn compile`) can be missing plugin dependencies that later
|
||||
> `test`/`verify`/`package` jobs then re-download on every run. See
|
||||
> [Ensuring the Maven cache is complete](docs/advanced-usage.md#ensuring-the-maven-cache-is-complete-plugin-dependencies)
|
||||
> for how to seed a complete cache.
|
||||
|
||||
#### Caching sbt dependencies
|
||||
```yaml
|
||||
steps:
|
||||
|
||||
@@ -133,7 +133,6 @@ describe('dependency cache', () => {
|
||||
describe('restore', () => {
|
||||
let spyCacheRestore: any;
|
||||
let spyGlobHashFiles: any;
|
||||
let spySetOutput: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyCacheRestore = (cache.restoreCache as any).mockImplementation(
|
||||
@@ -141,8 +140,6 @@ describe('dependency cache', () => {
|
||||
);
|
||||
spyGlobHashFiles = glob.hashFiles as jest.Mock;
|
||||
spyGlobHashFiles.mockResolvedValue('hash-stub');
|
||||
spySetOutput = core.setOutput as jest.Mock;
|
||||
spySetOutput.mockImplementation(() => null);
|
||||
spyWarning.mockImplementation(() => null);
|
||||
});
|
||||
|
||||
@@ -178,15 +175,6 @@ describe('dependency cache', () => {
|
||||
expect(spyWarning).not.toHaveBeenCalled();
|
||||
expect(spyInfo).toHaveBeenCalledWith('maven cache is not found');
|
||||
});
|
||||
it('sets the cache-primary-key output', async () => {
|
||||
createFile(join(workspace, 'pom.xml'));
|
||||
|
||||
await restore('maven', '');
|
||||
expect(spySetOutput).toHaveBeenCalledWith(
|
||||
'cache-primary-key',
|
||||
expect.stringContaining('setup-java-')
|
||||
);
|
||||
});
|
||||
it('downloads cache based on maven-wrapper.properties', async () => {
|
||||
createDirectory(join(workspace, '.mvn'));
|
||||
createDirectory(join(workspace, '.mvn', 'wrapper'));
|
||||
|
||||
@@ -420,29 +420,6 @@ describe('setupJava', () => {
|
||||
expect(spyCoreInfo).not.toHaveBeenCalledWith('Trying to download...');
|
||||
});
|
||||
|
||||
it('should resolve the latest version from remote when java-version is "latest", even if a version is cached', async () => {
|
||||
mockJavaBase = new EmptyJavaBase({
|
||||
version: 'latest',
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
await expect(mockJavaBase.setupJava()).resolves.toEqual({
|
||||
version: actualJavaVersion,
|
||||
path: javaPathInstalled
|
||||
});
|
||||
|
||||
// `latest` must bypass the tool-cache short-circuit and always resolve remotely
|
||||
expect(spyCoreInfo).toHaveBeenCalledWith(
|
||||
'Trying to resolve the latest version from remote'
|
||||
);
|
||||
expect(spyCoreInfo).toHaveBeenCalledWith('Trying to download...');
|
||||
expect(spyCoreInfo).not.toHaveBeenCalledWith(
|
||||
`Resolved Java ${installedJavaVersion} from tool-cache`
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
[
|
||||
{
|
||||
@@ -767,18 +744,11 @@ describe('normalizeVersion', () => {
|
||||
const DummyJavaBase = JavaBase as any;
|
||||
|
||||
it.each([
|
||||
['11', {version: '11', stable: true, latest: false}],
|
||||
['11.0', {version: '11.0', stable: true, latest: false}],
|
||||
['11.0.10', {version: '11.0.10', stable: true, latest: false}],
|
||||
['11-ea', {version: '11', stable: false, latest: false}],
|
||||
['11.0.2-ea', {version: '11.0.2', stable: false, latest: false}],
|
||||
['18.0.1.1', {version: '18.0.1+1', stable: true, latest: false}],
|
||||
['11.0.9.1', {version: '11.0.9+1', stable: true, latest: false}],
|
||||
['12.0.2.1.0', {version: '12.0.2+1.0', stable: true, latest: false}],
|
||||
['18.0.1.1-ea', {version: '18.0.1+1', stable: false, latest: false}],
|
||||
['latest', {version: 'x', stable: true, latest: true}],
|
||||
['LATEST', {version: 'x', stable: true, latest: true}],
|
||||
[' Latest ', {version: 'x', stable: true, latest: true}]
|
||||
['11', {version: '11', stable: true}],
|
||||
['11.0', {version: '11.0', stable: true}],
|
||||
['11.0.10', {version: '11.0.10', stable: true}],
|
||||
['11-ea', {version: '11', stable: false}],
|
||||
['11.0.2-ea', {version: '11.0.2', stable: false}]
|
||||
])('normalizeVersion from %s to %s', (input, expected) => {
|
||||
expect(DummyJavaBase.prototype.normalizeVersion.call(null, input)).toEqual(
|
||||
expected
|
||||
@@ -793,17 +763,6 @@ describe('normalizeVersion', () => {
|
||||
`The string '${version}' is not valid SemVer notation for a Java version. Please check README file for code snippets and more detailed information`
|
||||
);
|
||||
});
|
||||
|
||||
it.each(['latest-ea', 'latest.1', 'LATEST-EA', ' latest-ea '])(
|
||||
'normalizeVersion should throw a targeted error for latest combined with a qualifier (%s)',
|
||||
version => {
|
||||
expect(
|
||||
DummyJavaBase.prototype.normalizeVersion.bind(null, version)
|
||||
).toThrow(
|
||||
`The 'latest' alias resolves stable (GA) releases only and cannot be combined with '-ea' or other qualifiers (received '${version}'). Use 'latest' on its own, or specify a concrete version.`
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('createVersionNotFoundError', () => {
|
||||
|
||||
@@ -204,24 +204,6 @@ describe('getAvailableVersions', () => {
|
||||
expect(availableVersion.url).toBe(expectedLink);
|
||||
});
|
||||
|
||||
it('with latest resolves to the newest available major version', async () => {
|
||||
const distribution = new CorrettoDistribution({
|
||||
version: 'latest',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
mockPlatform(distribution, 'linux');
|
||||
|
||||
const availableVersion =
|
||||
await distribution['findPackageForDownload']('x');
|
||||
expect(availableVersion).not.toBeNull();
|
||||
// 18 is the newest major present in the mocked Corretto index
|
||||
expect(availableVersion.url).toBe(
|
||||
'https://corretto.aws/downloads/resources/18.0.0.37.1/amazon-corretto-18.0.0.37.1-linux-x64.tar.gz'
|
||||
);
|
||||
});
|
||||
|
||||
it('with unstable version expect to throw not supported error', async () => {
|
||||
const version = '18.0.1-ea';
|
||||
const distribution = new CorrettoDistribution({
|
||||
|
||||
@@ -417,61 +417,6 @@ describe('GraalVMDistribution', () => {
|
||||
);
|
||||
});
|
||||
|
||||
describe('latest alias', () => {
|
||||
it('resolves the newest major version from the Adoptium API', async () => {
|
||||
const latestDistribution = new GraalVMDistribution({
|
||||
...defaultOptions,
|
||||
version: 'latest'
|
||||
});
|
||||
(latestDistribution as any).http = mockHttpClient;
|
||||
jest
|
||||
.spyOn(latestDistribution, 'getPlatform')
|
||||
.mockReturnValue('linux');
|
||||
mockHttpClient.getJson.mockResolvedValue({
|
||||
statusCode: 200,
|
||||
result: {most_recent_feature_release: 25},
|
||||
headers: {}
|
||||
});
|
||||
mockHttpClient.head.mockResolvedValue({
|
||||
message: {statusCode: 200}
|
||||
});
|
||||
|
||||
const result = await (
|
||||
latestDistribution as any
|
||||
).findPackageForDownload('x');
|
||||
|
||||
expect(result).toEqual({
|
||||
url: 'https://download.oracle.com/graalvm/25/latest/graalvm-jdk-25_linux-x64_bin.tar.gz',
|
||||
version: '25'
|
||||
});
|
||||
});
|
||||
|
||||
it('throws an actionable error when the latest major is not yet available', async () => {
|
||||
const latestDistribution = new GraalVMDistribution({
|
||||
...defaultOptions,
|
||||
version: 'latest'
|
||||
});
|
||||
(latestDistribution as any).http = mockHttpClient;
|
||||
jest
|
||||
.spyOn(latestDistribution, 'getPlatform')
|
||||
.mockReturnValue('linux');
|
||||
mockHttpClient.getJson.mockResolvedValue({
|
||||
statusCode: 200,
|
||||
result: {most_recent_feature_release: 25},
|
||||
headers: {}
|
||||
});
|
||||
mockHttpClient.head.mockResolvedValue({
|
||||
message: {statusCode: 404}
|
||||
});
|
||||
|
||||
await expect(
|
||||
(latestDistribution as any).findPackageForDownload('x')
|
||||
).rejects.toThrow(
|
||||
/is not yet available for the GraalVM distribution/
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw error for JDK versions less than 17', async () => {
|
||||
await expect(
|
||||
(distribution as any).findPackageForDownload('11')
|
||||
@@ -1170,60 +1115,6 @@ describe('GraalVMDistribution', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('resolves latest to the newest GA across all Community majors without calling Adoptium', async () => {
|
||||
const latestCommunity = new GraalVMCommunityDistribution({
|
||||
...defaultOptions,
|
||||
version: 'latest'
|
||||
});
|
||||
(latestCommunity as any).http = mockHttpClient;
|
||||
jest.spyOn(latestCommunity, 'getPlatform').mockReturnValue('linux');
|
||||
|
||||
mockHttpClient.getJson.mockResolvedValue({
|
||||
result: [
|
||||
{
|
||||
draft: false,
|
||||
prerelease: false,
|
||||
assets: [
|
||||
{
|
||||
name: 'graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz',
|
||||
browser_download_url:
|
||||
'https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-21.0.2/graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
draft: false,
|
||||
prerelease: false,
|
||||
assets: [
|
||||
{
|
||||
name: 'graalvm-community-jdk-24.0.1_linux-x64_bin.tar.gz',
|
||||
browser_download_url:
|
||||
'https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-24.0.1/graalvm-community-jdk-24.0.1_linux-x64_bin.tar.gz'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
statusCode: 200,
|
||||
headers: {}
|
||||
});
|
||||
|
||||
const result = await (latestCommunity as any).findPackageForDownload(
|
||||
'x'
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
url: 'https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-24.0.1/graalvm-community-jdk-24.0.1_linux-x64_bin.tar.gz',
|
||||
version: '24.0.1'
|
||||
});
|
||||
// The Community release list is authoritative, so the Adoptium
|
||||
// most_recent_feature_release endpoint must not be consulted.
|
||||
expect(mockHttpClient.getJson).toHaveBeenCalledTimes(1);
|
||||
expect(mockHttpClient.getJson).toHaveBeenCalledWith(
|
||||
expect.stringContaining('graalvm-ce-builds/releases'),
|
||||
expect.anything()
|
||||
);
|
||||
});
|
||||
|
||||
it('should reject GraalVM Community early access requests', async () => {
|
||||
(communityDistribution as any).stable = false;
|
||||
|
||||
|
||||
@@ -170,20 +170,6 @@ describe('setupJava', () => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('throws for the latest alias since jdkfile has no version list', async () => {
|
||||
const inputs = {
|
||||
version: 'latest',
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
};
|
||||
|
||||
mockJavaBase = new LocalDistribution(inputs, expectedJdkFile);
|
||||
await expect(mockJavaBase.setupJava()).rejects.toThrow(
|
||||
"The 'latest' version alias is not supported for the 'jdkfile' distribution. Please specify a concrete version."
|
||||
);
|
||||
});
|
||||
|
||||
it('java is resolved from toolcache, jdkfile is untouched', async () => {
|
||||
const inputs = {
|
||||
version: actualJavaVersion,
|
||||
|
||||
@@ -174,59 +174,3 @@ describe('findPackageForDownload', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('findPackageForDownload with latest', () => {
|
||||
let spyHttpClientHead: any;
|
||||
let spyHttpClientGetJson: any;
|
||||
|
||||
beforeEach(() => {
|
||||
(core.debug as jest.Mock).mockImplementation(() => {});
|
||||
(core.error as jest.Mock).mockImplementation(() => {});
|
||||
spyHttpClientGetJson = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
spyHttpClientGetJson.mockResolvedValue({
|
||||
statusCode: 200,
|
||||
result: {most_recent_feature_release: 25},
|
||||
headers: {}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('resolves the newest major version from the Adoptium API', async () => {
|
||||
spyHttpClientHead = jest.spyOn(HttpClient.prototype, 'head');
|
||||
spyHttpClientHead.mockResolvedValue({message: {statusCode: 200}});
|
||||
|
||||
const distribution = new OracleDistribution({
|
||||
version: 'latest',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
const result = await distribution['findPackageForDownload']('x');
|
||||
const osType = distribution.getPlatform();
|
||||
const archiveType = getDownloadArchiveExtension();
|
||||
|
||||
expect(result.version).toBe('25');
|
||||
expect(result.url).toBe(
|
||||
`https://download.oracle.com/java/25/latest/jdk-25_${osType}-x64_bin.${archiveType}`
|
||||
);
|
||||
});
|
||||
|
||||
it('throws an actionable error when the latest major is not yet available', async () => {
|
||||
spyHttpClientHead = jest.spyOn(HttpClient.prototype, 'head');
|
||||
spyHttpClientHead.mockResolvedValue({message: {statusCode: 404}});
|
||||
|
||||
const distribution = new OracleDistribution({
|
||||
version: 'latest',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
await expect(distribution['findPackageForDownload']('x')).rejects.toThrow(
|
||||
/is not yet available for the Oracle JDK distribution/
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -312,24 +312,6 @@ describe('findPackageForDownload', () => {
|
||||
expect(resolvedVersion.signatureUrl).toBeDefined();
|
||||
});
|
||||
|
||||
it('version "latest" is normalized to the newest available version', async () => {
|
||||
const distribution = new TemurinDistribution(
|
||||
{
|
||||
version: 'latest',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
TemurinImplementation.Hotspot
|
||||
);
|
||||
distribution['getAvailableVersions'] = async () => manifestData as any;
|
||||
// normalizeVersion turns `latest` into the wildcard carried on `this.version`
|
||||
const resolvedVersion = await distribution['findPackageForDownload'](
|
||||
distribution['version']
|
||||
);
|
||||
expect(resolvedVersion.version).toBe('16.0.2+7');
|
||||
});
|
||||
|
||||
it('version is found but binaries list is empty', async () => {
|
||||
const distribution = new TemurinDistribution(
|
||||
{
|
||||
|
||||
@@ -56,8 +56,7 @@ const {
|
||||
isVersionSatisfies,
|
||||
isCacheFeatureAvailable,
|
||||
isGhes,
|
||||
validatePaginationUrl,
|
||||
getLatestMajorVersion
|
||||
validatePaginationUrl
|
||||
} = await import('../src/util.js');
|
||||
|
||||
describe('isVersionSatisfies', () => {
|
||||
@@ -297,72 +296,6 @@ describe('getVersionFromFileContent', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
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')
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('isGhes', () => {
|
||||
@@ -401,33 +334,3 @@ describe('isGhes', () => {
|
||||
expect(isGhes()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
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'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
10
action.yml
10
action.yml
@@ -4,7 +4,7 @@ description: 'Set up a specific version of the Java JDK and add the
|
||||
author: 'GitHub'
|
||||
inputs:
|
||||
java-version:
|
||||
description: 'The Java version to set up. Takes a whole or semver Java version, or the "latest" alias to use the newest available stable release. See examples of supported syntax in README file'
|
||||
description: 'The Java version to set up. Takes a whole or semver Java version. See examples of supported syntax in README file'
|
||||
required: false
|
||||
java-version-file:
|
||||
description: 'The path to a file containing the Java version to set up (.java-version, .tool-versions, .sdkmanrc). Used when java-version is not set. See examples of supported syntax in README file'
|
||||
@@ -19,13 +19,9 @@ inputs:
|
||||
architecture:
|
||||
description: "The architecture of the package (defaults to the action runner's architecture)"
|
||||
required: false
|
||||
jdk-file:
|
||||
jdkFile:
|
||||
description: 'Path to where the compressed JDK is located'
|
||||
required: false
|
||||
jdkFile:
|
||||
description: 'Deprecated alias for `jdk-file`. Path to where the compressed JDK is located. Use `jdk-file` instead; this alias may be removed in a future release.'
|
||||
required: false
|
||||
deprecationMessage: 'The `jdkFile` input is deprecated. Use `jdk-file` instead.'
|
||||
check-latest:
|
||||
description: 'Set this option if you want the action to check for the latest available version that satisfies the version spec'
|
||||
required: false
|
||||
@@ -103,8 +99,6 @@ outputs:
|
||||
description: 'Path to where the java environment has been installed (same as $JAVA_HOME)'
|
||||
cache-hit:
|
||||
description: 'A boolean value to indicate an exact match was found for the primary key'
|
||||
cache-primary-key:
|
||||
description: 'The primary cache key computed by the action for the configured build tool. Empty when caching is not enabled or when caching is skipped (e.g. cache service unavailable). Useful for composing with actions/cache or actions/cache/restore across jobs.'
|
||||
runs:
|
||||
using: 'node24'
|
||||
main: 'dist/setup/index.js'
|
||||
|
||||
69
dist/cleanup/index.js
vendored
69
dist/cleanup/index.js
vendored
@@ -95834,8 +95834,7 @@ const INPUT_JAVA_VERSION_FILE = 'java-version-file';
|
||||
const INPUT_ARCHITECTURE = 'architecture';
|
||||
const INPUT_JAVA_PACKAGE = 'java-package';
|
||||
const INPUT_DISTRIBUTION = 'distribution';
|
||||
const INPUT_JDK_FILE = 'jdk-file';
|
||||
const INPUT_JDK_FILE_DEPRECATED = 'jdkFile';
|
||||
const INPUT_JDK_FILE = 'jdkFile';
|
||||
const INPUT_CHECK_LATEST = 'check-latest';
|
||||
const INPUT_SET_DEFAULT = 'set-default';
|
||||
const INPUT_VERIFY_SIGNATURE = 'verify-signature';
|
||||
@@ -95966,10 +95965,8 @@ function getVersionFromFileContent(content, distributionName, versionFile) {
|
||||
}
|
||||
const versionFileName = getFileName(versionFile);
|
||||
if (versionFileName == '.tool-versions') {
|
||||
// Capture an optional asdf-java vendor prefix (e.g. `temurin-`, `corretto-`)
|
||||
// in the `distribution` group so it can be mapped to a setup-java distribution.
|
||||
javaVersionRegExp =
|
||||
/^java\s+(?:(?<distribution>\S*)-)?(?<version>\d+(?:\.\d+)*([+_.-](?:openj9[-._]?\d[\w.-]*|java\d+|jre[-_\w]*|OpenJDK\d+[\w_.-]*|[a-z0-9]+))*)/im;
|
||||
/^java\s+(?:\S*-)?(?<version>\d+(?:\.\d+)*([+_.-](?:openj9[-._]?\d[\w.-]*|java\d+|jre[-_\w]*|OpenJDK\d+[\w_.-]*|[a-z0-9]+))*)/im;
|
||||
}
|
||||
else if (versionFileName == '.sdkmanrc') {
|
||||
// Match both version and optional distribution identifier
|
||||
@@ -95989,14 +95986,6 @@ function getVersionFromFileContent(content, distributionName, versionFile) {
|
||||
extractedDistribution = mapSdkmanDistribution(sdkmanDist);
|
||||
core.debug(`Parsed distribution '${extractedDistribution}' from SDKMAN identifier '${sdkmanDist}'`);
|
||||
}
|
||||
// Extract distribution from asdf .tool-versions file
|
||||
if (versionFileName == '.tool-versions' && match?.groups?.distribution) {
|
||||
const asdfDist = match.groups.distribution;
|
||||
extractedDistribution = mapAsdfDistribution(asdfDist);
|
||||
if (extractedDistribution) {
|
||||
core.debug(`Parsed distribution '${extractedDistribution}' from asdf identifier '${asdfDist}'`);
|
||||
}
|
||||
}
|
||||
core.debug(`Parsed version '${capturedVersion}' from file '${versionFileName}'`);
|
||||
if (!capturedVersion) {
|
||||
return null;
|
||||
@@ -96045,43 +96034,6 @@ function mapSdkmanDistribution(sdkmanDist) {
|
||||
}
|
||||
return mapped;
|
||||
}
|
||||
// Map asdf-java (.tool-versions) vendor identifiers to setup-java distribution names.
|
||||
// asdf-java encodes the vendor as a prefix on the version string, e.g.
|
||||
// `java temurin-17.0.3+7` or `java semeru-openj9-11.0.25+9`. Packaging variants
|
||||
// (`-jre`, `-musl`, `-openj9`, `-crac`, `-javafx`, ...) are collapsed onto the
|
||||
// base vendor since setup-java does not distinguish them here.
|
||||
function mapAsdfDistribution(asdfDist) {
|
||||
const normalized = asdfDist.toLowerCase();
|
||||
// Multi-segment vendors that map to a distinct setup-java distribution.
|
||||
if (normalized.startsWith('graalvm-community')) {
|
||||
return 'graalvm-community';
|
||||
}
|
||||
if (normalized.startsWith('oracle-graalvm')) {
|
||||
return 'graalvm';
|
||||
}
|
||||
const baseVendor = normalized.split('-')[0];
|
||||
const distributionMap = {
|
||||
temurin: 'temurin',
|
||||
adoptopenjdk: 'temurin',
|
||||
zulu: 'zulu',
|
||||
corretto: 'corretto',
|
||||
liberica: 'liberica',
|
||||
microsoft: 'microsoft',
|
||||
semeru: 'semeru',
|
||||
ibm: 'semeru',
|
||||
dragonwell: 'dragonwell',
|
||||
graalvm: 'graalvm',
|
||||
oracle: 'oracle',
|
||||
sapmachine: 'sapmachine',
|
||||
kona: 'kona',
|
||||
jetbrains: 'jetbrains'
|
||||
};
|
||||
const mapped = distributionMap[baseVendor];
|
||||
if (!mapped) {
|
||||
core.warning(`Unknown asdf distribution identifier '${asdfDist}'. Please specify the distribution explicitly.`);
|
||||
}
|
||||
return mapped;
|
||||
}
|
||||
// By convention, action expects version 8 in the format `8.*` instead of `1.8`
|
||||
function avoidOldNotation(content) {
|
||||
return content.startsWith('1.') ? content.substring(2) : content;
|
||||
@@ -96154,22 +96106,6 @@ function renameWinArchive(javaArchivePath) {
|
||||
fs.renameSync(javaArchivePath, javaArchivePathRenamed);
|
||||
return javaArchivePathRenamed;
|
||||
}
|
||||
// Resolve the newest available stable/GA feature (major) release.
|
||||
//
|
||||
// Some distributions (e.g. Oracle, GraalVM) construct their download URLs from a
|
||||
// concrete major version and don't expose an endpoint to list every available
|
||||
// release, so a bare `latest` alias can't be resolved from their own metadata.
|
||||
// The Adoptium (Temurin) API is used as a proxy for "what is the newest GA major
|
||||
// version out there", which those distributions typically publish at the same time.
|
||||
async function getLatestMajorVersion(http) {
|
||||
const availableReleasesUrl = 'https://api.adoptium.net/v3/info/available_releases';
|
||||
const response = await http.getJson(availableReleasesUrl);
|
||||
const mostRecent = response.result?.most_recent_feature_release;
|
||||
if (!mostRecent || Number.isNaN(Number(mostRecent))) {
|
||||
throw new Error(`Could not determine the latest available Java major version from ${availableReleasesUrl}`);
|
||||
}
|
||||
return Number(mostRecent);
|
||||
}
|
||||
|
||||
;// CONCATENATED MODULE: ./src/gpg.ts
|
||||
|
||||
@@ -99751,7 +99687,6 @@ async function restore(id, cacheDependencyPath) {
|
||||
const primaryKey = await computeCacheKey(packageManager, cacheDependencyPath);
|
||||
core.debug(`primary key is ${primaryKey}`);
|
||||
core.saveState(STATE_CACHE_PRIMARY_KEY, primaryKey);
|
||||
core.setOutput(STATE_CACHE_PRIMARY_KEY, primaryKey);
|
||||
// No "restoreKeys" is set, to start with a clear cache after dependency update (see https://github.com/actions/setup-java/issues/269)
|
||||
const matchedKey = await cache.restoreCache(packageManager.path, primaryKey);
|
||||
if (matchedKey) {
|
||||
|
||||
182
dist/setup/index.js
vendored
182
dist/setup/index.js
vendored
@@ -73279,8 +73279,7 @@ const INPUT_JAVA_VERSION_FILE = 'java-version-file';
|
||||
const INPUT_ARCHITECTURE = 'architecture';
|
||||
const INPUT_JAVA_PACKAGE = 'java-package';
|
||||
const INPUT_DISTRIBUTION = 'distribution';
|
||||
const INPUT_JDK_FILE = 'jdk-file';
|
||||
const INPUT_JDK_FILE_DEPRECATED = 'jdkFile';
|
||||
const INPUT_JDK_FILE = 'jdkFile';
|
||||
const INPUT_CHECK_LATEST = 'check-latest';
|
||||
const INPUT_SET_DEFAULT = 'set-default';
|
||||
const INPUT_VERIFY_SIGNATURE = 'verify-signature';
|
||||
@@ -126958,10 +126957,8 @@ function getVersionFromFileContent(content, distributionName, versionFile) {
|
||||
}
|
||||
const versionFileName = getFileName(versionFile);
|
||||
if (versionFileName == '.tool-versions') {
|
||||
// Capture an optional asdf-java vendor prefix (e.g. `temurin-`, `corretto-`)
|
||||
// in the `distribution` group so it can be mapped to a setup-java distribution.
|
||||
javaVersionRegExp =
|
||||
/^java\s+(?:(?<distribution>\S*)-)?(?<version>\d+(?:\.\d+)*([+_.-](?:openj9[-._]?\d[\w.-]*|java\d+|jre[-_\w]*|OpenJDK\d+[\w_.-]*|[a-z0-9]+))*)/im;
|
||||
/^java\s+(?:\S*-)?(?<version>\d+(?:\.\d+)*([+_.-](?:openj9[-._]?\d[\w.-]*|java\d+|jre[-_\w]*|OpenJDK\d+[\w_.-]*|[a-z0-9]+))*)/im;
|
||||
}
|
||||
else if (versionFileName == '.sdkmanrc') {
|
||||
// Match both version and optional distribution identifier
|
||||
@@ -126981,14 +126978,6 @@ function getVersionFromFileContent(content, distributionName, versionFile) {
|
||||
extractedDistribution = mapSdkmanDistribution(sdkmanDist);
|
||||
core_debug(`Parsed distribution '${extractedDistribution}' from SDKMAN identifier '${sdkmanDist}'`);
|
||||
}
|
||||
// Extract distribution from asdf .tool-versions file
|
||||
if (versionFileName == '.tool-versions' && match?.groups?.distribution) {
|
||||
const asdfDist = match.groups.distribution;
|
||||
extractedDistribution = mapAsdfDistribution(asdfDist);
|
||||
if (extractedDistribution) {
|
||||
core_debug(`Parsed distribution '${extractedDistribution}' from asdf identifier '${asdfDist}'`);
|
||||
}
|
||||
}
|
||||
core_debug(`Parsed version '${capturedVersion}' from file '${versionFileName}'`);
|
||||
if (!capturedVersion) {
|
||||
return null;
|
||||
@@ -127037,43 +127026,6 @@ function mapSdkmanDistribution(sdkmanDist) {
|
||||
}
|
||||
return mapped;
|
||||
}
|
||||
// Map asdf-java (.tool-versions) vendor identifiers to setup-java distribution names.
|
||||
// asdf-java encodes the vendor as a prefix on the version string, e.g.
|
||||
// `java temurin-17.0.3+7` or `java semeru-openj9-11.0.25+9`. Packaging variants
|
||||
// (`-jre`, `-musl`, `-openj9`, `-crac`, `-javafx`, ...) are collapsed onto the
|
||||
// base vendor since setup-java does not distinguish them here.
|
||||
function mapAsdfDistribution(asdfDist) {
|
||||
const normalized = asdfDist.toLowerCase();
|
||||
// Multi-segment vendors that map to a distinct setup-java distribution.
|
||||
if (normalized.startsWith('graalvm-community')) {
|
||||
return 'graalvm-community';
|
||||
}
|
||||
if (normalized.startsWith('oracle-graalvm')) {
|
||||
return 'graalvm';
|
||||
}
|
||||
const baseVendor = normalized.split('-')[0];
|
||||
const distributionMap = {
|
||||
temurin: 'temurin',
|
||||
adoptopenjdk: 'temurin',
|
||||
zulu: 'zulu',
|
||||
corretto: 'corretto',
|
||||
liberica: 'liberica',
|
||||
microsoft: 'microsoft',
|
||||
semeru: 'semeru',
|
||||
ibm: 'semeru',
|
||||
dragonwell: 'dragonwell',
|
||||
graalvm: 'graalvm',
|
||||
oracle: 'oracle',
|
||||
sapmachine: 'sapmachine',
|
||||
kona: 'kona',
|
||||
jetbrains: 'jetbrains'
|
||||
};
|
||||
const mapped = distributionMap[baseVendor];
|
||||
if (!mapped) {
|
||||
warning(`Unknown asdf distribution identifier '${asdfDist}'. Please specify the distribution explicitly.`);
|
||||
}
|
||||
return mapped;
|
||||
}
|
||||
// By convention, action expects version 8 in the format `8.*` instead of `1.8`
|
||||
function avoidOldNotation(content) {
|
||||
return content.startsWith('1.') ? content.substring(2) : content;
|
||||
@@ -127146,22 +127098,6 @@ function renameWinArchive(javaArchivePath) {
|
||||
external_fs_namespaceObject.renameSync(javaArchivePath, javaArchivePathRenamed);
|
||||
return javaArchivePathRenamed;
|
||||
}
|
||||
// Resolve the newest available stable/GA feature (major) release.
|
||||
//
|
||||
// Some distributions (e.g. Oracle, GraalVM) construct their download URLs from a
|
||||
// concrete major version and don't expose an endpoint to list every available
|
||||
// release, so a bare `latest` alias can't be resolved from their own metadata.
|
||||
// The Adoptium (Temurin) API is used as a proxy for "what is the newest GA major
|
||||
// version out there", which those distributions typically publish at the same time.
|
||||
async function getLatestMajorVersion(http) {
|
||||
const availableReleasesUrl = 'https://api.adoptium.net/v3/info/available_releases';
|
||||
const response = await http.getJson(availableReleasesUrl);
|
||||
const mostRecent = response.result?.most_recent_feature_release;
|
||||
if (!mostRecent || Number.isNaN(Number(mostRecent))) {
|
||||
throw new Error(`Could not determine the latest available Java major version from ${availableReleasesUrl}`);
|
||||
}
|
||||
return Number(mostRecent);
|
||||
}
|
||||
|
||||
;// CONCATENATED MODULE: ./src/gpg.ts
|
||||
|
||||
@@ -130973,7 +130909,6 @@ async function restore(id, cacheDependencyPath) {
|
||||
const primaryKey = await computeCacheKey(packageManager, cacheDependencyPath);
|
||||
core_debug(`primary key is ${primaryKey}`);
|
||||
saveState(STATE_CACHE_PRIMARY_KEY, primaryKey);
|
||||
setOutput(STATE_CACHE_PRIMARY_KEY, primaryKey);
|
||||
// No "restoreKeys" is set, to start with a clear cache after dependency update (see https://github.com/actions/setup-java/issues/269)
|
||||
const matchedKey = await restoreCache(packageManager.path, primaryKey);
|
||||
if (matchedKey) {
|
||||
@@ -131061,7 +130996,6 @@ class JavaBase {
|
||||
architecture;
|
||||
packageType;
|
||||
stable;
|
||||
latest;
|
||||
checkLatest;
|
||||
setDefault;
|
||||
verifySignature;
|
||||
@@ -131072,11 +131006,7 @@ class JavaBase {
|
||||
allowRetries: true,
|
||||
maxRetries: 3
|
||||
});
|
||||
({
|
||||
version: this.version,
|
||||
stable: this.stable,
|
||||
latest: this.latest
|
||||
} = this.normalizeVersion(installerOptions.version));
|
||||
({ version: this.version, stable: this.stable } = this.normalizeVersion(installerOptions.version));
|
||||
this.architecture = installerOptions.architecture || external_os_default().arch();
|
||||
this.packageType = installerOptions.packageType;
|
||||
this.checkLatest = installerOptions.checkLatest;
|
||||
@@ -131092,7 +131022,7 @@ class JavaBase {
|
||||
throw new Error(`Input 'verify-signature' is not supported for distribution '${this.distribution}'.`);
|
||||
}
|
||||
let foundJava = this.findInToolcache();
|
||||
if (foundJava && !this.checkLatest && !this.latest) {
|
||||
if (foundJava && !this.checkLatest) {
|
||||
info(`Resolved Java ${foundJava.version} from tool-cache`);
|
||||
}
|
||||
else {
|
||||
@@ -131270,26 +131200,6 @@ class JavaBase {
|
||||
}
|
||||
normalizeVersion(version) {
|
||||
let stable = true;
|
||||
const latest = false;
|
||||
// Support the `latest` alias (case-insensitive), which floats to the newest
|
||||
// available stable/GA release. It is translated to the SemVer wildcard `x`
|
||||
// so the existing "newest satisfying version wins" resolution applies.
|
||||
const normalized = version.trim().toLowerCase();
|
||||
if (normalized === 'latest') {
|
||||
return {
|
||||
version: 'x',
|
||||
stable: true,
|
||||
latest: true
|
||||
};
|
||||
}
|
||||
// Reject `latest` combined with any qualifier (e.g. `latest-ea`). Such inputs
|
||||
// would otherwise have their `-ea` suffix stripped and fall through to the
|
||||
// generic SemVer check, which fails with a confusing "'latest' is not valid
|
||||
// SemVer" message even though `latest` is a supported value. Fail early with a
|
||||
// targeted explanation instead.
|
||||
if (normalized.startsWith('latest')) {
|
||||
throw new Error(`The 'latest' alias resolves stable (GA) releases only and cannot be combined with '-ea' or other qualifiers (received '${version}'). Use 'latest' on its own, or specify a concrete version.`);
|
||||
}
|
||||
if (version.endsWith('-ea')) {
|
||||
version = version.replace(/-ea$/, '');
|
||||
stable = false;
|
||||
@@ -131299,21 +131209,12 @@ class JavaBase {
|
||||
version = version.replace('-ea.', '+');
|
||||
stable = false;
|
||||
}
|
||||
// Java uses a versioning scheme (JEP 322) that can contain more numeric
|
||||
// fields than SemVer allows, e.g. '18.0.1.1' or '11.0.9.1'. Convert such
|
||||
// exact versions to SemVer build notation ('18.0.1+1') so they are
|
||||
// accepted. Ranges and versions that already carry build metadata are
|
||||
// left untouched.
|
||||
if (/^\d+(\.\d+){3,}$/.test(version)) {
|
||||
version = convertVersionToSemver(version);
|
||||
}
|
||||
if (!semver_default().validRange(version)) {
|
||||
throw new Error(`The string '${version}' is not valid SemVer notation for a Java version. Please check README file for code snippets and more detailed information`);
|
||||
}
|
||||
return {
|
||||
version,
|
||||
stable,
|
||||
latest
|
||||
stable
|
||||
};
|
||||
}
|
||||
createVersionNotFoundError(versionOrRange, availableVersions, additionalContext) {
|
||||
@@ -131387,9 +131288,6 @@ class LocalDistribution extends JavaBase {
|
||||
this.jdkFile = jdkFile;
|
||||
}
|
||||
async setupJava() {
|
||||
if (this.latest) {
|
||||
throw new Error("The 'latest' version alias is not supported for the 'jdkfile' distribution. Please specify a concrete version.");
|
||||
}
|
||||
let foundJava = this.findInToolcache();
|
||||
if (foundJava) {
|
||||
info(`Resolved Java ${foundJava.version} from tool-cache`);
|
||||
@@ -132405,22 +132303,10 @@ class CorrettoDistribution extends JavaBase {
|
||||
if (!this.stable) {
|
||||
throw new Error('Early access versions are not supported');
|
||||
}
|
||||
const availableVersions = await this.getAvailableVersions();
|
||||
// The `latest` alias is normalized to the SemVer wildcard, but Corretto
|
||||
// matches on an exact major version, so resolve it to the newest available
|
||||
// major from Corretto's own list.
|
||||
if (this.latest) {
|
||||
const majors = availableVersions
|
||||
.map(item => parseInt(item.version, 10))
|
||||
.filter(major => Number.isFinite(major) && major > 0);
|
||||
if (majors.length === 0) {
|
||||
throw new Error('Could not determine the latest available Corretto major version from remote metadata');
|
||||
}
|
||||
version = Math.max(...majors).toString();
|
||||
}
|
||||
if (version.includes('.')) {
|
||||
throw new Error('Only major versions are supported');
|
||||
}
|
||||
const availableVersions = await this.getAvailableVersions();
|
||||
const matchingVersions = availableVersions
|
||||
.filter(item => item.version == version)
|
||||
.map(item => {
|
||||
@@ -132548,13 +132434,6 @@ class OracleDistribution extends JavaBase {
|
||||
}
|
||||
const platform = this.getPlatform();
|
||||
const extension = getDownloadArchiveExtension();
|
||||
// The `latest` alias is normalized to the SemVer wildcard. Oracle builds its
|
||||
// download URLs from a concrete major and has no endpoint to list releases,
|
||||
// so resolve the newest available GA major from the Adoptium API and use it.
|
||||
if (this.latest) {
|
||||
const latestMajor = await getLatestMajorVersion(this.http);
|
||||
range = latestMajor.toString();
|
||||
}
|
||||
const isOnlyMajorProvided = !range.includes('.');
|
||||
const major = isOnlyMajorProvided ? range : range.split('.')[0];
|
||||
const possibleUrls = [];
|
||||
@@ -132581,11 +132460,6 @@ class OracleDistribution extends JavaBase {
|
||||
throw new Error(`Http request for Oracle JDK failed with status code: ${response.message.statusCode}`);
|
||||
}
|
||||
}
|
||||
if (this.latest) {
|
||||
const error = this.createVersionNotFoundError(range);
|
||||
error.message += `\nThe latest Java major version (${range}) is not yet available for the Oracle JDK distribution. Please specify a concrete version instead of 'latest'.`;
|
||||
throw error;
|
||||
}
|
||||
throw this.createVersionNotFoundError(range);
|
||||
}
|
||||
getPlatform(platform = process.platform) {
|
||||
@@ -132984,12 +132858,6 @@ class GraalVMDistribution extends JavaBase {
|
||||
if (!this.stable) {
|
||||
return this.findEABuildDownloadUrl(`${range}-ea`);
|
||||
}
|
||||
// The `latest` alias is normalized to the SemVer wildcard. Oracle GraalVM
|
||||
// builds its download URLs from a concrete major and has no endpoint to list
|
||||
// releases, so resolve the newest available GA major from the Adoptium API.
|
||||
if (this.latest) {
|
||||
range = (await getLatestMajorVersion(this.http)).toString();
|
||||
}
|
||||
const { platform, extension, major } = this.validateStableBuildRequest(range);
|
||||
const fileUrl = this.constructFileUrl(range, major, platform, arch, extension);
|
||||
const response = await this.http.head(fileUrl);
|
||||
@@ -133038,9 +132906,6 @@ class GraalVMDistribution extends JavaBase {
|
||||
if (statusCode === HttpCodes.NotFound) {
|
||||
// Create the standard error with additional hint about checking the download URL
|
||||
const error = this.createVersionNotFoundError(range);
|
||||
if (this.latest) {
|
||||
error.message += `\nThe latest Java major version (${range}) is not yet available for the ${this.distribution} distribution. Please specify a concrete version instead of 'latest'.`;
|
||||
}
|
||||
error.message += `\nPlease check if this version is available at ${GRAALVM_DOWNLOAD_URL} . Pick a version from the list.`;
|
||||
throw error;
|
||||
}
|
||||
@@ -133128,24 +132993,7 @@ class GraalVMCommunityDistribution extends GraalVMDistribution {
|
||||
throw new Error('GraalVM Community does not provide early access builds');
|
||||
}
|
||||
const arch = this.getSupportedArchitecture();
|
||||
// GraalVM Community publishes its releases on GitHub, so the `latest` alias
|
||||
// (normalized to the SemVer wildcard `x`) can float to the newest GA it
|
||||
// actually ships. Unlike Oracle GraalVM (which has no listing endpoint and
|
||||
// must derive the newest major from the Adoptium API), we match against the
|
||||
// real release list here, so `latest` never fails when GraalVM lags behind a
|
||||
// brand-new Java major.
|
||||
let platform;
|
||||
let extension;
|
||||
if (this.latest) {
|
||||
if (this.packageType !== 'jdk') {
|
||||
throw new Error(`${this.distribution} provides only the \`jdk\` package type`);
|
||||
}
|
||||
platform = this.getPlatform();
|
||||
extension = getDownloadArchiveExtension();
|
||||
}
|
||||
else {
|
||||
({ platform, extension } = this.validateStableBuildRequest(range));
|
||||
}
|
||||
const { platform, extension } = this.validateStableBuildRequest(range);
|
||||
// GraalVM Community asset names embed the platform, architecture and
|
||||
// archive type, e.g. `graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz`.
|
||||
const assetSuffix = `_${platform}-${arch}_bin.${extension}`;
|
||||
@@ -133665,7 +133513,7 @@ async function run() {
|
||||
const versionFile = getInput(INPUT_JAVA_VERSION_FILE);
|
||||
const architecture = getInput(INPUT_ARCHITECTURE);
|
||||
const packageType = getInput(INPUT_JAVA_PACKAGE);
|
||||
const jdkFile = getJdkFileInput();
|
||||
const jdkFile = getInput(INPUT_JDK_FILE);
|
||||
const cache = getInput(INPUT_CACHE);
|
||||
const cacheDependencyPath = getInput(INPUT_CACHE_DEPENDENCY_PATH);
|
||||
const checkLatest = util_getBooleanInput(INPUT_CHECK_LATEST, false);
|
||||
@@ -133743,14 +133591,6 @@ async function run() {
|
||||
}
|
||||
}
|
||||
run();
|
||||
function getJdkFileInput() {
|
||||
const jdkFile = getInput(INPUT_JDK_FILE);
|
||||
const deprecatedJdkFile = getInput(INPUT_JDK_FILE_DEPRECATED);
|
||||
if (deprecatedJdkFile) {
|
||||
warning(`The '${INPUT_JDK_FILE_DEPRECATED}' input is deprecated and may be removed in a future release. Please use '${INPUT_JDK_FILE}' instead.`);
|
||||
}
|
||||
return jdkFile || deprecatedJdkFile;
|
||||
}
|
||||
async function installVersion(version, options, toolchainId = 0) {
|
||||
const { distributionName, jdkFile, architecture, packageType, checkLatest, setDefault, verifySignature, verifySignaturePublicKey, toolchainIds } = options;
|
||||
const installerOptions = {
|
||||
@@ -133767,11 +133607,7 @@ async function installVersion(version, options, toolchainId = 0) {
|
||||
throw new Error(`No supported distribution was found for input ${distributionName}`);
|
||||
}
|
||||
const result = await distribution.setupJava();
|
||||
// When the `latest` alias is used, the literal input isn't a real version, so
|
||||
// pass the resolved version to the toolchains configuration instead.
|
||||
const isLatest = version.trim().toLowerCase() === 'latest';
|
||||
const toolchainVersion = isLatest ? result.version : version;
|
||||
await configureToolchains(toolchainVersion, distributionName, result.path, toolchainIds[toolchainId]);
|
||||
await configureToolchains(version, distributionName, result.path, toolchainIds[toolchainId]);
|
||||
info('');
|
||||
info('Java configuration:');
|
||||
info(` Distribution: ${distributionName}`);
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
- [Tencent Kona](#Tencent-Kona)
|
||||
- [Installing custom Java package type](#Installing-custom-Java-package-type)
|
||||
- [JavaFX Maven project](#JavaFX-Maven-project)
|
||||
- [Ensuring the Maven cache is complete (plugin dependencies)](#ensuring-the-maven-cache-is-complete-plugin-dependencies)
|
||||
- [Installing custom Java architecture](#Installing-custom-Java-architecture)
|
||||
- [Installing JDK without setting as default](#Installing-JDK-without-setting-as-default)
|
||||
- [Installing custom Java distribution from local file](#Installing-Java-from-local-file)
|
||||
@@ -286,122 +285,6 @@ To run the JavaFX application in CI:
|
||||
run: mvn --no-transfer-progress javafx:run
|
||||
```
|
||||
|
||||
## Ensuring the Maven cache is complete (plugin dependencies)
|
||||
|
||||
When you enable `cache: maven`, the action caches your local Maven repository
|
||||
(`~/.m2/repository`) and downloaded Maven Wrapper distributions
|
||||
(`~/.m2/wrapper/dists`). The cache key is a hash of your Maven inputs — every
|
||||
`**/pom.xml`, plus `**/.mvn/wrapper/maven-wrapper.properties` and
|
||||
`**/.mvn/extensions.xml` — so changing any of those files (for example bumping
|
||||
the wrapper version or editing core extensions) produces a new key and
|
||||
invalidates the cache. At the end of the job the action saves whatever was
|
||||
downloaded during that run. It does **not** re-save the cache when the key
|
||||
already matches (a cache *hit*).
|
||||
|
||||
Maven resolves **plugin** dependencies lazily: it only downloads the plugins and
|
||||
plugin dependencies required by the goals that actually execute. As a result, the
|
||||
run that first creates the cache determines what is stored. If that run executed a
|
||||
"thin" goal such as `mvn compile`, plugins bound to later phases are never
|
||||
resolved. For example, `maven-shade-plugin` (bound to `package`) pulls in
|
||||
`plexus-archiver`, `commons-compress`, `io.airlift:aircompressor` and
|
||||
`org.tukaani:xz` — none of which a `compile` run downloads. Those artifacts are
|
||||
therefore absent from the cache, and because the action does not re-save on a
|
||||
hit, every later `test`/`verify`/`package` job re-downloads them on every run.
|
||||
|
||||
### Seed the cache with a resolution step
|
||||
|
||||
To populate `~/.m2` as comprehensively as possible on the run that creates the
|
||||
cache, run a dependency-resolution "seed" command before your build. Choose a
|
||||
command based on how thorough you need it to be:
|
||||
|
||||
| Seed command | Resolves plugin dependencies? | Notes |
|
||||
|--------------|:-----------------------------:|-------|
|
||||
| `mvn dependency:resolve` | No | Resolves project dependencies only — misses plugin dependencies (e.g. `aircompressor`). |
|
||||
| `mvn dependency:resolve-plugins` | Yes | Resolves plugins **and their dependencies**. |
|
||||
| `mvn dependency:go-offline` | Yes | Resolves project and plugin dependencies (a superset). |
|
||||
| `mvn dependency:go-offline dependency:resolve-plugins` | Yes (most thorough) | Recommended default. Use `dependency:resolve dependency:resolve-plugins` if `go-offline` is flaky or insufficient for your project. |
|
||||
|
||||
Single job — seed, then build (the cache saved at the end of this run contains
|
||||
the full set):
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'maven'
|
||||
- name: Seed the Maven cache
|
||||
run: mvn -B dependency:go-offline dependency:resolve-plugins
|
||||
- name: Build with Maven
|
||||
run: mvn -B verify --file pom.xml
|
||||
```
|
||||
|
||||
Separate seed job — useful for a matrix where different legs run different goals
|
||||
(`test`, `check`, `verify`, `-Pprofile1`, ...) but all share the same `~/.m2`
|
||||
cache. Without a seed, whichever job finishes first creates the cache from its
|
||||
own partial `.m2`, and parallel jobs race to save an equally partial cache; the
|
||||
seed job instead creates one comprehensive cache that every other job reuses:
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
seed-cache:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'maven'
|
||||
- name: Seed the Maven cache
|
||||
run: mvn -B dependency:go-offline dependency:resolve-plugins
|
||||
|
||||
build:
|
||||
needs: seed-cache
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
goal: ['test', 'verify', 'test -Pprofile1']
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'maven'
|
||||
- name: Build
|
||||
run: mvn -B ${{ matrix.goal }} --file pom.xml
|
||||
```
|
||||
|
||||
### Caveats
|
||||
|
||||
- **The seed only helps on the run that creates the cache.** Once a cache exists
|
||||
for the current `pom.xml` hash, later runs get a hit and any additional
|
||||
downloads are not saved. On an existing repository whose cache is already
|
||||
incomplete, invalidate it once (for example by changing `cache-dependency-path`
|
||||
or deleting the repository's caches) so a complete cache is created from the
|
||||
seed.
|
||||
- **Static resolution is not exhaustive.** `go-offline`/`resolve-plugins` resolve
|
||||
the statically declared plugin set for the *active* profiles and modules.
|
||||
Profile-gated plugins, conditionally-active modules, and artifacts a plugin
|
||||
fetches at execution time may still be missed. For the most complete cache,
|
||||
seed with the fullest goal set your CI actually uses (for example
|
||||
`mvn -B verify` with every profile enabled).
|
||||
- **Multi-module projects:** run the seed at the reactor root so every module's
|
||||
plugins are resolved.
|
||||
|
||||
> [!NOTE]
|
||||
> The same "the cache stores only what the creating run downloaded, and is not
|
||||
> re-saved on a hit" behavior applies to `cache: gradle`, since Gradle also
|
||||
> resolves dependencies and plugin/buildscript classpaths lazily. Gradle has no
|
||||
> direct equivalent of `dependency:go-offline`, so for complete and fine-grained
|
||||
> dependency caching on Gradle projects we recommend
|
||||
> [`gradle/actions/setup-gradle`](https://github.com/gradle/actions/tree/main/setup-gradle),
|
||||
> which provides purpose-built caching (see the
|
||||
> [setup-gradle documentation](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md)).
|
||||
|
||||
## Installing custom Java architecture
|
||||
|
||||
```yaml
|
||||
@@ -447,7 +330,7 @@ In this example, `JAVA_HOME` and `java` on `PATH` point to Java 17, while Java 2
|
||||
If your use-case requires a custom distribution or a version that is not provided by setup-java, you can download it manually and setup-java will take care of the installation and caching on the VM:
|
||||
|
||||
> [!NOTE]
|
||||
> This approach also lets you use builds that setup-java does not provide directly, such as **Early Access (EA)** or other unreleased JDK builds (for example, an upcoming feature release or a Loom/Valhalla preview build). Download the desired archive in a prior step and point `jdk-file` at it; setup-java will extract, install, and cache it just like a supported distribution. When targeting multiple architectures, select the correct binary per architecture in your workflow (for example, with a build matrix).
|
||||
> This approach also lets you use builds that setup-java does not provide directly, such as **Early Access (EA)** or other unreleased JDK builds (for example, an upcoming feature release or a Loom/Valhalla preview build). Download the desired archive in a prior step and point `jdkFile` at it; setup-java will extract, install, and cache it just like a supported distribution. When targeting multiple architectures, select the correct binary per architecture in your workflow (for example, with a build matrix).
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
@@ -457,7 +340,7 @@ steps:
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'jdkfile'
|
||||
jdk-file: ${{ runner.temp }}/java_package.tar.gz
|
||||
jdkFile: ${{ runner.temp }}/java_package.tar.gz
|
||||
java-version: '11.0.0'
|
||||
architecture: x64
|
||||
|
||||
@@ -474,7 +357,7 @@ steps:
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'jdkfile'
|
||||
jdk-file: ${{ runner.temp }}/java_package.tar.gz
|
||||
jdkFile: ${{ runner.temp }}/java_package.tar.gz
|
||||
java-version: '25.0.0-ea.36'
|
||||
architecture: x64
|
||||
|
||||
@@ -500,7 +383,7 @@ If your use-case requires a custom distribution (in the example, alpine-linux is
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'jdkfile'
|
||||
jdk-file: ${{ runner.temp }}/java_package.tar.gz
|
||||
jdkFile: ${{ runner.temp }}/java_package.tar.gz
|
||||
java-version: {{ steps.fetch_latest_jdk.outputs.java_version }}
|
||||
architecture: x64
|
||||
- run: java --version
|
||||
@@ -825,7 +708,7 @@ The result is a Toolchain with entries for JDKs 8, 11 and 15. You can even combi
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'jdkfile'
|
||||
jdk-file: ${{ runner.temp }}/java_package.tar.gz
|
||||
jdkFile: ${{ runner.temp }}/java_package.tar.gz
|
||||
java-version: '1.6'
|
||||
architecture: x64
|
||||
```
|
||||
@@ -842,7 +725,7 @@ Each JDK provider will receive a default `vendor` using the `distribution` input
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'jdkfile'
|
||||
jdk-file: ${{ runner.temp }}/java_package.tar.gz
|
||||
jdkFile: ${{ runner.temp }}/java_package.tar.gz
|
||||
java-version: '1.6'
|
||||
architecture: x64
|
||||
mvn-toolchain-vendor: 'Oracle'
|
||||
@@ -897,27 +780,7 @@ steps:
|
||||
|
||||
Supported files are `.java-version`, `.tool-versions` and `.sdkmanrc`.
|
||||
* In `.java-version` file, only the version should be specified (e.g., 17.0.7). The `.java-version` file recognizes all variants of the version description according to [jenv](https://github.com/jenv/jenv).
|
||||
* In `.tool-versions` file, java version should be preceded by the java keyword (e.g., java 17.0.7). The `.tool-versions` file supports version specifications in accordance with [asdf](https://github.com/asdf-vm/asdf) standards, adhering to Semantic Versioning ([semver](https://semver.org/)). When the entry includes an [asdf-java](https://github.com/halcyon/asdf-java) vendor prefix (e.g. `java temurin-17.0.3+7`), setup-java can infer the `distribution` input automatically. Unrecognized vendor prefixes require setting `distribution` explicitly.
|
||||
|
||||
Supported asdf-java vendor prefix mappings (packaging variants such as `-jre`, `-musl`, `-openj9`, `-crac`, `-javafx` are collapsed onto the base vendor):
|
||||
|
||||
| asdf-java vendor prefix | setup-java distribution |
|
||||
| ----------------------- | ----------------------- |
|
||||
| `temurin` | `temurin` |
|
||||
| `adoptopenjdk` | `temurin` |
|
||||
| `zulu` | `zulu` |
|
||||
| `corretto` | `corretto` |
|
||||
| `liberica` | `liberica` |
|
||||
| `microsoft` | `microsoft` |
|
||||
| `semeru`, `ibm` | `semeru` |
|
||||
| `dragonwell` | `dragonwell` |
|
||||
| `graalvm`, `oracle-graalvm` | `graalvm` |
|
||||
| `graalvm-community` | `graalvm-community` |
|
||||
| `oracle` | `oracle` |
|
||||
| `sapmachine` | `sapmachine` |
|
||||
| `kona` | `kona` |
|
||||
| `jetbrains` | `jetbrains` |
|
||||
|
||||
* In `.tool-versions` file, java version should be preceded by the java keyword (e.g., java 17.0.7). The `.tool-versions` file supports version specifications in accordance with [asdf](https://github.com/asdf-vm/asdf) standards, adhering to Semantic Versioning ([semver](https://semver.org/)).
|
||||
* In `.sdkmanrc` file, java version should be preceded by the `java=` prefix (e.g., `java=17.0.7-tem`). When a recognized SDKMAN distribution suffix is present, setup-java can infer the `distribution` input automatically. Unrecognized suffixes require setting `distribution` explicitly. The `.sdkmanrc` file supports version specifications in accordance with [file format](https://sdkman.io/usage#env-command), see [Sdkman! documentation](https://sdkman.io/jdks) for more information.
|
||||
|
||||
Supported SDKMAN suffix mappings:
|
||||
@@ -953,19 +816,6 @@ steps:
|
||||
java=17.0.7-tem
|
||||
```
|
||||
|
||||
**Example step using `asdf`** (distribution inferred from `.tool-versions`):
|
||||
```yml
|
||||
- name: Setup java
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version-file: '.tool-versions'
|
||||
```
|
||||
|
||||
**Example `.tool-versions`**:
|
||||
```
|
||||
java temurin-17.0.7+7
|
||||
```
|
||||
|
||||
Valid entry options (does not apply to `.sdkmanrc`):
|
||||
```
|
||||
major versions: 8, 11, 16, 17, 21
|
||||
|
||||
@@ -118,7 +118,6 @@ export async function restore(id: string, cacheDependencyPath: string) {
|
||||
const primaryKey = await computeCacheKey(packageManager, cacheDependencyPath);
|
||||
core.debug(`primary key is ${primaryKey}`);
|
||||
core.saveState(STATE_CACHE_PRIMARY_KEY, primaryKey);
|
||||
core.setOutput(STATE_CACHE_PRIMARY_KEY, primaryKey);
|
||||
|
||||
// No "restoreKeys" is set, to start with a clear cache after dependency update (see https://github.com/actions/setup-java/issues/269)
|
||||
const matchedKey = await cache.restoreCache(packageManager.path, primaryKey);
|
||||
|
||||
@@ -4,8 +4,7 @@ export const INPUT_JAVA_VERSION_FILE = 'java-version-file';
|
||||
export const INPUT_ARCHITECTURE = 'architecture';
|
||||
export const INPUT_JAVA_PACKAGE = 'java-package';
|
||||
export const INPUT_DISTRIBUTION = 'distribution';
|
||||
export const INPUT_JDK_FILE = 'jdk-file';
|
||||
export const INPUT_JDK_FILE_DEPRECATED = 'jdkFile';
|
||||
export const INPUT_JDK_FILE = 'jdkFile';
|
||||
export const INPUT_CHECK_LATEST = 'check-latest';
|
||||
export const INPUT_SET_DEFAULT = 'set-default';
|
||||
export const INPUT_VERIFY_SIGNATURE = 'verify-signature';
|
||||
|
||||
@@ -4,11 +4,7 @@ import * as fs from 'fs';
|
||||
import semver from 'semver';
|
||||
import path from 'path';
|
||||
import * as httpm from '@actions/http-client';
|
||||
import {
|
||||
convertVersionToSemver,
|
||||
getToolcachePath,
|
||||
isVersionSatisfies
|
||||
} from '../util.js';
|
||||
import {getToolcachePath, isVersionSatisfies} from '../util.js';
|
||||
import {
|
||||
JavaDownloadRelease,
|
||||
JavaInstallerOptions,
|
||||
@@ -23,7 +19,6 @@ export abstract class JavaBase {
|
||||
protected architecture: string;
|
||||
protected packageType: string;
|
||||
protected stable: boolean;
|
||||
protected latest: boolean;
|
||||
protected checkLatest: boolean;
|
||||
protected setDefault: boolean;
|
||||
protected verifySignature: boolean;
|
||||
@@ -38,11 +33,9 @@ export abstract class JavaBase {
|
||||
maxRetries: 3
|
||||
});
|
||||
|
||||
({
|
||||
version: this.version,
|
||||
stable: this.stable,
|
||||
latest: this.latest
|
||||
} = this.normalizeVersion(installerOptions.version));
|
||||
({version: this.version, stable: this.stable} = this.normalizeVersion(
|
||||
installerOptions.version
|
||||
));
|
||||
this.architecture = installerOptions.architecture || os.arch();
|
||||
this.packageType = installerOptions.packageType;
|
||||
this.checkLatest = installerOptions.checkLatest;
|
||||
@@ -69,7 +62,7 @@ export abstract class JavaBase {
|
||||
}
|
||||
|
||||
let foundJava = this.findInToolcache();
|
||||
if (foundJava && !this.checkLatest && !this.latest) {
|
||||
if (foundJava && !this.checkLatest) {
|
||||
core.info(`Resolved Java ${foundJava.version} from tool-cache`);
|
||||
} else {
|
||||
core.info('Trying to resolve the latest version from remote');
|
||||
@@ -270,30 +263,6 @@ export abstract class JavaBase {
|
||||
|
||||
protected normalizeVersion(version: string) {
|
||||
let stable = true;
|
||||
const latest = false;
|
||||
|
||||
// Support the `latest` alias (case-insensitive), which floats to the newest
|
||||
// available stable/GA release. It is translated to the SemVer wildcard `x`
|
||||
// so the existing "newest satisfying version wins" resolution applies.
|
||||
const normalized = version.trim().toLowerCase();
|
||||
if (normalized === 'latest') {
|
||||
return {
|
||||
version: 'x',
|
||||
stable: true,
|
||||
latest: true
|
||||
};
|
||||
}
|
||||
|
||||
// Reject `latest` combined with any qualifier (e.g. `latest-ea`). Such inputs
|
||||
// would otherwise have their `-ea` suffix stripped and fall through to the
|
||||
// generic SemVer check, which fails with a confusing "'latest' is not valid
|
||||
// SemVer" message even though `latest` is a supported value. Fail early with a
|
||||
// targeted explanation instead.
|
||||
if (normalized.startsWith('latest')) {
|
||||
throw new Error(
|
||||
`The 'latest' alias resolves stable (GA) releases only and cannot be combined with '-ea' or other qualifiers (received '${version}'). Use 'latest' on its own, or specify a concrete version.`
|
||||
);
|
||||
}
|
||||
|
||||
if (version.endsWith('-ea')) {
|
||||
version = version.replace(/-ea$/, '');
|
||||
@@ -304,15 +273,6 @@ export abstract class JavaBase {
|
||||
stable = false;
|
||||
}
|
||||
|
||||
// Java uses a versioning scheme (JEP 322) that can contain more numeric
|
||||
// fields than SemVer allows, e.g. '18.0.1.1' or '11.0.9.1'. Convert such
|
||||
// exact versions to SemVer build notation ('18.0.1+1') so they are
|
||||
// accepted. Ranges and versions that already carry build metadata are
|
||||
// left untouched.
|
||||
if (/^\d+(\.\d+){3,}$/.test(version)) {
|
||||
version = convertVersionToSemver(version);
|
||||
}
|
||||
|
||||
if (!semver.validRange(version)) {
|
||||
throw new Error(
|
||||
`The string '${version}' is not valid SemVer notation for a Java version. Please check README file for code snippets and more detailed information`
|
||||
@@ -321,8 +281,7 @@ export abstract class JavaBase {
|
||||
|
||||
return {
|
||||
version,
|
||||
stable,
|
||||
latest
|
||||
stable
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -59,28 +59,10 @@ export class CorrettoDistribution extends JavaBase {
|
||||
if (!this.stable) {
|
||||
throw new Error('Early access versions are not supported');
|
||||
}
|
||||
const availableVersions = await this.getAvailableVersions();
|
||||
|
||||
// The `latest` alias is normalized to the SemVer wildcard, but Corretto
|
||||
// matches on an exact major version, so resolve it to the newest available
|
||||
// major from Corretto's own list.
|
||||
if (this.latest) {
|
||||
const majors = availableVersions
|
||||
.map(item => parseInt(item.version, 10))
|
||||
.filter(major => Number.isFinite(major) && major > 0);
|
||||
|
||||
if (majors.length === 0) {
|
||||
throw new Error(
|
||||
'Could not determine the latest available Corretto major version from remote metadata'
|
||||
);
|
||||
}
|
||||
|
||||
version = Math.max(...majors).toString();
|
||||
}
|
||||
|
||||
if (version.includes('.')) {
|
||||
throw new Error('Only major versions are supported');
|
||||
}
|
||||
const availableVersions = await this.getAvailableVersions();
|
||||
const matchingVersions = availableVersions
|
||||
.filter(item => item.version == version)
|
||||
.map(item => {
|
||||
|
||||
@@ -16,7 +16,6 @@ import {
|
||||
extractJdkFile,
|
||||
getDownloadArchiveExtension,
|
||||
getGitHubHttpHeaders,
|
||||
getLatestMajorVersion,
|
||||
getNextPageUrlFromLinkHeader,
|
||||
isVersionSatisfies,
|
||||
MAX_PAGINATION_PAGES,
|
||||
@@ -120,13 +119,6 @@ export class GraalVMDistribution extends JavaBase {
|
||||
return this.findEABuildDownloadUrl(`${range}-ea`);
|
||||
}
|
||||
|
||||
// The `latest` alias is normalized to the SemVer wildcard. Oracle GraalVM
|
||||
// builds its download URLs from a concrete major and has no endpoint to list
|
||||
// releases, so resolve the newest available GA major from the Adoptium API.
|
||||
if (this.latest) {
|
||||
range = (await getLatestMajorVersion(this.http)).toString();
|
||||
}
|
||||
|
||||
const {platform, extension, major} = this.validateStableBuildRequest(range);
|
||||
|
||||
const fileUrl = this.constructFileUrl(
|
||||
@@ -211,9 +203,6 @@ export class GraalVMDistribution extends JavaBase {
|
||||
if (statusCode === HttpCodes.NotFound) {
|
||||
// Create the standard error with additional hint about checking the download URL
|
||||
const error = this.createVersionNotFoundError(range);
|
||||
if (this.latest) {
|
||||
error.message += `\nThe latest Java major version (${range}) is not yet available for the ${this.distribution} distribution. Please specify a concrete version instead of 'latest'.`;
|
||||
}
|
||||
error.message += `\nPlease check if this version is available at ${GRAALVM_DOWNLOAD_URL} . Pick a version from the list.`;
|
||||
throw error;
|
||||
}
|
||||
@@ -365,27 +354,7 @@ export class GraalVMCommunityDistribution extends GraalVMDistribution {
|
||||
}
|
||||
|
||||
const arch = this.getSupportedArchitecture();
|
||||
|
||||
// GraalVM Community publishes its releases on GitHub, so the `latest` alias
|
||||
// (normalized to the SemVer wildcard `x`) can float to the newest GA it
|
||||
// actually ships. Unlike Oracle GraalVM (which has no listing endpoint and
|
||||
// must derive the newest major from the Adoptium API), we match against the
|
||||
// real release list here, so `latest` never fails when GraalVM lags behind a
|
||||
// brand-new Java major.
|
||||
let platform: OsVersions;
|
||||
let extension: string;
|
||||
if (this.latest) {
|
||||
if (this.packageType !== 'jdk') {
|
||||
throw new Error(
|
||||
`${this.distribution} provides only the \`jdk\` package type`
|
||||
);
|
||||
}
|
||||
platform = this.getPlatform();
|
||||
extension = getDownloadArchiveExtension();
|
||||
} else {
|
||||
({platform, extension} = this.validateStableBuildRequest(range));
|
||||
}
|
||||
|
||||
const {platform, extension} = this.validateStableBuildRequest(range);
|
||||
// GraalVM Community asset names embed the platform, architecture and
|
||||
// archive type, e.g. `graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz`.
|
||||
const assetSuffix = `_${platform}-${arch}_bin.${extension}`;
|
||||
|
||||
@@ -22,12 +22,6 @@ export class LocalDistribution extends JavaBase {
|
||||
}
|
||||
|
||||
public async setupJava(): Promise<JavaInstallerResults> {
|
||||
if (this.latest) {
|
||||
throw new Error(
|
||||
"The 'latest' version alias is not supported for the 'jdkfile' distribution. Please specify a concrete version."
|
||||
);
|
||||
}
|
||||
|
||||
let foundJava = this.findInToolcache();
|
||||
|
||||
if (foundJava) {
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
import {
|
||||
extractJdkFile,
|
||||
getDownloadArchiveExtension,
|
||||
getLatestMajorVersion,
|
||||
renameWinArchive
|
||||
} from '../../util.js';
|
||||
import {HttpCodes} from '@actions/http-client';
|
||||
@@ -74,14 +73,6 @@ export class OracleDistribution extends JavaBase {
|
||||
const platform = this.getPlatform();
|
||||
const extension = getDownloadArchiveExtension();
|
||||
|
||||
// The `latest` alias is normalized to the SemVer wildcard. Oracle builds its
|
||||
// download URLs from a concrete major and has no endpoint to list releases,
|
||||
// so resolve the newest available GA major from the Adoptium API and use it.
|
||||
if (this.latest) {
|
||||
const latestMajor = await getLatestMajorVersion(this.http);
|
||||
range = latestMajor.toString();
|
||||
}
|
||||
|
||||
const isOnlyMajorProvided = !range.includes('.');
|
||||
const major = isOnlyMajorProvided ? range : range.split('.')[0];
|
||||
|
||||
@@ -122,12 +113,6 @@ export class OracleDistribution extends JavaBase {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.latest) {
|
||||
const error = this.createVersionNotFoundError(range);
|
||||
error.message += `\nThe latest Java major version (${range}) is not yet available for the Oracle JDK distribution. Please specify a concrete version instead of 'latest'.`;
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw this.createVersionNotFoundError(range);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ async function run() {
|
||||
const versionFile = core.getInput(constants.INPUT_JAVA_VERSION_FILE);
|
||||
const architecture = core.getInput(constants.INPUT_ARCHITECTURE);
|
||||
const packageType = core.getInput(constants.INPUT_JAVA_PACKAGE);
|
||||
const jdkFile = getJdkFileInput();
|
||||
const jdkFile = core.getInput(constants.INPUT_JDK_FILE);
|
||||
const cache = core.getInput(constants.INPUT_CACHE);
|
||||
const cacheDependencyPath = core.getInput(
|
||||
constants.INPUT_CACHE_DEPENDENCY_PATH
|
||||
@@ -134,19 +134,6 @@ async function run() {
|
||||
|
||||
run();
|
||||
|
||||
function getJdkFileInput(): string {
|
||||
const jdkFile = core.getInput(constants.INPUT_JDK_FILE);
|
||||
const deprecatedJdkFile = core.getInput(constants.INPUT_JDK_FILE_DEPRECATED);
|
||||
|
||||
if (deprecatedJdkFile) {
|
||||
core.warning(
|
||||
`The '${constants.INPUT_JDK_FILE_DEPRECATED}' input is deprecated and may be removed in a future release. Please use '${constants.INPUT_JDK_FILE}' instead.`
|
||||
);
|
||||
}
|
||||
|
||||
return jdkFile || deprecatedJdkFile;
|
||||
}
|
||||
|
||||
async function installVersion(
|
||||
version: string,
|
||||
options: installerInputsOptions,
|
||||
@@ -186,14 +173,8 @@ async function installVersion(
|
||||
}
|
||||
|
||||
const result = await distribution.setupJava();
|
||||
|
||||
// When the `latest` alias is used, the literal input isn't a real version, so
|
||||
// pass the resolved version to the toolchains configuration instead.
|
||||
const isLatest = version.trim().toLowerCase() === 'latest';
|
||||
const toolchainVersion = isLatest ? result.version : version;
|
||||
|
||||
await toolchains.configureToolchains(
|
||||
toolchainVersion,
|
||||
version,
|
||||
distributionName,
|
||||
result.path,
|
||||
toolchainIds[toolchainId]
|
||||
|
||||
89
src/util.ts
89
src/util.ts
@@ -6,7 +6,6 @@ import * as cache from '@actions/cache';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as httpm from '@actions/http-client';
|
||||
import {
|
||||
INPUT_JOB_STATUS,
|
||||
DISTRIBUTIONS_ONLY_MAJOR_VERSION
|
||||
@@ -150,10 +149,8 @@ export function getVersionFromFileContent(
|
||||
|
||||
const versionFileName = getFileName(versionFile);
|
||||
if (versionFileName == '.tool-versions') {
|
||||
// Capture an optional asdf-java vendor prefix (e.g. `temurin-`, `corretto-`)
|
||||
// in the `distribution` group so it can be mapped to a setup-java distribution.
|
||||
javaVersionRegExp =
|
||||
/^java\s+(?:(?<distribution>\S*)-)?(?<version>\d+(?:\.\d+)*([+_.-](?:openj9[-._]?\d[\w.-]*|java\d+|jre[-_\w]*|OpenJDK\d+[\w_.-]*|[a-z0-9]+))*)/im;
|
||||
/^java\s+(?:\S*-)?(?<version>\d+(?:\.\d+)*([+_.-](?:openj9[-._]?\d[\w.-]*|java\d+|jre[-_\w]*|OpenJDK\d+[\w_.-]*|[a-z0-9]+))*)/im;
|
||||
} else if (versionFileName == '.sdkmanrc') {
|
||||
// Match both version and optional distribution identifier
|
||||
javaVersionRegExp =
|
||||
@@ -176,17 +173,6 @@ export function getVersionFromFileContent(
|
||||
);
|
||||
}
|
||||
|
||||
// Extract distribution from asdf .tool-versions file
|
||||
if (versionFileName == '.tool-versions' && match?.groups?.distribution) {
|
||||
const asdfDist = match.groups.distribution;
|
||||
extractedDistribution = mapAsdfDistribution(asdfDist);
|
||||
if (extractedDistribution) {
|
||||
core.debug(
|
||||
`Parsed distribution '${extractedDistribution}' from asdf identifier '${asdfDist}'`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
core.debug(
|
||||
`Parsed version '${capturedVersion}' from file '${versionFileName}'`
|
||||
);
|
||||
@@ -252,49 +238,6 @@ function mapSdkmanDistribution(sdkmanDist: string): string | undefined {
|
||||
return mapped;
|
||||
}
|
||||
|
||||
// Map asdf-java (.tool-versions) vendor identifiers to setup-java distribution names.
|
||||
// asdf-java encodes the vendor as a prefix on the version string, e.g.
|
||||
// `java temurin-17.0.3+7` or `java semeru-openj9-11.0.25+9`. Packaging variants
|
||||
// (`-jre`, `-musl`, `-openj9`, `-crac`, `-javafx`, ...) are collapsed onto the
|
||||
// base vendor since setup-java does not distinguish them here.
|
||||
function mapAsdfDistribution(asdfDist: string): string | undefined {
|
||||
const normalized = asdfDist.toLowerCase();
|
||||
|
||||
// Multi-segment vendors that map to a distinct setup-java distribution.
|
||||
if (normalized.startsWith('graalvm-community')) {
|
||||
return 'graalvm-community';
|
||||
}
|
||||
if (normalized.startsWith('oracle-graalvm')) {
|
||||
return 'graalvm';
|
||||
}
|
||||
|
||||
const baseVendor = normalized.split('-')[0];
|
||||
const distributionMap: Record<string, string> = {
|
||||
temurin: 'temurin',
|
||||
adoptopenjdk: 'temurin',
|
||||
zulu: 'zulu',
|
||||
corretto: 'corretto',
|
||||
liberica: 'liberica',
|
||||
microsoft: 'microsoft',
|
||||
semeru: 'semeru',
|
||||
ibm: 'semeru',
|
||||
dragonwell: 'dragonwell',
|
||||
graalvm: 'graalvm',
|
||||
oracle: 'oracle',
|
||||
sapmachine: 'sapmachine',
|
||||
kona: 'kona',
|
||||
jetbrains: 'jetbrains'
|
||||
};
|
||||
|
||||
const mapped = distributionMap[baseVendor];
|
||||
if (!mapped) {
|
||||
core.warning(
|
||||
`Unknown asdf distribution identifier '${asdfDist}'. Please specify the distribution explicitly.`
|
||||
);
|
||||
}
|
||||
return mapped;
|
||||
}
|
||||
|
||||
// By convention, action expects version 8 in the format `8.*` instead of `1.8`
|
||||
function avoidOldNotation(content: string): string {
|
||||
return content.startsWith('1.') ? content.substring(2) : content;
|
||||
@@ -383,33 +326,3 @@ export function renameWinArchive(javaArchivePath: string): string {
|
||||
fs.renameSync(javaArchivePath, javaArchivePathRenamed);
|
||||
return javaArchivePathRenamed;
|
||||
}
|
||||
|
||||
interface IAdoptiumAvailableReleases {
|
||||
most_recent_feature_release: number;
|
||||
}
|
||||
|
||||
// Resolve the newest available stable/GA feature (major) release.
|
||||
//
|
||||
// Some distributions (e.g. Oracle, GraalVM) construct their download URLs from a
|
||||
// concrete major version and don't expose an endpoint to list every available
|
||||
// release, so a bare `latest` alias can't be resolved from their own metadata.
|
||||
// The Adoptium (Temurin) API is used as a proxy for "what is the newest GA major
|
||||
// version out there", which those distributions typically publish at the same time.
|
||||
export async function getLatestMajorVersion(
|
||||
http: httpm.HttpClient
|
||||
): Promise<number> {
|
||||
const availableReleasesUrl =
|
||||
'https://api.adoptium.net/v3/info/available_releases';
|
||||
|
||||
const response =
|
||||
await http.getJson<IAdoptiumAvailableReleases>(availableReleasesUrl);
|
||||
|
||||
const mostRecent = response.result?.most_recent_feature_release;
|
||||
if (!mostRecent || Number.isNaN(Number(mostRecent))) {
|
||||
throw new Error(
|
||||
`Could not determine the latest available Java major version from ${availableReleasesUrl}`
|
||||
);
|
||||
}
|
||||
|
||||
return Number(mostRecent);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user