diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index bdc1379..11600d3 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -407,3 +407,27 @@ jobs:
# popd > /dev/null
- name: Remove components
run: gu remove espresso llvm-toolchain nodejs python ruby wasm
+
+ test-java-version-file:
+ name: java-version-file on ubuntu-latest
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: write # for `native-image-pr-reports` option
+ steps:
+ - uses: actions/checkout@v4
+ - run: echo '17' > .java-version
+ - name: Run setup-graalvm action
+ uses: ./
+ with:
+ java-version-file: .java-version
+ distribution: 'graalvm'
+ native-image-job-reports: 'true'
+ native-image-pr-reports: 'true'
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ - name: Build HelloWorld executable with GraalVM Native Image on Windows
+ run: |
+ echo 'public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }' > HelloWorld.java
+ javac HelloWorld.java
+ native-image HelloWorld
+ ./helloworld
diff --git a/README.md b/README.md
index eef7ff2..22de72d 100644
--- a/README.md
+++ b/README.md
@@ -187,7 +187,8 @@ can be replaced with:
| Name | Default | Description |
|-----------------|:--------:|-------------|
-| `java-version`
*(required)* | n/a | Java version
- major versions: `'21'`, `'17'`, `'11'`, `'8'`
- specific versions: `'21.0.2'`, `'17.0.7'`
- early access (EA) builds: `'22-ea'` *(requires `distribution: 'graalvm'`)*
- latest EA build: `'latest-ea'` *(requires `distribution: 'graalvm'`)*
- dev builds: `'dev'`
|
+| `java-version` | n/a | Java version - major versions: `'21'`, `'17'`, `'11'`, `'8'`
- specific versions: `'21.0.2'`, `'17.0.7'`
- early access (EA) builds: `'22-ea'` *(requires `distribution: 'graalvm'`)*
- latest EA build: `'latest-ea'` *(requires `distribution: 'graalvm'`)*
- dev builds: `'dev'`
|
+| `java-version-file`| n/a | The path to the `.java-version` file. See more details in [about `.java-version` file](#Java-version-file) |
| `distribution` | `'graalvm'` | GraalVM distribution - Oracle GraalVM: `'graalvm'`
- GraalVM Community Edition: `'graalvm-community'`
- Mandrel: `'mandrel'`
- Liberica: `'liberica'`
|
| `java-package` | `'jdk'` | The package type (`'jdk'` or `'jdk+fx'`). Currently applies to Liberica only. |
| `github-token` | `'${{ github.token }}'` | Token for communication with the GitHub API. Please set this to `${{ secrets.GITHUB_TOKEN }}` (see [templates](#templates)) to allow the action to authenticate with the GitHub API, which helps reduce rate-limiting issues. |
@@ -203,6 +204,20 @@ can be replaced with:
**) Make sure that Native Image is used only once per build job. Otherwise, the report is only generated for the last Native Image build.*
+## Advanced Usage
+
+### Java-version file
+
+If the `java-version-file` input is specified, the action will try to extract the version from the file and install it.
+Action is able to recognize all variants of the version description according to [jenv](https://github.com/jenv/jenv).
+Valid entry options:
+```
+major versions: 8, 11, 16, 17
+more specific versions: 1.8.0.2, 17.0, 11.0, 11.0.4, 8.0.232, 8.0.282+8
+early access (EA) versions: 15-ea, 15.0.0-ea, 15.0.0-ea.2, 15.0.0+2-ea
+versions with specified distribution: openjdk64-11.0.2
+```
+If the file contains multiple versions, only the first one will be recognized.
## Contributing
diff --git a/action.yml b/action.yml
index dece5ee..19115cd 100644
--- a/action.yml
+++ b/action.yml
@@ -6,8 +6,9 @@ branding:
color: 'blue'
inputs:
java-version:
- required: true
description: 'Java version. See examples of supported syntax in the README file.'
+ java-version-file:
+ description: 'The path to the `.java-version` file. See examples of supported syntax in README file'
java-package:
description: 'The package type (jdk or jdk+fx). Currently applies to Liberica only.'
required: false
diff --git a/src/constants.ts b/src/constants.ts
index 11964e8..b14191d 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -3,6 +3,7 @@ import * as otypes from '@octokit/types'
export const INPUT_VERSION = 'version'
export const INPUT_GDS_TOKEN = 'gds-token'
export const INPUT_JAVA_VERSION = 'java-version'
+export const INPUT_JAVA_VERSION_FILE = 'java-version-file'
export const INPUT_JAVA_PACKAGE = 'java-package'
export const INPUT_DISTRIBUTION = 'distribution'
export const INPUT_COMPONENTS = 'components'
@@ -12,6 +13,8 @@ export const INPUT_CACHE = 'cache'
export const INPUT_CHECK_FOR_UPDATES = 'check-for-updates'
export const INPUT_NI_MUSL = 'native-image-musl'
+export const DISTRIBUTIONS_ONLY_MAJOR_VERSION = ['corretto']
+
export const IS_LINUX = process.platform === 'linux'
export const IS_MACOS = process.platform === 'darwin'
export const IS_WINDOWS = process.platform === 'win32'
diff --git a/src/main.ts b/src/main.ts
index 75b373e..0a60b4f 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,6 +1,7 @@
import * as c from './constants'
import * as core from '@actions/core'
import * as graalvm from './graalvm'
+import {getVersionFromFileContent} from './utils'
import * as semver from 'semver'
import {isFeatureAvailable as isCacheAvailable} from '@actions/cache'
import {basename, join} from 'path'
@@ -14,10 +15,12 @@ import {setUpNativeImageMusl} from './features/musl'
import {setUpWindowsEnvironment} from './msvc'
import {setUpNativeImageBuildReports} from './features/reports'
import {exec} from '@actions/exec'
+import fs from 'fs'
async function run(): Promise {
try {
- const javaVersion = core.getInput(c.INPUT_JAVA_VERSION, {required: true})
+ const javaVersionInput = core.getInput(c.INPUT_JAVA_VERSION)
+ const javaVersionFile = core.getInput(c.INPUT_JAVA_VERSION_FILE)
const javaPackage = core.getInput(c.INPUT_JAVA_PACKAGE)
const distribution = core.getInput(c.INPUT_DISTRIBUTION)
const graalVMVersion = core.getInput(c.INPUT_VERSION)
@@ -35,6 +38,32 @@ async function run(): Promise {
const isGraalVMforJDK17OrLater =
distribution.length > 0 || graalVMVersion.length == 0
+ if (!javaVersionInput && !javaVersionFile) {
+ throw new Error('java-version or java-version-file input expected');
+ }
+
+ var javaVersion = javaVersionInput
+ if (!javaVersion) {
+ core.debug(
+ 'java-version input is empty, looking for java-version-file input'
+ );
+ const content = fs.readFileSync(javaVersionFile).toString().trim();
+
+ javaVersion = getVersionFromFileContent(
+ content,
+ javaPackage,
+ javaVersionFile
+ )
+
+ core.debug(`Parsed version from file '${javaVersion}'`);
+
+ if (!javaVersion) {
+ throw new Error(
+ `No supported version was found in file ${javaVersionFile}`
+ );
+ }
+ }
+
if (c.IS_WINDOWS) {
setUpWindowsEnvironment(
javaVersion,
diff --git a/src/utils.ts b/src/utils.ts
index 1bd5335..74a5b71 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -8,7 +8,7 @@ import {ExecOptions, exec as e} from '@actions/exec'
import {readFileSync, readdirSync} from 'fs'
import {Octokit} from '@octokit/core'
import {createHash} from 'crypto'
-import {join} from 'path'
+import {join, path} from 'path'
// Set up Octokit for github.com only and in the same way as @actions/github (see https://git.io/Jy9YP)
const baseUrl = 'https://api.github.com'
@@ -201,3 +201,58 @@ export async function createPRComment(content: string): Promise {
)
}
}
+
+// copied from https://github.com/actions/setup-java/blob/a1c6c9c8677803c9f4bd31e0f15ac0844258f955/src/util.ts#L116
+export function getVersionFromFileContent(
+ content: string,
+ distributionName: string,
+ versionFile: string
+): string | null {
+ let javaVersionRegExp: RegExp;
+
+ function getFileName(versionFile: string) {
+ return path.basename(versionFile);
+ }
+
+ const versionFileName = getFileName(versionFile);
+ if (versionFileName == '.tool-versions') {
+ javaVersionRegExp =
+ /^(java\s+)(?:\S*-)?v?(?(\d+)(\.\d+)?(\.\d+)?(\+\d+)?(-ea(\.\d+)?)?)$/m;
+ } else {
+ javaVersionRegExp = /(?(?<=(^|\s|-))(\d+\S*))(\s|$)/;
+ }
+
+ const fileContent = content.match(javaVersionRegExp)?.groups?.version
+ ? (content.match(javaVersionRegExp)?.groups?.version as string)
+ : '';
+ if (!fileContent) {
+ return null;
+ }
+
+ core.debug(`Version from file '${fileContent}'`);
+
+ const tentativeVersion = avoidOldNotation(fileContent);
+ const rawVersion = tentativeVersion.split('-')[0];
+
+ let version = semver.validRange(rawVersion)
+ ? tentativeVersion
+ : semver.coerce(tentativeVersion);
+
+ core.debug(`Range version from file is '${version}'`);
+
+ if (!version) {
+ return null;
+ }
+
+ if (c.DISTRIBUTIONS_ONLY_MAJOR_VERSION.includes(distributionName)) {
+ const coerceVersion = semver.coerce(version) ?? version;
+ version = semver.major(coerceVersion).toString();
+ }
+
+ return version.toString();
+}
+
+// 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;
+}