Compare commits

..

62 Commits

Author SHA1 Message Date
Fabio Niephaus
c09e29bb11 Bump version to 1.2.7. 2025-01-16 15:54:52 +01:00
Fabio Niephaus
04d7e4f4bb Skip steps that require a GDS token in PR builds. 2025-01-16 15:54:52 +01:00
Fabio Niephaus
64b43dc209 Update @actions/cache and other dependencies.
Context: https://github.com/actions/toolkit/discussions/1890
2025-01-16 15:54:52 +01:00
Fabio Niephaus
4a200f28cd Bump version to 1.2.6. 2024-11-13 21:01:33 +01:00
Fabio Niephaus
a8c0509ec2 Revert "Upgrade musl and follow recommendation."
This reverts commit 9dd2b41757.
2024-11-13 21:01:33 +01:00
Fabio Niephaus
557ffcf459 Bump version to 1.2.5. 2024-10-29 15:50:32 +01:00
Fabio Niephaus
f7c3ab9a9a Upgrade to macos-13.
Context: https://github.com/actions/runner-images/issues/10721
2024-10-29 15:50:32 +01:00
Fabio Niephaus
dee12811d5 Update tests to use GraalVM for JDK 22 and 23-ea. 2024-10-29 15:50:32 +01:00
Fabio Niephaus
9dd2b41757 Upgrade musl and follow recommendation.
Closes #113
2024-10-29 15:50:32 +01:00
Fabio Niephaus
3aaf71e276 Fix and improve README.md.
Thanks to @Marcono1234 for the suggestions.
2024-10-17 22:19:35 +02:00
Fabio Niephaus
17d757cc41 Add 'Supported distributions' section.
Related to #107.
2024-10-17 22:19:35 +02:00
Fabio Niephaus
24013ae277 Upgrade job to 17.0.13. 2024-10-17 22:19:35 +02:00
Fabio Niephaus
caa712a441 Recommend actions/upload-artifact@v4. [ci skip]
Fixes #111.

https://github.blog/changelog/2024-02-13-deprecation-notice-v1-and-v2-of-the-artifact-actions/
2024-10-17 22:19:35 +02:00
Fabio Niephaus
6f327093bb Bump version to 1.2.4. 2024-10-15 15:02:57 +02:00
Fabio Niephaus
4873ae0b28 Add support for Oracle GraalVM via GDS. 2024-10-14 17:35:04 +02:00
Fabio Niephaus
c3163945bd Update dependency. 2024-10-14 17:35:04 +02:00
Fabio Niephaus
c60701d448 Upgrade to macos-12.
`macos-11` was removed in June 2024:
https://github.blog/changelog/2024-05-20-actions-upcoming-changes-to-github-hosted-macos-runners/
2024-08-12 11:44:53 +02:00
Fabio Niephaus
22cc13fe88 Bump version to 1.2.3. 2024-08-09 15:00:57 +02:00
Fabio Niephaus
6bb7c0d4f1 Update dist files. 2024-08-09 15:00:57 +02:00
Fabio Niephaus
ee6894e12f Polish native-image-pr-reports-update-existing. 2024-08-09 15:00:57 +02:00
Lauri Huotari (Github Mrflatt)
cc51024a44 Add input option to merge pr reports 2024-08-09 15:00:57 +02:00
Fabio Niephaus
2911b2304b Bump version to 1.2.1. 2024-06-18 17:53:39 +02:00
Fabio Niephaus
00a7ff5258 Update dist files. 2024-06-18 17:53:39 +02:00
Fabio Niephaus
010c924385 Adjust to updated GDS behavior. 2024-06-18 17:53:39 +02:00
Fabio Niephaus
bafd5b75bd Mention some newer Java versions. 2024-06-18 17:53:39 +02:00
dependabot[bot]
e92be2ccca Bump braces from 3.0.2 to 3.0.3
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-18 10:58:38 +02:00
dependabot[bot]
809512d83d Bump undici from 5.28.3 to 5.28.4
Bumps [undici](https://github.com/nodejs/undici) from 5.28.3 to 5.28.4.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v5.28.3...v5.28.4)

---
updated-dependencies:
- dependency-name: undici
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-28 18:37:22 +02:00
Fabio Niephaus
2f25c0caae Bump version to 1.2.1. 2024-03-21 12:07:27 +01:00
Fabio Niephaus
ee8b81f45c Use NATIVE_IMAGE_OPTIONS if possible. 2024-03-21 08:37:34 +01:00
Fabio Niephaus
3e1010f34c Update EA template. 2024-03-21 08:13:50 +01:00
Fabio Niephaus
fb9f5a0734 Add GraalVM for JDK 22 to build matrix. 2024-03-21 08:13:30 +01:00
Fabio Niephaus
6c07077221 Bump version to 1.2.0. 2024-03-18 17:12:35 +01:00
Fabio Niephaus
3d5584d4fc Update httpclient version and other dependencies. 2024-03-18 17:11:31 +01:00
peterz
a19f51dc38 Cleanups 2024-03-18 16:34:28 +01:00
peterz
30261a858e Use java-package input instead of version 2024-03-18 16:34:28 +01:00
peterz
6670574f7f Bumped version 2024-03-18 16:34:27 +01:00
peterz
d9e910f637 Removed mentions of 'version=core' 2024-03-18 16:34:27 +01:00
peterz
5302a697e3 Added Liberica to README 2024-03-18 16:34:27 +01:00
peterz
049aa7c191 Musl support 2024-03-18 16:34:27 +01:00
peterz
df4b80eebe Added Liberica distribution 2024-03-18 16:34:26 +01:00
Fabio Niephaus
3d7ab58c1d Bump version to 1.1.9. 2024-03-12 20:41:34 +01:00
Fabio Niephaus
d3f9e14fc3 Fix and test check for MSVC setup. 2024-03-12 17:01:21 +01:00
Fabio Niephaus
b03aef7455 Fix GraalVM for JDK 17+ detection in MSVC feature.
Fixes #88
2024-03-12 17:01:21 +01:00
Fabio Niephaus
5393c3d809 Use -version on JDK 8. Fixes #86 2024-02-23 08:45:57 +01:00
Fabio Niephaus
e878075a91 Bump version to 1.1.8. 2024-02-22 13:17:14 +01:00
Fabio Niephaus
9a425fb910 Report java --version when done.
Fixes #81
2024-02-22 13:17:14 +01:00
Fabio Niephaus
7652cc43b3 Disable MSVC feature for javaVersion gte 18.
Fixes #32.
2024-02-22 13:17:14 +01:00
Fabio Niephaus
a2b35c9a1c Turn descriptions for versions & distros into list.
[ci skip]
2024-02-22 13:17:14 +01:00
Fabio Niephaus
791f27b2b8 Document support for Oracle GraalVM EA builds.
[ci skip]
2024-02-22 13:17:14 +01:00
Fabio Niephaus
f6947ecb49 Derive javaVersion from downloadUrl.
This ensures that `latest-ea` and `22-ea` can be cached based on the actual version number (e.g., `22.0.0`).
2024-02-22 13:17:14 +01:00
Fabio Niephaus
cb063c121c Use new Oracle GraalVM EA builds repo. 2024-02-22 13:17:14 +01:00
dependabot[bot]
076347913e Bump undici from 5.28.2 to 5.28.3
Bumps [undici](https://github.com/nodejs/undici) from 5.28.2 to 5.28.3.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v5.28.2...v5.28.3)

---
updated-dependencies:
- dependency-name: undici
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-19 09:32:54 +01:00
Fabio Niephaus
d72e3dbf5f Bump version to 1.1.7. 2024-02-13 17:28:29 +01:00
Fabio Niephaus
22551b2bec Minor edit. 2024-02-13 17:16:15 +01:00
Fabio Niephaus
bf3e45bce6 Use toSemVer() for tool name. 2024-02-13 15:44:22 +01:00
Fabio Niephaus
1588b03f82 Use semver in toSemVer(). 2024-02-13 15:44:08 +01:00
Fabio Niephaus
6df9f698c6 Avoid deprecated methods in tests. 2024-02-13 15:43:34 +01:00
Fabio Niephaus
2408275e34 Add initial support for early access (EA) builds. 2024-02-13 13:37:00 +01:00
Fabio Niephaus
a638430bc0 Move migration notice further down. 2024-02-08 12:05:32 +01:00
Fabio Niephaus
3bd233e767 Test on macos-14 (macOS on Apple Silicon).
For context: https://github.blog/changelog/2024-01-30-github-actions-introducing-the-new-m1-macos-runner-available-to-open-source/
2024-01-31 14:27:15 +01:00
Fabio Niephaus
c99915cc1a Upgrade actions/setup-node to v4. 2024-01-31 14:27:03 +01:00
Jongwoo Han
a0f131ece5 Upgrade node-version to v20. 2024-01-31 14:35:58 +09:00
23 changed files with 29904 additions and 11092 deletions

View File

@@ -26,10 +26,10 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set Node.js 16.x - name: Set Node.js 20.x
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: 16.x node-version: 20.x
cache: npm cache: npm
- name: Install dependencies - name: Install dependencies

View File

@@ -25,11 +25,23 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
java-version: ['21', '17', '20', 'dev'] java-version: ['23', '21', '17', '20', 'dev']
distribution: ['graalvm', 'graalvm-community'] distribution: ['graalvm', 'graalvm-community']
os: [macos-latest, windows-latest, ubuntu-latest] os: [
ubuntu-latest,
macos-latest, # macOS on Apple silicon
macos-13, # macOS on Intel
windows-latest
]
set-gds-token: [false]
components: [''] components: ['']
include: include:
- java-version: 'latest-ea'
distribution: 'graalvm'
os: ubuntu-latest
- java-version: '24-ea'
distribution: 'graalvm'
os: ubuntu-latest
- java-version: '21' - java-version: '21'
distribution: '' distribution: ''
os: ubuntu-latest os: ubuntu-latest
@@ -43,6 +55,14 @@ jobs:
- java-version: '21.0.0' # test for GA version (see #63) - java-version: '21.0.0' # test for GA version (see #63)
distribution: 'graalvm' distribution: 'graalvm'
os: ubuntu-latest os: ubuntu-latest
- java-version: '17'
distribution: 'graalvm'
os: ubuntu-latest
set-gds-token: true
- java-version: '17.0.13'
distribution: 'graalvm'
os: ubuntu-latest
set-gds-token: true
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Run setup-graalvm action - name: Run setup-graalvm action
@@ -52,6 +72,9 @@ jobs:
distribution: ${{ matrix.distribution }} distribution: ${{ matrix.distribution }}
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
components: ${{ matrix.components }} components: ${{ matrix.components }}
gds-token: ${{ matrix.set-gds-token && secrets.GDS_TOKEN || '' }}
# Skip in PR builds that require a GDS token (secrets are not available in PR runs)
if: github.event_name != 'pull_request' || !matrix.set-gds-token
- name: Check environment - name: Check environment
run: | run: |
echo "GRAALVM_HOME: $GRAALVM_HOME" echo "GRAALVM_HOME: $GRAALVM_HOME"
@@ -64,15 +87,16 @@ jobs:
java --version java --version
java --version | grep "GraalVM" || exit 34 java --version | grep "GraalVM" || exit 34
native-image --version native-image --version
if: runner.os != 'Windows' if: runner.os != 'Windows' && (github.event_name != 'pull_request' || !matrix.set-gds-token)
- name: Check Windows environment - name: Check Windows environment
run: | run: |
echo "GRAALVM_HOME: $env:GRAALVM_HOME" echo "GRAALVM_HOME: $env:GRAALVM_HOME"
echo "JAVA_HOME: $env:JAVA_HOME" echo "JAVA_HOME: $env:JAVA_HOME"
java --version java --version
native-image --version native-image --version
if: runner.os == 'Windows'
test-ce: # make sure the action works on a clean machine without building test-ce: # make sure the action works on a clean machine without building
needs: test needs: test
name: CE ${{ matrix.version }} + JDK${{ matrix.java-version }} on ${{ matrix.os }} name: CE ${{ matrix.version }} + JDK${{ matrix.java-version }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
@@ -91,10 +115,14 @@ jobs:
java-version: '17' java-version: '17'
components: 'native-image' components: 'native-image'
os: ubuntu-20.04 os: ubuntu-20.04
- version: '22.3.1' - version: '21.2.0'
java-version: '11' # for JDK11 notification java-version: '8' # for JDK 8 notification
components: 'native-image' components: 'native-image'
os: macos-11 os: ubuntu-latest
- version: '22.3.1'
java-version: '11' # for JDK 11 notification
components: 'native-image'
os: macos-13
- version: '22.3.1' - version: '22.3.1'
java-version: '17' java-version: '17'
components: 'native-image' components: 'native-image'
@@ -121,8 +149,8 @@ jobs:
[[ "$GRAALVM_HOME" == *"$RUNNER_TOOL_CACHE"* ]] || exit 23 [[ "$GRAALVM_HOME" == *"$RUNNER_TOOL_CACHE"* ]] || exit 23
fi fi
echo "JAVA_HOME: $JAVA_HOME" echo "JAVA_HOME: $JAVA_HOME"
java --version java -version
java --version | grep "GraalVM" || exit 34 java -version 2>&1 | grep "GraalVM" || exit 34
native-image --version native-image --version
if [[ "${{ matrix.java-version }}" != "dev" ]]; then if [[ "${{ matrix.java-version }}" != "dev" ]]; then
gu list gu list
@@ -132,7 +160,7 @@ jobs:
run: | run: |
echo "GRAALVM_HOME: $env:GRAALVM_HOME" echo "GRAALVM_HOME: $env:GRAALVM_HOME"
echo "JAVA_HOME: $env:JAVA_HOME" echo "JAVA_HOME: $env:JAVA_HOME"
java --version java -version
native-image --version native-image --version
gu.cmd remove native-image gu.cmd remove native-image
if: runner.os == 'Windows' if: runner.os == 'Windows'
@@ -228,6 +256,48 @@ jobs:
java --version java --version
native-image --version native-image --version
if: runner.os == 'Windows' if: runner.os == 'Windows'
test-liberica:
needs: test
name: Liberica (${{ matrix.java-version }}, '${{ matrix.java-package }}', ${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
matrix:
java-version: ['17', '21.0.2']
java-package: ['', 'jdk', 'jdk+fx']
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- name: Run setup-graalvm action
uses: ./
with:
distribution: liberica
java-version: ${{ matrix.java-version }}
java-package: ${{ matrix.java-package }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Check environment
run: |
echo "GRAALVM_HOME: $GRAALVM_HOME"
[[ "$GRAALVM_HOME" == *"$RUNNER_TOOL_CACHE"* ]] || exit 12
echo "JAVA_HOME: $JAVA_HOME"
java --version
java --version | fgrep -qw ${{ matrix.java-version }} || exit 23
native-image --version
native-image --version | fgrep -qw ${{ matrix.java-version }} || exit 24
if: runner.os != 'Windows'
- name: Check Windows environment
shell: pwsh
run: |
echo "GRAALVM_HOME: $env:GRAALVM_HOME"
echo "JAVA_HOME: $env:JAVA_HOME"
java --version
if (!(java --version | findstr \<${{ matrix.java-version }}\>)) {
exit 23
}
native-image --version
if (!(native-image --version | findstr \<${{ matrix.java-version }}\>)) {
exit 24
}
if: runner.os == 'Windows'
test-native-image-windows: test-native-image-windows:
name: native-image on windows-latest name: native-image on windows-latest
runs-on: windows-latest runs-on: windows-latest

199
README.md
View File

@@ -1,11 +1,11 @@
# GitHub Action for GraalVM [![build-test](https://github.com/graalvm/setup-graalvm/actions/workflows/test.yml/badge.svg)](https://github.com/graalvm/setup-graalvm/actions/workflows/test.yml) # GitHub Action for GraalVM [![build-test](https://github.com/graalvm/setup-graalvm/actions/workflows/test.yml/badge.svg)](https://github.com/graalvm/setup-graalvm/actions/workflows/test.yml)
This GitHub action sets up [Oracle GraalVM][graalvm-medium], GraalVM [Community Edition (CE)][repo], [Enterprise Edition (EE)][graalvm-ee], or [Mandrel][mandrel], as well as [Native Image][native-image] and GraalVM components such as [Truffle languages][truffle-languages]. This GitHub action sets up [Oracle GraalVM][graalvm-medium], GraalVM [Community Edition (CE)][repo], [Enterprise Edition (EE)][graalvm-ee], [Mandrel][mandrel], or [Liberica Native Image Kit][liberica] as well as [Native Image][native-image] and GraalVM components such as [Truffle languages][truffle-languages].
## Key Features ## Key Features
This action: This action:
- supports Oracle GraalVM [releases][graalvm-dl], GraalVM Community Edition (CE) [releases], [dev builds][dev-builds], GraalVM Enterprise Edition (EE) [releases][graalvm-ee] (set [`gds-token`](#options)) 22.1.0 and later, and [Mandrel][mandrel] (see [Options](#options)) - supports Oracle GraalVM [releases][graalvm-dl], [EA builds][ea-builds], GraalVM Community Edition (CE) [releases], [dev builds][dev-builds], GraalVM Enterprise Edition (EE) [releases][graalvm-ee] (set [`gds-token`](#options)) 22.1.0 and later, [Mandrel][mandrel], and [Liberica Native Image Kit][liberica] (see [Options](#options))
- exports a `$GRAALVM_HOME` environment variable - exports a `$GRAALVM_HOME` environment variable
- adds `$GRAALVM_HOME/bin` to the `$PATH` environment variable<br>(Native Image, Truffle languages, and tools can be invoked directly) - adds `$GRAALVM_HOME/bin` to the `$PATH` environment variable<br>(Native Image, Truffle languages, and tools can be invoked directly)
- sets `$JAVA_HOME` to `$GRAALVM_HOME` by default<br>(can be disabled via `set-java-home: 'false'`, see [Options](#options)) - sets `$JAVA_HOME` to `$GRAALVM_HOME` by default<br>(can be disabled via `set-java-home: 'false'`, see [Options](#options))
@@ -15,34 +15,6 @@ This action:
- has built-in support for GraalVM components and the [GraalVM Updater][gu] - has built-in support for GraalVM components and the [GraalVM Updater][gu]
## Migrating from GraalVM 22.3 or Earlier to the New GraalVM for JDK 17 and Later
The [GraalVM for JDK 17 and JDK 20 release](https://medium.com/graalvm/a-new-graalvm-release-and-new-free-license-4aab483692f5) aligns the GraalVM version scheme with OpenJDK.
As a result, this action no longer requires the `version` option to select a specific GraalVM version.
At the same time, it introduces a new `distribution` option to select a specific GraalVM distribution (`graalvm`, `graalvm-community`, or `mandrel`).
Therefore, to migrate your workflow to use the latest GraalVM release, replace the `version` with the `distribution` option in the workflow `yml` config, for example:
```yml
# ...
- uses: graalvm/setup-graalvm@v1
with:
java-version: '17'
version: '22.3.2' # Old 'version' option for the GraalVM version
# ...
```
can be replaced with:
```yml
# ...
- uses: graalvm/setup-graalvm@v1
with:
java-version: '17.0.7' # for a specific JDK 17; or '17' for the latest JDK 17
distribution: 'graalvm' # New 'distribution' option
# ...
```
## Templates ## Templates
### Quickstart Template ### Quickstart Template
@@ -57,8 +29,8 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: graalvm/setup-graalvm@v1 - uses: graalvm/setup-graalvm@v1
with: with:
java-version: '21' java-version: '21' # See 'Options' for more details
distribution: 'graalvm' # See 'Options' for all available distributions distribution: 'graalvm' # See 'Supported distributions' for available options
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Example step - name: Example step
run: | run: |
@@ -102,17 +74,16 @@ jobs:
./helloworld ./helloworld
- name: Upload binary - name: Upload binary
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v4
with: with:
name: helloworld-${{ matrix.os }} name: helloworld-${{ matrix.os }}
path: helloworld* path: helloworld*
``` ```
<details> ### Template for Oracle GraalVM Early Access (EA) builds
<summary><h4>Template for older GraalVM releases</h4></summary>
```yml ```yml
name: GraalVM build name: Oracle GraalVM Early Access build
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
build: build:
@@ -121,12 +92,54 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: graalvm/setup-graalvm@v1 - uses: graalvm/setup-graalvm@v1
with: with:
version: '22.3.2' # GraalVM version java-version: '24-ea' # or 'latest-ea' for the latest Java version available
java-version: '17' distribution: 'graalvm'
components: 'native-image'
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
``` ```
<details>
<summary><h4>Template for Oracle GraalVM via GraalVM Download Service</h4></summary>
#### Prerequisites
1. Obtain a token for the GraalVM Download Service. For this, replace `your@email.com` with your email address and run the following `curl` command:
```bash
curl -sS -X POST "https://gds.oracle.com/api/20220101/licenseAcceptance" \
-H "Content-Type: application/json" \
-d "{ \"email\": \"your@email.com\", \"licenseId\": \"D53FA58D12817B3CE0530F15000A74CA\", \"type\": \"GENERATE_TOKEN_AND_ACCEPT_LICENSE\"}"
```
The response should look like this:
```json
{"token":"<your-token>","status":"UNVERIFIED"}
```
2. Store the value of `<your-token>` as a [GitHub Action secret][gha-secrets]. For the following template, we use the name `GDS_TOKEN`.
3. Check your emails and accept the license to activate the token.
4. Use `java-version: '17'` (or a specific version such as `17.0.13`) and provide the `GDS_TOKEN` as shown in the following template:
```yml
name: Build with Oracle GraalVM for JDK 17 via GDS
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: graalvm/setup-graalvm@v1
with:
distribution: 'graalvm'
java-version: '17'
gds-token: ${{ secrets.GDS_TOKEN }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Example step
run: |
java --version
native-image --version
```
</details> </details>
<details> <details>
@@ -137,37 +150,53 @@ jobs:
1. Download the version of [GraalVM Enterprise Edition (EE)][graalvm-ee] you want to run on GitHub Actions. 1. Download the version of [GraalVM Enterprise Edition (EE)][graalvm-ee] you want to run on GitHub Actions.
2. Use the [GraalVM Updater][gu] to install the GraalVM components you need on GitHub Actions and accept the corresponding licenses. 2. Use the [GraalVM Updater][gu] to install the GraalVM components you need on GitHub Actions and accept the corresponding licenses.
3. Run `$GRAALVM_HOME/bin/gu --show-ee-token` to display your token for the GraalVM Download Service. 3. Run `$GRAALVM_HOME/bin/gu --show-ee-token` to display your token for the GraalVM Download Service.
4. Store this token as a [GitHub Action secret][gha-secrets]. For this template, we use the name `GDS_TOKEN`. 4. Store this token as a [GitHub Action secret][gha-secrets]. In the following template, we use the name `GDS_TOKEN`:
```yml ```yml
name: GraalVM Enterprise Edition build name: GraalVM Enterprise Edition build
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: graalvm/setup-graalvm@v1 - uses: graalvm/setup-graalvm@v1
with: with:
version: '22.3.0' version: '22.3.0'
gds-token: ${{ secrets.GDS_TOKEN }} gds-token: ${{ secrets.GDS_TOKEN }}
java-version: '17' java-version: '17'
components: 'native-image' components: 'native-image'
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Example step - name: Example step
run: | run: |
java --version java --version
native-image --version native-image --version
``` ```
</details> </details>
## Supported distributions
Currently, the following distributions are supported:
| Keyword | Distribution | Official site | License |
|-|-|-|-|
| `graalvm` | Oracle GraalVM | [Link](https://www.graalvm.org/) | [Link](https://www.oracle.com/downloads/licenses/graal-free-license.html) |
| `graalvm-community` | GraalVM Community Edition | [Link](https://www.graalvm.org/) | [Link](https://github.com/oracle/graal/blob/master/LICENSE) |
| `mandrel` | Mandrel | [Link](https://github.com/graalvm/mandrel) | [Link](https://github.com/graalvm/mandrel/blob/default/LICENSE) |
| `liberica` | Liberica NIK | [Link](https://bell-sw.com/liberica-native-image-kit/) | [Link](https://bell-sw.com/liberica_nik_eula/) |
## Options ## Options
This actions can be configured with the following options:
| Name | Default | Description | | Name | Default | Description |
|-----------------|:--------:|-------------| |-----------------|:--------:|-------------|
| `java-version`<br>*(required)* | n/a | `'21'` or `'17.0.7'` for a specific Java version, `'dev'` for a dev build with the latest Java version available.<br>(`'8'`, `'11'`, `'16'`, `'19'` are supported for older GraalVM releases.) | | `java-version`<br>*(required)* | n/a | Java version <ul><li>major versions: `'23'`, `'21'`, `'17'`, `'11'`, `'8'`</li><li>specific versions: `'21.0.3'`, `'17.0.11'`</li><li>early access (EA) builds: `'24-ea'` *(requires `distribution: 'graalvm'`)*</li><li>latest EA build: `'latest-ea'` *(requires `distribution: 'graalvm'`)*</li><li>dev builds: `'dev'`</li></ul> |
| `distribution` | `''` | GraalVM distribution (`graalvm` for Oracle GraalVM, `graalvm-community` for GraalVM Community Edition, `mandrel` for Mandrel). | | `distribution` | `'graalvm'` | GraalVM distribution (see [supported distributions](#supported-distributions)) |
| `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. | | `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. |
| `set-java-home` | `'true'` | If set to `'true'`, instructs the action to set `$JAVA_HOME` to the path of the GraalVM installation. Overrides any previous action or command that sets `$JAVA_HOME`. | | `set-java-home` | `'true'` | If set to `'true'`, instructs the action to set `$JAVA_HOME` to the path of the GraalVM installation. Overrides any previous action or command that sets `$JAVA_HOME`. |
| `cache` | `''` | Name of the build platform to cache dependencies. Turned off by default (`''`). It can also be `'maven'`, `'gradle'`, or `'sbt'` and works the same way as described in [actions/setup-java][setup-java-caching]. | | `cache` | `''` | Name of the build platform to cache dependencies. Turned off by default (`''`). It can also be `'maven'`, `'gradle'`, or `'sbt'` and works the same way as described in [actions/setup-java][setup-java-caching]. |
@@ -175,13 +204,54 @@ jobs:
| `native-image-musl` | `'false'` | If set to `'true'`, sets up [musl] to build [static binaries][native-image-static] with GraalVM Native Image *(Linux only)*. [Example usage][native-image-musl-build] (be sure to replace `uses: ./` with `uses: graalvm/setup-graalvm@v1`). | | `native-image-musl` | `'false'` | If set to `'true'`, sets up [musl] to build [static binaries][native-image-static] with GraalVM Native Image *(Linux only)*. [Example usage][native-image-musl-build] (be sure to replace `uses: ./` with `uses: graalvm/setup-graalvm@v1`). |
| `native-image-job-reports` *) | `'false'` | If set to `'true'`, post a job summary containing a Native Image build report. | | `native-image-job-reports` *) | `'false'` | If set to `'true'`, post a job summary containing a Native Image build report. |
| `native-image-pr-reports` *) | `'false'` | If set to `'true'`, post a comment containing a Native Image build report on pull requests. Requires `write` permissions for the [`pull-requests` scope][gha-permissions]. | | `native-image-pr-reports` *) | `'false'` | If set to `'true'`, post a comment containing a Native Image build report on pull requests. Requires `write` permissions for the [`pull-requests` scope][gha-permissions]. |
| `native-image-pr-reports-update-existing` *) | `'false'` | Instead of posting another comment, update an existing PR comment with the latest Native Image build report. Requires `native-image-pr-reports` to be `true`. |
| `components` | `''` | Comma-separated list of GraalVM components (e.g., `native-image` or `ruby,nodejs`) that will be installed by the [GraalVM Updater][gu]. | | `components` | `''` | Comma-separated list of GraalVM components (e.g., `native-image` or `ruby,nodejs`) that will be installed by the [GraalVM Updater][gu]. |
| `version` | `''` | `X.Y.Z` (e.g., `22.3.0`) for a specific [GraalVM release][releases] up to `22.3.2`<br>`mandrel-X.Y.Z.W` or `X.Y.Z.W-Final` (e.g., `mandrel-21.3.0.0-Final` or `21.3.0.0-Final`) for a specific [Mandrel release][mandrel-releases],<br>`mandrel-latest` or `latest` for the latest Mandrel stable release. | | `version` | `''` | `X.Y.Z` (e.g., `22.3.0`) for a specific [GraalVM release][releases] up to `22.3.2`<br>`mandrel-X.Y.Z.W` or `X.Y.Z.W-Final` (e.g., `mandrel-21.3.0.0-Final` or `21.3.0.0-Final`) for a specific [Mandrel release][mandrel-releases],<br>`mandrel-latest` or `latest` for the latest Mandrel stable release. |
| `gds-token` | `''` | Download token for the GraalVM Download Service. If a non-empty token is provided, the action will set up GraalVM Enterprise Edition (see [GraalVM EE template](#template-for-graalvm-enterprise-edition)). | | `gds-token` | `''` Download token for the GraalVM Download Service. If a non-empty token is provided, the action will set up Oracle GraalVM (see [Oracle GraalVM via GDS template](#template-for-oracle-graalvm-via-graalvm-download-service)) or GraalVM Enterprise Edition (see [GraalVM EE template](#template-for-graalvm-enterprise-edition)) via GDS. |
**) Make sure that Native Image is used only once per build job. Otherwise, the report is only generated for the last Native Image build.* **) Make sure that Native Image is used only once per build job. Otherwise, the report is only generated for the last Native Image build.*
## Notes on Oracle GraalVM for JDK 17
GraalVM for JDK 17.0.12 is the [last release of Oracle GraalVM for JDK 17 under the GFTC](https://blogs.oracle.com/java/post/jdk-17-approaches-endofpermissive-license).
Updates after September 2024 will be licensed under the [GraalVM OTN License Including License for Early Adopter Versions](https://www.oracle.com/downloads/licenses/graalvm-otn-license.html) (GOTN) and production use beyond the limited free grants of the GraalVM OTN license will require a fee.
As a user of `setup-graalvm`, you have the following options:
- *Recommended*: Upgrade to Oracle GraalVM for JDK 21 or later to receive new updates.
- *Not recommended*: Instead of `java-version: '17'`, use `java-version: '17.0.12'` in your workflow to keep using the last release under GFTC. This will also disable the warning. Note that switching to GraalVM Community Edition or other GraalVM distributions might provide you with even older releases of GraalVM.
- Provide a `gds-token` to access Oracle GraalVM for JDK 17 under GOTN (see [Oracle GraalVM via GDS template](#template-for-oracle-graalvm-via-graalvm-download-service)).
## Migrating from GraalVM 22.3 or Earlier to the New GraalVM for JDK 17 and Later
The [GraalVM for JDK 17 and JDK 20 release](https://medium.com/graalvm/a-new-graalvm-release-and-new-free-license-4aab483692f5) aligns the GraalVM version scheme with OpenJDK.
As a result, this action no longer requires the `version` option to select a specific GraalVM version.
At the same time, it introduces a new `distribution` option to select a specific GraalVM distribution (`graalvm`, `graalvm-community`, or `mandrel`).
Therefore, to migrate your workflow to use the latest GraalVM release, replace the `version` with the `distribution` option in the workflow `yml` config, for example:
```yml
# ...
- uses: graalvm/setup-graalvm@v1
with:
java-version: '17'
version: '22.3.2' # Old 'version' option for the GraalVM version
# ...
```
can be replaced with:
```yml
# ...
- uses: graalvm/setup-graalvm@v1
with:
java-version: '17.0.12' # for a specific JDK 17; or '17' for the latest JDK 17
distribution: 'graalvm' # New 'distribution' option
# ...
```
## Contributing ## Contributing
We welcome code contributions. To get started, you will need to sign the [Oracle Contributor Agreement][oca] (OCA). We welcome code contributions. To get started, you will need to sign the [Oracle Contributor Agreement][oca] (OCA).
@@ -191,6 +261,8 @@ Only pull requests from committers that can be verified as having signed the OCA
[dev-build]: https://github.com/graalvm/graalvm-ce-dev-builds/releases/latest [dev-build]: https://github.com/graalvm/graalvm-ce-dev-builds/releases/latest
[dev-builds]: https://github.com/graalvm/graalvm-ce-dev-builds [dev-builds]: https://github.com/graalvm/graalvm-ce-dev-builds
[ea-builds]: https://github.com/graalvm/oracle-graalvm-ea-builds
[gftc]: https://www.oracle.com/downloads/licenses/graal-free-license.html
[gha-annotations]: https://github.com/actions/toolkit/tree/main/packages/core#annotations [gha-annotations]: https://github.com/actions/toolkit/tree/main/packages/core#annotations
[gha-permissions]: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions [gha-permissions]: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
[gha-secrets]: https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository [gha-secrets]: https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository
@@ -200,6 +272,7 @@ Only pull requests from committers that can be verified as having signed the OCA
[graalvm-dl]: https://www.oracle.com/java/technologies/downloads/ [graalvm-dl]: https://www.oracle.com/java/technologies/downloads/
[graalvm-medium]: https://medium.com/graalvm/a-new-graalvm-release-and-new-free-license-4aab483692f5 [graalvm-medium]: https://medium.com/graalvm/a-new-graalvm-release-and-new-free-license-4aab483692f5
[graalvm-ee]: https://www.oracle.com/downloads/graalvm-downloads.html [graalvm-ee]: https://www.oracle.com/downloads/graalvm-downloads.html
[liberica]: https://bell-sw.com/liberica-native-image-kit/
[mandrel]: https://github.com/graalvm/mandrel [mandrel]: https://github.com/graalvm/mandrel
[mandrel-releases]: https://github.com/graalvm/mandrel/releases [mandrel-releases]: https://github.com/graalvm/mandrel/releases
[mandrel-stable]: https://github.com/graalvm/mandrel/releases/latest [mandrel-stable]: https://github.com/graalvm/mandrel/releases/latest

View File

@@ -101,14 +101,14 @@ describe('dependency cache', () => {
}) })
it('throws error if unsupported package manager specified', () => { it('throws error if unsupported package manager specified', () => {
return expect(restore('ant')).rejects.toThrowError( return expect(restore('ant')).rejects.toThrow(
'unknown package manager specified: ant' 'unknown package manager specified: ant'
) )
}) })
describe('for maven', () => { describe('for maven', () => {
it('throws error if no pom.xml found', async () => { it('throws error if no pom.xml found', async () => {
await expect(restore('maven')).rejects.toThrowError( await expect(restore('maven')).rejects.toThrow(
`No file in ${projectRoot( `No file in ${projectRoot(
workspace workspace
)} matched to [**/pom.xml], make sure you have checked out the target repository` )} matched to [**/pom.xml], make sure you have checked out the target repository`
@@ -118,14 +118,14 @@ describe('dependency cache', () => {
createFile(join(workspace, 'pom.xml')) createFile(join(workspace, 'pom.xml'))
await restore('maven') await restore('maven')
expect(spyCacheRestore).toBeCalled() expect(spyCacheRestore).toHaveBeenCalled()
expect(spyWarning).not.toBeCalled() expect(spyWarning).not.toHaveBeenCalled()
expect(spyInfo).toBeCalledWith('maven cache is not found') expect(spyInfo).toHaveBeenCalledWith('maven cache is not found')
}) })
}) })
describe('for gradle', () => { describe('for gradle', () => {
it('throws error if no build.gradle found', async () => { it('throws error if no build.gradle found', async () => {
await expect(restore('gradle')).rejects.toThrowError( await expect(restore('gradle')).rejects.toThrow(
`No file in ${projectRoot( `No file in ${projectRoot(
workspace workspace
)} matched to [**/*.gradle*,**/gradle-wrapper.properties,buildSrc/**/Versions.kt,buildSrc/**/Dependencies.kt], make sure you have checked out the target repository` )} matched to [**/*.gradle*,**/gradle-wrapper.properties,buildSrc/**/Versions.kt,buildSrc/**/Dependencies.kt], make sure you have checked out the target repository`
@@ -135,17 +135,17 @@ describe('dependency cache', () => {
createFile(join(workspace, 'build.gradle')) createFile(join(workspace, 'build.gradle'))
await restore('gradle') await restore('gradle')
expect(spyCacheRestore).toBeCalled() expect(spyCacheRestore).toHaveBeenCalled()
expect(spyWarning).not.toBeCalled() expect(spyWarning).not.toHaveBeenCalled()
expect(spyInfo).toBeCalledWith('gradle cache is not found') expect(spyInfo).toHaveBeenCalledWith('gradle cache is not found')
}) })
it('downloads cache based on build.gradle.kts', async () => { it('downloads cache based on build.gradle.kts', async () => {
createFile(join(workspace, 'build.gradle.kts')) createFile(join(workspace, 'build.gradle.kts'))
await restore('gradle') await restore('gradle')
expect(spyCacheRestore).toBeCalled() expect(spyCacheRestore).toHaveBeenCalled()
expect(spyWarning).not.toBeCalled() expect(spyWarning).not.toHaveBeenCalled()
expect(spyInfo).toBeCalledWith('gradle cache is not found') expect(spyInfo).toHaveBeenCalledWith('gradle cache is not found')
}) })
}) })
it('downloads cache based on buildSrc/Versions.kt', async () => { it('downloads cache based on buildSrc/Versions.kt', async () => {
@@ -153,13 +153,13 @@ describe('dependency cache', () => {
createFile(join(workspace, 'buildSrc', 'Versions.kt')) createFile(join(workspace, 'buildSrc', 'Versions.kt'))
await restore('gradle') await restore('gradle')
expect(spyCacheRestore).toBeCalled() expect(spyCacheRestore).toHaveBeenCalled()
expect(spyWarning).not.toBeCalled() expect(spyWarning).not.toHaveBeenCalled()
expect(spyInfo).toBeCalledWith('gradle cache is not found') expect(spyInfo).toHaveBeenCalledWith('gradle cache is not found')
}) })
describe('for sbt', () => { describe('for sbt', () => {
it('throws error if no build.sbt found', async () => { it('throws error if no build.sbt found', async () => {
await expect(restore('sbt')).rejects.toThrowError( await expect(restore('sbt')).rejects.toThrow(
`No file in ${projectRoot( `No file in ${projectRoot(
workspace workspace
)} matched to [**/*.sbt,**/project/build.properties,**/project/**.{scala,sbt}], make sure you have checked out the target repository` )} matched to [**/*.sbt,**/project/build.properties,**/project/**.{scala,sbt}], make sure you have checked out the target repository`
@@ -169,9 +169,9 @@ describe('dependency cache', () => {
createFile(join(workspace, 'build.sbt')) createFile(join(workspace, 'build.sbt'))
await restore('sbt') await restore('sbt')
expect(spyCacheRestore).toBeCalled() expect(spyCacheRestore).toHaveBeenCalled()
expect(spyWarning).not.toBeCalled() expect(spyWarning).not.toHaveBeenCalled()
expect(spyInfo).toBeCalledWith('sbt cache is not found') expect(spyInfo).toHaveBeenCalledWith('sbt cache is not found')
}) })
}) })
}) })
@@ -191,7 +191,7 @@ describe('dependency cache', () => {
}) })
it('throws error if unsupported package manager specified', () => { it('throws error if unsupported package manager specified', () => {
return expect(save('ant')).rejects.toThrowError( return expect(save('ant')).rejects.toThrow(
'unknown package manager specified: ant' 'unknown package manager specified: ant'
) )
}) })
@@ -201,10 +201,10 @@ describe('dependency cache', () => {
createStateForMissingBuildFile() createStateForMissingBuildFile()
await save('maven') await save('maven')
expect(spyCacheSave).toBeCalled() expect(spyCacheSave).toHaveBeenCalled()
expect(spyWarning).not.toBeCalled() expect(spyWarning).not.toHaveBeenCalled()
expect(spyInfo).toBeCalled() expect(spyInfo).toHaveBeenCalled()
expect(spyInfo).toBeCalledWith( expect(spyInfo).toHaveBeenCalledWith(
expect.stringMatching(/^Cache saved with the key:.*/) expect.stringMatching(/^Cache saved with the key:.*/)
) )
}) })
@@ -225,24 +225,26 @@ describe('dependency cache', () => {
it('uploads cache even if no pom.xml found', async () => { it('uploads cache even if no pom.xml found', async () => {
createStateForMissingBuildFile() createStateForMissingBuildFile()
await save('maven') await save('maven')
expect(spyCacheSave).toBeCalled() expect(spyCacheSave).toHaveBeenCalled()
expect(spyWarning).not.toBeCalled() expect(spyWarning).not.toHaveBeenCalled()
}) })
it('does not upload cache if no restore run before', async () => { it('does not upload cache if no restore run before', async () => {
createFile(join(workspace, 'pom.xml')) createFile(join(workspace, 'pom.xml'))
await save('maven') await save('maven')
expect(spyCacheSave).not.toBeCalled() expect(spyCacheSave).not.toHaveBeenCalled()
expect(spyWarning).toBeCalledWith('Error retrieving key from state.') expect(spyWarning).toHaveBeenCalledWith(
'Error retrieving key from state.'
)
}) })
it('uploads cache', async () => { it('uploads cache', async () => {
createFile(join(workspace, 'pom.xml')) createFile(join(workspace, 'pom.xml'))
createStateForSuccessfulRestore() createStateForSuccessfulRestore()
await save('maven') await save('maven')
expect(spyCacheSave).toBeCalled() expect(spyCacheSave).toHaveBeenCalled()
expect(spyWarning).not.toBeCalled() expect(spyWarning).not.toHaveBeenCalled()
expect(spyInfo).toBeCalledWith( expect(spyInfo).toHaveBeenCalledWith(
expect.stringMatching(/^Cache saved with the key:.*/) expect.stringMatching(/^Cache saved with the key:.*/)
) )
}) })
@@ -252,24 +254,26 @@ describe('dependency cache', () => {
createStateForMissingBuildFile() createStateForMissingBuildFile()
await save('gradle') await save('gradle')
expect(spyCacheSave).toBeCalled() expect(spyCacheSave).toHaveBeenCalled()
expect(spyWarning).not.toBeCalled() expect(spyWarning).not.toHaveBeenCalled()
}) })
it('does not upload cache if no restore run before', async () => { it('does not upload cache if no restore run before', async () => {
createFile(join(workspace, 'build.gradle')) createFile(join(workspace, 'build.gradle'))
await save('gradle') await save('gradle')
expect(spyCacheSave).not.toBeCalled() expect(spyCacheSave).not.toHaveBeenCalled()
expect(spyWarning).toBeCalledWith('Error retrieving key from state.') expect(spyWarning).toHaveBeenCalledWith(
'Error retrieving key from state.'
)
}) })
it('uploads cache based on build.gradle', async () => { it('uploads cache based on build.gradle', async () => {
createFile(join(workspace, 'build.gradle')) createFile(join(workspace, 'build.gradle'))
createStateForSuccessfulRestore() createStateForSuccessfulRestore()
await save('gradle') await save('gradle')
expect(spyCacheSave).toBeCalled() expect(spyCacheSave).toHaveBeenCalled()
expect(spyWarning).not.toBeCalled() expect(spyWarning).not.toHaveBeenCalled()
expect(spyInfo).toBeCalledWith( expect(spyInfo).toHaveBeenCalledWith(
expect.stringMatching(/^Cache saved with the key:.*/) expect.stringMatching(/^Cache saved with the key:.*/)
) )
}) })
@@ -278,9 +282,9 @@ describe('dependency cache', () => {
createStateForSuccessfulRestore() createStateForSuccessfulRestore()
await save('gradle') await save('gradle')
expect(spyCacheSave).toBeCalled() expect(spyCacheSave).toHaveBeenCalled()
expect(spyWarning).not.toBeCalled() expect(spyWarning).not.toHaveBeenCalled()
expect(spyInfo).toBeCalledWith( expect(spyInfo).toHaveBeenCalledWith(
expect.stringMatching(/^Cache saved with the key:.*/) expect.stringMatching(/^Cache saved with the key:.*/)
) )
}) })
@@ -290,9 +294,9 @@ describe('dependency cache', () => {
createStateForSuccessfulRestore() createStateForSuccessfulRestore()
await save('gradle') await save('gradle')
expect(spyCacheSave).toBeCalled() expect(spyCacheSave).toHaveBeenCalled()
expect(spyWarning).not.toBeCalled() expect(spyWarning).not.toHaveBeenCalled()
expect(spyInfo).toBeCalledWith( expect(spyInfo).toHaveBeenCalledWith(
expect.stringMatching(/^Cache saved with the key:.*/) expect.stringMatching(/^Cache saved with the key:.*/)
) )
}) })
@@ -301,24 +305,26 @@ describe('dependency cache', () => {
it('uploads cache even if no build.sbt found', async () => { it('uploads cache even if no build.sbt found', async () => {
createStateForMissingBuildFile() createStateForMissingBuildFile()
await save('sbt') await save('sbt')
expect(spyCacheSave).toBeCalled() expect(spyCacheSave).toHaveBeenCalled()
expect(spyWarning).not.toBeCalled() expect(spyWarning).not.toHaveBeenCalled()
}) })
it('does not upload cache if no restore run before', async () => { it('does not upload cache if no restore run before', async () => {
createFile(join(workspace, 'build.sbt')) createFile(join(workspace, 'build.sbt'))
await save('sbt') await save('sbt')
expect(spyCacheSave).not.toBeCalled() expect(spyCacheSave).not.toHaveBeenCalled()
expect(spyWarning).toBeCalledWith('Error retrieving key from state.') expect(spyWarning).toHaveBeenCalledWith(
'Error retrieving key from state.'
)
}) })
it('uploads cache', async () => { it('uploads cache', async () => {
createFile(join(workspace, 'build.sbt')) createFile(join(workspace, 'build.sbt'))
createStateForSuccessfulRestore() createStateForSuccessfulRestore()
await save('sbt') await save('sbt')
expect(spyCacheSave).toBeCalled() expect(spyCacheSave).toHaveBeenCalled()
expect(spyWarning).not.toBeCalled() expect(spyWarning).not.toHaveBeenCalled()
expect(spyInfo).toBeCalledWith( expect(spyInfo).toHaveBeenCalledWith(
expect.stringMatching(/^Cache saved with the key:.*/) expect.stringMatching(/^Cache saved with the key:.*/)
) )
}) })

View File

@@ -27,7 +27,6 @@
import {run as cleanup} from '../src/cleanup' import {run as cleanup} from '../src/cleanup'
import * as core from '@actions/core' import * as core from '@actions/core'
import * as cache from '@actions/cache' import * as cache from '@actions/cache'
import * as util from '../src/utils'
describe('cleanup', () => { describe('cleanup', () => {
let spyWarning: jest.SpyInstance<void, Parameters<typeof core.warning>> let spyWarning: jest.SpyInstance<void, Parameters<typeof core.warning>>
@@ -62,8 +61,8 @@ describe('cleanup', () => {
return name === 'cache' ? 'gradle' : '' return name === 'cache' ? 'gradle' : ''
}) })
await cleanup() await cleanup()
expect(spyCacheSave).toBeCalled() expect(spyCacheSave).toHaveBeenCalled()
expect(spyWarning).not.toBeCalled() expect(spyWarning).not.toHaveBeenCalled()
}) })
it('does not fail even though the save process throws error', async () => { it('does not fail even though the save process throws error', async () => {
@@ -74,7 +73,7 @@ describe('cleanup', () => {
return name === 'cache' ? 'gradle' : '' return name === 'cache' ? 'gradle' : ''
}) })
await cleanup() await cleanup()
expect(spyCacheSave).toBeCalled() expect(spyCacheSave).toHaveBeenCalled()
}) })
}) })

View File

@@ -1,5 +1,10 @@
import * as path from 'path' import * as path from 'path'
import {downloadGraalVMEELegacy, fetchArtifact} from '../src/gds' import {
downloadGraalVM,
downloadGraalVMEELegacy,
fetchArtifact,
fetchArtifactEE
} from '../src/gds'
import {expect, test} from '@jest/globals' import {expect, test} from '@jest/globals'
const TEST_USER_AGENT = 'GraalVMGitHubActionTest/1.0.4' const TEST_USER_AGENT = 'GraalVMGitHubActionTest/1.0.4'
@@ -7,7 +12,28 @@ const TEST_USER_AGENT = 'GraalVMGitHubActionTest/1.0.4'
process.env['RUNNER_TEMP'] = path.join(__dirname, 'TEMP') process.env['RUNNER_TEMP'] = path.join(__dirname, 'TEMP')
test('fetch artifacts', async () => { test('fetch artifacts', async () => {
let artifact = await fetchArtifact( let artifact = await fetchArtifact(TEST_USER_AGENT, 'isBase:True', '17.0.12')
expect(artifact.id).toBe('1C351E8F41BB8E9EE0631518000AE5F2')
expect(artifact.checksum).toBe(
'b6f3dace24cf1960ec790216f4c86f00d4f43df64e4e8b548f6382f04894713f'
)
artifact = await fetchArtifact(TEST_USER_AGENT, 'isBase:True', '17')
expect(artifact.checksum).toHaveLength(
'b6f3dace24cf1960ec790216f4c86f00d4f43df64e4e8b548f6382f04894713f'.length
)
})
test('errors when downloading artifacts', async () => {
await expect(downloadGraalVM('invalid', '17')).rejects.toThrow(
'The provided "gds-token" was rejected (reason: "Invalid download token", opc-request-id: '
)
await expect(downloadGraalVM('invalid', '1')).rejects.toThrow(
'Unable to find GraalVM for JDK 1'
)
})
test('fetch legacy artifacts', async () => {
let artifact = await fetchArtifactEE(
TEST_USER_AGENT, TEST_USER_AGENT,
'isBase:True', 'isBase:True',
'22.1.0', '22.1.0',
@@ -17,25 +43,30 @@ test('fetch artifacts', async () => {
expect(artifact.checksum).toBe( expect(artifact.checksum).toBe(
'4280782f6c7fcabe0ba707e8389cbfaf7bbe6b0cf634d309e6efcd1b172e3ce6' '4280782f6c7fcabe0ba707e8389cbfaf7bbe6b0cf634d309e6efcd1b172e3ce6'
) )
artifact = await fetchArtifact(TEST_USER_AGENT, 'isBase:True', '22.1.0', '17') artifact = await fetchArtifactEE(
TEST_USER_AGENT,
'isBase:True',
'22.1.0',
'17'
)
expect(artifact.id).toBe('DCECD2068882A0E9E0536E16000A9504') expect(artifact.id).toBe('DCECD2068882A0E9E0536E16000A9504')
expect(artifact.checksum).toBe( expect(artifact.checksum).toBe(
'e897add7d94bc456a61e6f927e831dff759efa3392a4b69c720dd3debc8f947d' 'e897add7d94bc456a61e6f927e831dff759efa3392a4b69c720dd3debc8f947d'
) )
await expect( await expect(
fetchArtifact(TEST_USER_AGENT, 'isBase:False', '22.1.0', '11') fetchArtifactEE(TEST_USER_AGENT, 'isBase:False', '22.1.0', '11')
).rejects.toThrow('Found more than one GDS artifact') ).rejects.toThrow('Found more than one GDS artifact')
await expect( await expect(
fetchArtifact(TEST_USER_AGENT, 'isBase:True', '1.0.0', '11') fetchArtifactEE(TEST_USER_AGENT, 'isBase:True', '1.0.0', '11')
).rejects.toThrow('Unable to find JDK11-based GraalVM EE 1.0.0') ).rejects.toThrow('Unable to find JDK11-based GraalVM EE 1.0.0')
}) })
test('errors when downloading artifacts', async () => { test('errors when downloading legacy artifacts', async () => {
await expect( await expect(
downloadGraalVMEELegacy('invalid', '22.1.0', '11') downloadGraalVMEELegacy('invalid', '22.1.0', '11')
).rejects.toThrow( ).rejects.toThrow(
'The provided "gds-token" was rejected (reason: "Invalid download token", opc-request-id: /' 'The provided "gds-token" was rejected (reason: "Invalid download token", opc-request-id: '
) )
await expect( await expect(
downloadGraalVMEELegacy('invalid', '1.0.0', '11') downloadGraalVMEELegacy('invalid', '1.0.0', '11')

View File

@@ -2,8 +2,12 @@ import * as path from 'path'
import * as graalvm from '../src/graalvm' import * as graalvm from '../src/graalvm'
import {expect, test} from '@jest/globals' import {expect, test} from '@jest/globals'
import {getTaggedRelease} from '../src/utils' import {getTaggedRelease} from '../src/utils'
import {findGraalVMVersion, findHighestJavaVersion} from '../src/graalvm' import {
import {GRAALVM_RELEASES_REPO} from '../src/constants' findGraalVMVersion,
findHighestJavaVersion,
findLatestEABuildDownloadUrl
} from '../src/graalvm'
import {GRAALVM_GH_USER, GRAALVM_RELEASES_REPO} from '../src/constants'
process.env['RUNNER_TOOL_CACHE'] = path.join(__dirname, 'TOOL_CACHE') process.env['RUNNER_TOOL_CACHE'] = path.join(__dirname, 'TOOL_CACHE')
process.env['RUNNER_TEMP'] = path.join(__dirname, 'TEMP') process.env['RUNNER_TEMP'] = path.join(__dirname, 'TEMP')
@@ -49,6 +53,7 @@ test('find version/javaVersion', async () => {
expect(error.message).toContain('Unable to find the latest Java version for') expect(error.message).toContain('Unable to find the latest Java version for')
const latestRelease = await getTaggedRelease( const latestRelease = await getTaggedRelease(
GRAALVM_GH_USER,
GRAALVM_RELEASES_REPO, GRAALVM_RELEASES_REPO,
'vm-22.3.1' 'vm-22.3.1'
) )
@@ -79,3 +84,21 @@ test('find version/javaVersion', async () => {
} }
expect(error.message).toContain('Could not find highest Java version.') expect(error.message).toContain('Could not find highest Java version.')
}) })
test('find version/javaVersion', async () => {
let url22EA = await findLatestEABuildDownloadUrl('22-ea')
expect(url22EA).not.toBe('')
let urlLatestEA = await findLatestEABuildDownloadUrl('latest-ea')
expect(urlLatestEA).not.toBe('')
let error = new Error('unexpected')
try {
await findLatestEABuildDownloadUrl('8-ea')
} catch (err) {
if (!(err instanceof Error)) {
fail(`Unexpected non-Error: ${err}`)
}
error = err
}
expect(error.message).toContain('Unable to resolve download URL for')
})

138
__tests__/liberica.test.ts Normal file
View File

@@ -0,0 +1,138 @@
import * as liberica from '../src/liberica'
import * as c from '../src/constants'
import * as path from 'path'
import * as semver from 'semver'
import {expect, test} from '@jest/globals'
process.env['RUNNER_TOOL_CACHE'] = path.join(__dirname, 'TOOL_CACHE')
process.env['RUNNER_TEMP'] = path.join(__dirname, 'TEMP')
test('find latest JDK version', async () => {
// Make sure the action can find the latest Java version for known major versions
await expectLatestToBe('11', atLeast('11.0.22+12'))
await expectLatestToBe('11.0.22', upToBuild('11.0.22+12'))
await expectLatestToBe('11.0.22+12', exactly('11.0.22+12'))
await expectLatestToBe('17', atLeast('17.0.10+13'))
await expectLatestToBe('17.0.10', upToBuild('17.0.10+13'))
await expectLatestToBe('17.0.10+13', exactly('17.0.10+13'))
await expectLatestToBe('21', atLeast('21.0.2+14'))
await expectLatestToBe('21.0.2', upToBuild('21.0.2+14'))
await expectLatestToBe('21.0.2+14', exactly('21.0.2+14'))
// Outdated major version
await expectLatestToFail('20')
// Outdated CPU versions
await expectLatestToFail('11.0.2') // should not resolve to 11.0.22
await expectLatestToFail('17.0.1') // should not resolve to 17.0.10
await expectLatestToFail('17.0.7+11')
await expectLatestToFail('21.0.0+8')
await expectLatestToFail('21.0.1')
// Incorrect build number
await expectLatestToFail('17.0.10+10')
}, 30000)
test('find asset URL', async () => {
await expectURL('11.0.22+12', '', 'bellsoft-liberica-vm-openjdk11.0.22')
await expectURL('17.0.10+13', 'jdk', 'bellsoft-liberica-vm-openjdk17.0.10')
if (!c.IS_LINUX) {
// This check can fail on Linux because there's no `jdk+fx` package for aarch64 and/or musl
await expectURL(
'21.0.2+14',
'jdk+fx',
'bellsoft-liberica-vm-full-openjdk21.0.2'
)
}
}, 10000)
type verifier = (
version: string,
major: number,
minor: number,
patch: number
) => void
function atLeast(expectedMinVersion: string): verifier {
const expectedMajor = semver.major(expectedMinVersion)
return function (
version: string,
major: number,
minor: number,
patch: number
) {
expect(major).toBe(expectedMajor)
if (semver.compareBuild(version, expectedMinVersion) < 0) {
throw new Error(`Version ${version} is older than ${expectedMinVersion}`)
}
}
}
function upToBuild(expectedMinVersion: string): verifier {
const expectedMinor = semver.minor(expectedMinVersion)
const expectedPatch = semver.patch(expectedMinVersion)
const atLeastVerifier = atLeast(expectedMinVersion)
return function (
version: string,
major: number,
minor: number,
patch: number
) {
atLeastVerifier(version, major, minor, patch)
expect(minor).toBe(expectedMinor)
expect(patch).toBe(expectedPatch)
}
}
function exactly(expectedVersion: string): verifier {
return function (
version: string,
major: number,
minor: number,
patch: number
) {
if (semver.compareBuild(version, expectedVersion) != 0) {
throw new Error(`Expected version ${expectedVersion} but got ${version}`)
}
}
}
async function expectLatestToBe(pattern: string, verify: verifier) {
const result = await liberica.findLatestLibericaJavaVersion(pattern)
expect(semver.valid(result)).toBeDefined()
const major = semver.major(result)
const minor = semver.minor(result)
const patch = semver.patch(result)
verify(result, major, minor, patch)
}
async function expectLatestToFail(pattern: string) {
try {
const result = await liberica.findLatestLibericaJavaVersion(pattern)
throw new Error(
`findLatest(${pattern}) should have failed but returned ${result}`
)
} catch (err) {
if (!(err instanceof Error)) {
throw new Error(`Unexpected non-Error: ${err}`)
}
expect(err.message).toContain(
`Unable to find the latest version for JDK${pattern}`
)
}
}
async function expectURL(
javaVersion: string,
javaPackage: string,
expectedPrefix: string
) {
const url = await liberica.findLibericaURL(javaVersion, javaPackage)
expect(url).toBeDefined()
const parts = url.split('/')
const file = parts[parts.length - 1]
expect(file.startsWith(expectedPrefix)).toBe(true)
}

36
__tests__/msvc.test.ts Normal file
View File

@@ -0,0 +1,36 @@
import * as path from 'path'
import {expect, test} from '@jest/globals'
import {needsWindowsEnvironmentSetup} from '../src/msvc'
import {VERSION_DEV, VERSION_LATEST} from '../src/constants'
process.env['RUNNER_TOOL_CACHE'] = path.join(__dirname, 'TOOL_CACHE')
process.env['RUNNER_TEMP'] = path.join(__dirname, 'TEMP')
test('decide whether Window env must be set up for GraalVM for JDK', async () => {
for (var javaVersion of [
'17',
'17.0.8',
'17.0',
'21',
'22',
'22-ea',
'23-ea',
VERSION_DEV
]) {
expect(needsWindowsEnvironmentSetup(javaVersion, '', true)).toBe(false)
}
})
test('decide whether Window env must be set up for legacy GraalVM', async () => {
for (var combination of [
['7', '22.3.0'],
['17', '22.3'],
['7', '22.3'],
['7', VERSION_DEV],
['17', VERSION_LATEST]
]) {
expect(
needsWindowsEnvironmentSetup(combination[0], combination[1], false)
).toBe(combination[1] !== VERSION_DEV)
}
})

34
__tests__/utils.test.ts Normal file
View File

@@ -0,0 +1,34 @@
import * as path from 'path'
import {expect, test} from '@jest/globals'
import {toSemVer} from '../src/utils'
test('convert version', async () => {
for (var inputAndExpectedOutput of [
['22', '22.0.0'],
['22.0', '22.0.0'],
['22.0.0', '22.0.0'],
['22.0.0.2', '22.0.0-2'],
['22-ea', '22.0.0-ea'],
['22.0-ea', '22.0.0-ea'],
['22.0.0-ea', '22.0.0-ea']
]) {
expect(toSemVer(inputAndExpectedOutput[0])).toBe(inputAndExpectedOutput[1])
}
})
test('convert invalid version', async () => {
for (var input of ['dev', 'abc', 'a.b.c']) {
let error = new Error('unexpected')
try {
toSemVer(input)
} catch (err) {
if (!(err instanceof Error)) {
fail(`Unexpected non-Error: ${err}`)
}
error = err
}
expect(error).not.toBeUndefined()
expect(error.message).toContain('Unable to convert')
}
})

View File

@@ -2,12 +2,16 @@ name: 'GitHub Action for GraalVM'
description: 'Set up a specific version of the GraalVM JDK and add the command-line tools to the PATH' description: 'Set up a specific version of the GraalVM JDK and add the command-line tools to the PATH'
author: 'GraalVM Community' author: 'GraalVM Community'
branding: branding:
icon: 'terminal' icon: 'terminal'
color: 'blue' color: 'blue'
inputs: inputs:
java-version: java-version:
required: true required: true
description: 'Java version. See examples of supported syntax in the README file.' description: 'Java version. See examples of supported syntax in the README file.'
java-package:
description: 'The package type (jdk or jdk+fx). Currently applies to Liberica only.'
required: false
default: 'jdk'
distribution: distribution:
description: 'GraalVM distribution. See the list of available distributions in the README file.' description: 'GraalVM distribution. See the list of available distributions in the README file.'
required: false required: false
@@ -43,6 +47,10 @@ inputs:
required: false required: false
description: 'Post a comment containing a Native Image build report on pull requests.' description: 'Post a comment containing a Native Image build report on pull requests.'
default: 'false' default: 'false'
native-image-pr-reports-update-existing:
required: false
description: 'Instead of posting another comment, update an existing PR comment with the latest Native Image build report.'
default: 'false'
version: version:
required: false required: false
description: 'GraalVM version (release, latest, dev).' description: 'GraalVM version (release, latest, dev).'

16726
dist/cleanup/index.js generated vendored

File diff suppressed because it is too large Load Diff

20988
dist/main/index.js generated vendored

File diff suppressed because one or more lines are too long

1998
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "setup-graalvm", "name": "setup-graalvm",
"version": "1.1.6", "version": "1.2.7",
"private": true, "private": true,
"description": "GitHub Action for GraalVM", "description": "GitHub Action for GraalVM",
"main": "lib/main.js", "main": "lib/main.js",
@@ -27,37 +27,38 @@
"author": "GraalVM Community", "author": "GraalVM Community",
"license": "UPL", "license": "UPL",
"dependencies": { "dependencies": {
"@actions/cache": "^3.2.3", "@actions/cache": "^4.0.0",
"@actions/core": "^1.10.1", "@actions/core": "^1.11.1",
"@actions/exec": "^1.1.1", "@actions/exec": "^1.1.1",
"@actions/github": "^6.0.0", "@actions/github": "^6.0.0",
"@actions/glob": "^0.4.0", "@actions/glob": "^0.5.0",
"@actions/http-client": "^2.2.0", "@actions/http-client": "^2.2.3",
"@actions/io": "^1.1.3", "@actions/io": "^1.1.3",
"@actions/tool-cache": "^2.0.1", "@actions/tool-cache": "^2.0.2",
"@octokit/core": "^5.1.0", "@octokit/core": "^5.2.0",
"@octokit/types": "^12.0.0", "@octokit/types": "^12.6.0",
"semver": "^7.5.4", "semver": "^7.6.3",
"uuid": "^9.0.1" "uuid": "^11.0.5"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.5.11", "@types/jest": "^29.5.14",
"@types/node": "^20.11.10", "@types/node": "^20.17.12",
"@types/semver": "^7.5.6", "@types/semver": "^7.5.8",
"@types/uuid": "^9.0.8", "@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^6.19.1", "@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^6.19.1", "@typescript-eslint/parser": "^7.2.0",
"@vercel/ncc": "^0.38.1", "@vercel/ncc": "^0.38.1",
"eslint": "^8.56.0", "eslint": "^8.57.0",
"eslint-plugin-github": "^4.10.1", "eslint-plugin-github": "^4.10.2",
"eslint-plugin-jest": "^27.6.3", "eslint-plugin-jest": "^27.9.0",
"eslint-plugin-jsonc": "^2.13.0", "eslint-plugin-jsonc": "^2.14.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^5.1.3", "eslint-plugin-prettier": "^5.1.3",
"jest": "^29.7.0", "jest": "^29.7.0",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"prettier": "^3.2.4", "prettier": "^3.2.5",
"prettier-eslint": "^16.3.0", "prettier-eslint": "^16.3.0",
"ts-jest": "^29.1.2", "ts-jest": "^29.2.5",
"typescript": "^5.3.3" "typescript": "^5.3.3"
} }
} }

View File

@@ -1,8 +1,11 @@
import * as otypes from '@octokit/types' import * as otypes from '@octokit/types'
export const ACTION_VERSION = '1.2.7'
export const INPUT_VERSION = 'version' export const INPUT_VERSION = 'version'
export const INPUT_GDS_TOKEN = 'gds-token' export const INPUT_GDS_TOKEN = 'gds-token'
export const INPUT_JAVA_VERSION = 'java-version' export const INPUT_JAVA_VERSION = 'java-version'
export const INPUT_JAVA_PACKAGE = 'java-package'
export const INPUT_DISTRIBUTION = 'distribution' export const INPUT_DISTRIBUTION = 'distribution'
export const INPUT_COMPONENTS = 'components' export const INPUT_COMPONENTS = 'components'
export const INPUT_GITHUB_TOKEN = 'github-token' export const INPUT_GITHUB_TOKEN = 'github-token'
@@ -15,9 +18,12 @@ export const IS_LINUX = process.platform === 'linux'
export const IS_MACOS = process.platform === 'darwin' export const IS_MACOS = process.platform === 'darwin'
export const IS_WINDOWS = process.platform === 'win32' export const IS_WINDOWS = process.platform === 'win32'
export const EXECUTABLE_SUFFIX = IS_WINDOWS ? '.exe' : ''
export const DISTRIBUTION_GRAALVM = 'graalvm' export const DISTRIBUTION_GRAALVM = 'graalvm'
export const DISTRIBUTION_GRAALVM_COMMUNITY = 'graalvm-community' export const DISTRIBUTION_GRAALVM_COMMUNITY = 'graalvm-community'
export const DISTRIBUTION_MANDREL = 'mandrel' export const DISTRIBUTION_MANDREL = 'mandrel'
export const DISTRIBUTION_LIBERICA = 'liberica'
export const VERSION_DEV = 'dev' export const VERSION_DEV = 'dev'
export const VERSION_LATEST = 'latest' export const VERSION_LATEST = 'latest'
@@ -40,6 +46,9 @@ export const GDS_GRAALVM_PRODUCT_ID = 'D53FAE8052773FFAE0530F15000AA6C6'
export const ENV_GITHUB_EVENT_NAME = 'GITHUB_EVENT_NAME' export const ENV_GITHUB_EVENT_NAME = 'GITHUB_EVENT_NAME'
export const EVENT_NAME_PULL_REQUEST = 'pull_request' export const EVENT_NAME_PULL_REQUEST = 'pull_request'
export const ERROR_REQUEST =
'Please file an issue at: https://github.com/graalvm/setup-graalvm/issues.'
export const ERROR_HINT = export const ERROR_HINT =
'If you think this is a mistake, please file an issue at: https://github.com/graalvm/setup-graalvm/issues.' 'If you think this is a mistake, please file an issue at: https://github.com/graalvm/setup-graalvm/issues.'
@@ -49,6 +58,25 @@ export type LatestReleaseResponse =
export type MatchingRefsResponse = export type MatchingRefsResponse =
otypes.Endpoints['GET /repos/{owner}/{repo}/git/matching-refs/{ref}']['response'] otypes.Endpoints['GET /repos/{owner}/{repo}/git/matching-refs/{ref}']['response']
export type ReleasesResponse =
otypes.Endpoints['GET /repos/{owner}/{repo}/releases']['response']
export type ContentsResponse =
otypes.Endpoints['GET /repos/{owner}/{repo}/contents/{path}']['response']
export interface OracleGraalVMEAFile {
filename: string
arch: 'aarch64' | 'x64'
platform: 'darwin' | 'linux' | 'windows'
}
export interface OracleGraalVMEAVersion {
version: string
latest?: boolean
download_base_url: string
files: OracleGraalVMEAFile[]
}
function determineJDKArchitecture(): string { function determineJDKArchitecture(): string {
switch (process.arch) { switch (process.arch) {
case 'x64': { case 'x64': {

View File

@@ -2,10 +2,16 @@ import * as c from '../constants'
import * as core from '@actions/core' import * as core from '@actions/core'
import * as fs from 'fs' import * as fs from 'fs'
import * as github from '@actions/github' import * as github from '@actions/github'
import * as semver from 'semver'
import {join} from 'path' import {join} from 'path'
import {tmpdir} from 'os' import {tmpdir} from 'os'
import {createPRComment, isPREvent, toSemVer} from '../utils' import {
import {gte} from 'semver' createPRComment,
findExistingPRCommentId,
isPREvent,
toSemVer,
updatePRComment
} from '../utils'
const BUILD_OUTPUT_JSON_PATH = join(tmpdir(), 'native-image-build-output.json') const BUILD_OUTPUT_JSON_PATH = join(tmpdir(), 'native-image-build-output.json')
const BYTES_TO_KiB = 1024 const BYTES_TO_KiB = 1024
@@ -15,11 +21,14 @@ const DOCS_BASE =
'https://github.com/oracle/graal/blob/master/docs/reference-manual/native-image/BuildOutput.md' 'https://github.com/oracle/graal/blob/master/docs/reference-manual/native-image/BuildOutput.md'
const INPUT_NI_JOB_REPORTS = 'native-image-job-reports' const INPUT_NI_JOB_REPORTS = 'native-image-job-reports'
const INPUT_NI_PR_REPORTS = 'native-image-pr-reports' const INPUT_NI_PR_REPORTS = 'native-image-pr-reports'
const INPUT_NI_PR_REPORTS_UPDATE = 'native-image-pr-reports-update-existing'
const NATIVE_IMAGE_CONFIG_FILE = join( const NATIVE_IMAGE_CONFIG_FILE = join(
tmpdir(), tmpdir(),
'native-image-options.properties' 'native-image-options.properties'
) )
const NATIVE_IMAGE_OPTIONS_ENV = 'NATIVE_IMAGE_OPTIONS'
const NATIVE_IMAGE_CONFIG_FILE_ENV = 'NATIVE_IMAGE_CONFIG_FILE' const NATIVE_IMAGE_CONFIG_FILE_ENV = 'NATIVE_IMAGE_CONFIG_FILE'
const PR_COMMENT_TITLE = '## GraalVM Native Image Build Report'
interface AnalysisResult { interface AnalysisResult {
total: number total: number
@@ -91,6 +100,7 @@ interface BuildOutput {
export async function setUpNativeImageBuildReports( export async function setUpNativeImageBuildReports(
isGraalVMforJDK17OrLater: boolean, isGraalVMforJDK17OrLater: boolean,
javaVersionOrDev: string,
graalVMVersion: string graalVMVersion: string
): Promise<void> { ): Promise<void> {
const isRequired = areJobReportsEnabled() || arePRReportsEnabled() const isRequired = areJobReportsEnabled() || arePRReportsEnabled()
@@ -102,7 +112,7 @@ export async function setUpNativeImageBuildReports(
graalVMVersion === c.VERSION_LATEST || graalVMVersion === c.VERSION_LATEST ||
graalVMVersion === c.VERSION_DEV || graalVMVersion === c.VERSION_DEV ||
(!graalVMVersion.startsWith(c.MANDREL_NAMESPACE) && (!graalVMVersion.startsWith(c.MANDREL_NAMESPACE) &&
gte(toSemVer(graalVMVersion), '22.2.0')) semver.gte(toSemVer(graalVMVersion), '22.2.0'))
if (!isSupported) { if (!isSupported) {
core.warning( core.warning(
`Build reports for PRs and job summaries are only available in GraalVM 22.2.0 or later. This build job uses GraalVM ${graalVMVersion}.` `Build reports for PRs and job summaries are only available in GraalVM 22.2.0 or later. This build job uses GraalVM ${graalVMVersion}.`
@@ -110,6 +120,7 @@ export async function setUpNativeImageBuildReports(
return return
} }
setNativeImageOption( setNativeImageOption(
javaVersionOrDev,
`-H:BuildOutputJSONFile=${BUILD_OUTPUT_JSON_PATH.replace(/\\/g, '\\\\')}` `-H:BuildOutputJSONFile=${BUILD_OUTPUT_JSON_PATH.replace(/\\/g, '\\\\')}`
) // Escape backslashes for Windows ) // Escape backslashes for Windows
} }
@@ -131,7 +142,17 @@ export async function generateReports(): Promise<void> {
core.summary.write() core.summary.write()
} }
if (arePRReportsEnabled()) { if (arePRReportsEnabled()) {
createPRComment(report) if (arePRReportsUpdateEnabled()) {
const commentId = await findExistingPRCommentId(PR_COMMENT_TITLE)
if (commentId) {
return updatePRComment(report, commentId)
}
}
return createPRComment(report)
} else if (arePRReportsUpdateEnabled()) {
throw new Error(
`'${INPUT_NI_PR_REPORTS_UPDATE}' option requires '${INPUT_NI_PR_REPORTS}' to be set 'true'`
)
} }
} }
} }
@@ -144,6 +165,38 @@ function arePRReportsEnabled(): boolean {
return isPREvent() && core.getInput(INPUT_NI_PR_REPORTS) === 'true' return isPREvent() && core.getInput(INPUT_NI_PR_REPORTS) === 'true'
} }
function arePRReportsUpdateEnabled(): boolean {
return isPREvent() && core.getInput(INPUT_NI_PR_REPORTS_UPDATE) === 'true'
}
function setNativeImageOption(
javaVersionOrDev: string,
optionValue: string
): void {
const coercedJavaVersionOrDev = semver.coerce(javaVersionOrDev)
if (
(coercedJavaVersionOrDev &&
semver.gte(coercedJavaVersionOrDev, '22.0.0')) ||
javaVersionOrDev === c.VERSION_DEV ||
javaVersionOrDev.endsWith('-ea')
) {
/* NATIVE_IMAGE_OPTIONS was introduced in GraalVM for JDK 22 (so were EA builds). */
let newOptionValue = optionValue
const existingOptions = process.env[NATIVE_IMAGE_OPTIONS_ENV]
if (existingOptions) {
newOptionValue = `${existingOptions} ${newOptionValue}`
}
core.exportVariable(NATIVE_IMAGE_OPTIONS_ENV, newOptionValue)
} else {
const optionsFile = getNativeImageOptionsFile()
if (fs.existsSync(optionsFile)) {
fs.appendFileSync(optionsFile, ` ${optionValue}`)
} else {
fs.writeFileSync(optionsFile, `NativeImageArgs = ${optionValue}`)
}
}
}
function getNativeImageOptionsFile(): string { function getNativeImageOptionsFile(): string {
let optionsFile = process.env[NATIVE_IMAGE_CONFIG_FILE_ENV] let optionsFile = process.env[NATIVE_IMAGE_CONFIG_FILE_ENV]
if (optionsFile === undefined) { if (optionsFile === undefined) {
@@ -153,15 +206,6 @@ function getNativeImageOptionsFile(): string {
return optionsFile return optionsFile
} }
function setNativeImageOption(value: string): void {
const optionsFile = getNativeImageOptionsFile()
if (fs.existsSync(optionsFile)) {
fs.appendFileSync(optionsFile, ` ${value}`)
} else {
fs.writeFileSync(optionsFile, `NativeImageArgs = ${value}`)
}
}
function createReport(data: BuildOutput): string { function createReport(data: BuildOutput): string {
const context = github.context const context = github.context
const info = data.general_info const info = data.general_info
@@ -238,7 +282,7 @@ function createReport(data: BuildOutput): string {
)} of total time)` )} of total time)`
} }
return `## GraalVM Native Image Build Report return `${PR_COMMENT_TITLE}
\`${info.name}\` generated${totalTime} as part of the '${ \`${info.name}\` generated${totalTime} as part of the '${
context.job context.job

View File

@@ -6,6 +6,7 @@ import * as io from '@actions/io'
import * as path from 'path' import * as path from 'path'
import * as stream from 'stream' import * as stream from 'stream'
import * as util from 'util' import * as util from 'util'
import * as semver from 'semver'
import {IncomingHttpHeaders, OutgoingHttpHeaders} from 'http' import {IncomingHttpHeaders, OutgoingHttpHeaders} from 'http'
import {RetryHelper} from '@actions/tool-cache/lib/retry-helper' import {RetryHelper} from '@actions/tool-cache/lib/retry-helper'
import {calculateSHA256} from './utils' import {calculateSHA256} from './utils'
@@ -26,13 +27,26 @@ interface GDSErrorResponse {
readonly message: string readonly message: string
} }
export async function downloadGraalVM(
gdsToken: string,
javaVersion: string
): Promise<string> {
const userAgent = `GraalVMGitHubAction/${c.ACTION_VERSION} (arch:${c.GRAALVM_ARCH}; os:${c.GRAALVM_PLATFORM}; java:${javaVersion})`
const baseArtifact = await fetchArtifact(
userAgent,
'isBase:True',
javaVersion
)
return downloadArtifact(gdsToken, userAgent, baseArtifact)
}
export async function downloadGraalVMEELegacy( export async function downloadGraalVMEELegacy(
gdsToken: string, gdsToken: string,
version: string, version: string,
javaVersion: string javaVersion: string
): Promise<string> { ): Promise<string> {
const userAgent = `GraalVMGitHubAction/1.1.6 (arch:${c.GRAALVM_ARCH}; os:${c.GRAALVM_PLATFORM}; java:${javaVersion})` const userAgent = `GraalVMGitHubAction/${c.ACTION_VERSION} (arch:${c.GRAALVM_ARCH}; os:${c.GRAALVM_PLATFORM}; java:${javaVersion})`
const baseArtifact = await fetchArtifact( const baseArtifact = await fetchArtifactEE(
userAgent, userAgent,
'isBase:True', 'isBase:True',
version, version,
@@ -42,6 +56,49 @@ export async function downloadGraalVMEELegacy(
} }
export async function fetchArtifact( export async function fetchArtifact(
userAgent: string,
metadata: string,
javaVersion: string
): Promise<GDSArtifact> {
const http = new httpClient.HttpClient(userAgent)
let filter
if (javaVersion.includes('.')) {
filter = `metadata=version:${javaVersion}`
} else {
filter = `sortBy=timeCreated&sortOrder=DESC&limit=1` // latest and only one item
}
let majorJavaVersion
if (semver.valid(javaVersion)) {
majorJavaVersion = semver.major(javaVersion)
} else {
majorJavaVersion = javaVersion
}
const catalogOS = c.IS_MACOS ? 'macos' : c.GRAALVM_PLATFORM
const requestUrl = `${c.GDS_BASE}/artifacts?productId=${c.GDS_GRAALVM_PRODUCT_ID}&displayName=Oracle%20GraalVM&${filter}&metadata=java:jdk${majorJavaVersion}&metadata=os:${catalogOS}&metadata=arch:${c.GRAALVM_ARCH}&metadata=${metadata}&status=PUBLISHED&responseFields=id&responseFields=checksum`
core.debug(`Requesting ${requestUrl}`)
const response = await http.get(requestUrl, {accept: 'application/json'})
if (response.message.statusCode !== 200) {
throw new Error(
`Unable to find GraalVM for JDK ${javaVersion}. Are you sure java-version: '${javaVersion}' is correct?`
)
}
const artifactResponse = JSON.parse(
await response.readBody()
) as GDSArtifactsResponse
if (artifactResponse.items.length !== 1) {
throw new Error(
artifactResponse.items.length > 1
? `Found more than one GDS artifact. ${c.ERROR_HINT}`
: `Unable to find GDS artifact. Are you sure java-version: '${javaVersion}' is correct?`
)
}
return artifactResponse.items[0]
}
export async function fetchArtifactEE(
userAgent: string, userAgent: string,
metadata: string, metadata: string,
version: string, version: string,

View File

@@ -1,18 +1,22 @@
import * as c from './constants' import * as c from './constants'
import * as core from '@actions/core'
import * as semver from 'semver' import * as semver from 'semver'
import { import {
downloadAndExtractJDK, downloadAndExtractJDK,
downloadExtractAndCacheJDK, downloadExtractAndCacheJDK,
getContents,
getLatestRelease, getLatestRelease,
getMatchingTags, getMatchingTags,
getTaggedRelease getTaggedRelease
} from './utils' } from './utils'
import {downloadGraalVMEELegacy} from './gds' import {downloadGraalVM, downloadGraalVMEELegacy} from './gds'
import {downloadTool} from '@actions/tool-cache' import {downloadTool} from '@actions/tool-cache'
import {basename} from 'path' import {basename} from 'path'
const GRAALVM_DL_BASE = 'https://download.oracle.com/graalvm' const GRAALVM_DL_BASE = 'https://download.oracle.com/graalvm'
const GRAALVM_CE_DL_BASE = `https://github.com/graalvm/${c.GRAALVM_RELEASES_REPO}/releases/download` const GRAALVM_CE_DL_BASE = `https://github.com/graalvm/${c.GRAALVM_RELEASES_REPO}/releases/download`
const ORACLE_GRAALVM_REPO_EA_BUILDS = 'oracle-graalvm-ea-builds'
const ORACLE_GRAALVM_REPO_EA_BUILDS_LATEST_SYMBOL = 'latest-ea'
const GRAALVM_REPO_DEV_BUILDS = 'graalvm-ce-dev-builds' const GRAALVM_REPO_DEV_BUILDS = 'graalvm-ce-dev-builds'
const GRAALVM_JDK_TAG_PREFIX = 'jdk-' const GRAALVM_JDK_TAG_PREFIX = 'jdk-'
const GRAALVM_TAG_PREFIX = 'vm-' const GRAALVM_TAG_PREFIX = 'vm-'
@@ -20,21 +24,45 @@ const GRAALVM_TAG_PREFIX = 'vm-'
// Support for GraalVM for JDK 17 and later // Support for GraalVM for JDK 17 and later
export async function setUpGraalVMJDK( export async function setUpGraalVMJDK(
javaVersionOrDev: string javaVersionOrDev: string,
gdsToken: string
): Promise<string> { ): Promise<string> {
if (javaVersionOrDev === c.VERSION_DEV) { if (javaVersionOrDev === c.VERSION_DEV) {
return setUpGraalVMJDKDevBuild() return setUpGraalVMJDKDevBuild()
} }
const javaVersion = javaVersionOrDev const isTokenProvided = gdsToken.length > 0
let toolName = determineToolName(javaVersion, false) let javaVersion = javaVersionOrDev
const toolName = determineToolName(javaVersion, false)
if (javaVersionOrDev === '17' && !isTokenProvided) {
core.warning(
'This build uses the last update of Oracle GraalVM for JDK 17 under the GFTC. More details: https://github.com/marketplace/actions/github-action-for-graalvm#notes-on-oracle-graalvm-for-jdk-17'
)
return setUpGraalVMJDK('17.0.12', gdsToken)
}
if (isTokenProvided) {
// Download from GDS
const downloader = async () => downloadGraalVM(gdsToken, javaVersion)
return downloadExtractAndCacheJDK(downloader, toolName, javaVersion)
}
// Download from oracle.com
let downloadName = toolName
let downloadUrl: string let downloadUrl: string
if (javaVersion.includes('.')) { if (javaVersion.endsWith('-ea')) {
downloadUrl = await findLatestEABuildDownloadUrl(javaVersion)
const filename = basename(downloadUrl)
const resolvedVersion = semver.valid(semver.coerce(filename))
if (!resolvedVersion) {
throw new Error(
`Unable to determine resolved version based on '${filename}'. ${c.ERROR_REQUEST}`
)
}
javaVersion = resolvedVersion
} else if (javaVersion.includes('.')) {
if (semver.valid(javaVersion)) { if (semver.valid(javaVersion)) {
const majorJavaVersion = semver.major(javaVersion) const majorJavaVersion = semver.major(javaVersion)
const minorJavaVersion = semver.minor(javaVersion) const minorJavaVersion = semver.minor(javaVersion)
const patchJavaVersion = semver.patch(javaVersion) const patchJavaVersion = semver.patch(javaVersion)
const isGARelease = minorJavaVersion === 0 && patchJavaVersion === 0 const isGARelease = minorJavaVersion === 0 && patchJavaVersion === 0
let downloadName = toolName
if (isGARelease) { if (isGARelease) {
// For GA versions of JDKs, /archive/ does not use minor and patch version (see https://www.oracle.com/java/technologies/jdk-script-friendly-urls/) // For GA versions of JDKs, /archive/ does not use minor and patch version (see https://www.oracle.com/java/technologies/jdk-script-friendly-urls/)
downloadName = determineToolName(majorJavaVersion.toString(), false) downloadName = determineToolName(majorJavaVersion.toString(), false)
@@ -46,12 +74,60 @@ export async function setUpGraalVMJDK(
) )
} }
} else { } else {
downloadUrl = `${GRAALVM_DL_BASE}/${javaVersion}/latest/${toolName}${c.GRAALVM_FILE_EXTENSION}` downloadUrl = `${GRAALVM_DL_BASE}/${javaVersion}/latest/${downloadName}${c.GRAALVM_FILE_EXTENSION}`
} }
const downloader = async () => downloadGraalVMJDK(downloadUrl, javaVersion) const downloader = async () => downloadGraalVMJDK(downloadUrl, javaVersion)
return downloadExtractAndCacheJDK(downloader, toolName, javaVersion) return downloadExtractAndCacheJDK(downloader, toolName, javaVersion)
} }
export async function findLatestEABuildDownloadUrl(
javaEaVersion: string
): Promise<string> {
const filePath = `versions/${javaEaVersion}.json`
let response
try {
response = await getContents(ORACLE_GRAALVM_REPO_EA_BUILDS, filePath)
} catch (error) {
throw new Error(
`Unable to resolve download URL for '${javaEaVersion}'. Please make sure the java-version is set correctly. ${c.ERROR_HINT}`
)
}
if (
Array.isArray(response) ||
response.type !== 'file' ||
!response.content
) {
throw new Error(
`Unexpected response when resolving download URL for '${javaEaVersion}'. ${c.ERROR_REQUEST}`
)
}
const versionData = JSON.parse(
Buffer.from(response.content, 'base64').toString('utf-8')
)
let latestVersion
if (javaEaVersion === ORACLE_GRAALVM_REPO_EA_BUILDS_LATEST_SYMBOL) {
latestVersion = versionData as c.OracleGraalVMEAVersion
} else {
latestVersion = (versionData as c.OracleGraalVMEAVersion[]).find(
v => v.latest
)
if (!latestVersion) {
throw new Error(
`Unable to find latest version for '${javaEaVersion}'. ${c.ERROR_REQUEST}`
)
}
}
const file = latestVersion.files.find(
f => f.arch === c.JDK_ARCH && f.platform === c.GRAALVM_PLATFORM
)
if (!file || !file.filename.startsWith('graalvm-jdk-')) {
throw new Error(
`Unable to find file metadata for '${javaEaVersion}'. ${c.ERROR_REQUEST}`
)
}
return `${latestVersion.download_base_url}${file.filename}`
}
export async function setUpGraalVMJDKCE( export async function setUpGraalVMJDKCE(
javaVersionOrDev: string javaVersionOrDev: string
): Promise<string> { ): Promise<string> {
@@ -77,6 +153,8 @@ export async function findLatestGraalVMJDKCEJavaVersion(
majorJavaVersion: string majorJavaVersion: string
): Promise<string> { ): Promise<string> {
const matchingRefs = await getMatchingTags( const matchingRefs = await getMatchingTags(
c.GRAALVM_GH_USER,
c.GRAALVM_RELEASES_REPO,
`${GRAALVM_JDK_TAG_PREFIX}${majorJavaVersion}` `${GRAALVM_JDK_TAG_PREFIX}${majorJavaVersion}`
) )
const lowestNonExistingVersion = '0.0.1' const lowestNonExistingVersion = '0.0.1'
@@ -183,6 +261,7 @@ export async function setUpGraalVMLatest_22_X(
return setUpGraalVMRelease(gdsToken, lockedVersion, javaVersion) return setUpGraalVMRelease(gdsToken, lockedVersion, javaVersion)
} }
const latestRelease = await getTaggedRelease( const latestRelease = await getTaggedRelease(
c.GRAALVM_GH_USER,
c.GRAALVM_RELEASES_REPO, c.GRAALVM_RELEASES_REPO,
GRAALVM_TAG_PREFIX + lockedVersion GRAALVM_TAG_PREFIX + lockedVersion
) )

119
src/liberica.ts Normal file
View File

@@ -0,0 +1,119 @@
import * as c from './constants'
import * as semver from 'semver'
import {
downloadExtractAndCacheJDK,
getTaggedRelease,
getMatchingTags
} from './utils'
import {downloadTool} from '@actions/tool-cache'
import {spawnSync} from 'child_process'
const LIBERICA_GH_USER = 'bell-sw'
const LIBERICA_RELEASES_REPO = 'LibericaNIK'
const LIBERICA_JDK_TAG_PREFIX = 'jdk-'
const LIBERICA_VM_PREFIX = 'bellsoft-liberica-vm-'
export async function setUpLiberica(
javaVersion: string,
javaPackage: string
): Promise<string> {
const resolvedJavaVersion = await findLatestLibericaJavaVersion(javaVersion)
const downloadUrl = await findLibericaURL(resolvedJavaVersion, javaPackage)
const toolName = determineToolName(javaVersion, javaPackage)
return downloadExtractAndCacheJDK(
async () => downloadTool(downloadUrl),
toolName,
javaVersion
)
}
export async function findLatestLibericaJavaVersion(
javaVersion: string
): Promise<string> {
const matchingRefs = await getMatchingTags(
LIBERICA_GH_USER,
LIBERICA_RELEASES_REPO,
`${LIBERICA_JDK_TAG_PREFIX}${javaVersion}`
)
const noMatch = '0.0.1'
let bestMatch = noMatch
const prefixLength = `refs/tags/${LIBERICA_JDK_TAG_PREFIX}`.length
const patternLength = javaVersion.length
for (const matchingRef of matchingRefs) {
const version = matchingRef.ref.substring(prefixLength)
if (
semver.valid(version) &&
// pattern '17.0.1' should match '17.0.1+12' but not '17.0.10'
(version.length <= patternLength ||
!isDigit(version.charAt(patternLength))) &&
semver.compareBuild(version, bestMatch) == 1
) {
bestMatch = version
}
}
if (bestMatch === noMatch) {
throw new Error(
`Unable to find the latest version for JDK${javaVersion}. Please make sure the java-version is set correctly. ${c.ERROR_HINT}`
)
}
return bestMatch
}
export async function findLibericaURL(
javaVersion: string,
javaPackage: string
): Promise<string> {
const release = await getTaggedRelease(
LIBERICA_GH_USER,
LIBERICA_RELEASES_REPO,
LIBERICA_JDK_TAG_PREFIX + javaVersion
)
const platform = determinePlatformPart()
const assetPrefix = `${LIBERICA_VM_PREFIX}${determineVariantPart(
javaPackage
)}openjdk${javaVersion}`
const assetSuffix = `-${platform}${c.GRAALVM_FILE_EXTENSION}`
for (const asset of release.assets) {
if (
asset.name.startsWith(assetPrefix) &&
asset.name.endsWith(assetSuffix)
) {
return asset.browser_download_url
}
}
throw new Error(
`Unable to find asset for java-version: ${javaVersion}, java-package: ${javaPackage}, platform: ${platform}. ${c.ERROR_REQUEST}`
)
}
function determineToolName(javaVersion: string, javaPackage: string) {
const variant = determineVariantPart(javaPackage)
const platform = determinePlatformPart()
return `${LIBERICA_VM_PREFIX}${variant}${platform}`
}
function determineVariantPart(javaPackage: string) {
return javaPackage !== null && javaPackage.includes('+fx') ? 'full-' : ''
}
function determinePlatformPart() {
if (isMuslBasedLinux()) {
return `linux-${c.JDK_ARCH}-musl`
} else {
return `${c.JDK_PLATFORM}-${c.GRAALVM_ARCH}`
}
}
function isMuslBasedLinux() {
if (c.IS_LINUX) {
const output = spawnSync('ldd', ['--version']).stderr.toString('utf8')
if (output.includes('musl')) {
return true
}
}
return false
}
function isDigit(c: string) {
return c.charAt(0) >= '0' && c.charAt(0) <= '9'
}

View File

@@ -3,19 +3,22 @@ import * as core from '@actions/core'
import * as graalvm from './graalvm' import * as graalvm from './graalvm'
import * as semver from 'semver' import * as semver from 'semver'
import {isFeatureAvailable as isCacheAvailable} from '@actions/cache' import {isFeatureAvailable as isCacheAvailable} from '@actions/cache'
import {join} from 'path' import {basename, join} from 'path'
import {restore} from './features/cache' import {restore} from './features/cache'
import {setUpDependencies} from './dependencies' import {setUpDependencies} from './dependencies'
import {setUpGUComponents} from './gu' import {setUpGUComponents} from './gu'
import {setUpMandrel} from './mandrel' import {setUpMandrel} from './mandrel'
import {setUpLiberica} from './liberica'
import {checkForUpdates} from './features/check-for-updates' import {checkForUpdates} from './features/check-for-updates'
import {setUpNativeImageMusl} from './features/musl' import {setUpNativeImageMusl} from './features/musl'
import {setUpWindowsEnvironment} from './msvc' import {setUpWindowsEnvironment} from './msvc'
import {setUpNativeImageBuildReports} from './features/reports' import {setUpNativeImageBuildReports} from './features/reports'
import {exec} from '@actions/exec'
async function run(): Promise<void> { async function run(): Promise<void> {
try { try {
const javaVersion = core.getInput(c.INPUT_JAVA_VERSION, {required: true}) const javaVersion = core.getInput(c.INPUT_JAVA_VERSION, {required: true})
const javaPackage = core.getInput(c.INPUT_JAVA_PACKAGE)
const distribution = core.getInput(c.INPUT_DISTRIBUTION) const distribution = core.getInput(c.INPUT_DISTRIBUTION)
const graalVMVersion = core.getInput(c.INPUT_VERSION) const graalVMVersion = core.getInput(c.INPUT_VERSION)
const gdsToken = core.getInput(c.INPUT_GDS_TOKEN) const gdsToken = core.getInput(c.INPUT_GDS_TOKEN)
@@ -29,9 +32,15 @@ async function run(): Promise<void> {
const enableCheckForUpdates = const enableCheckForUpdates =
core.getInput(c.INPUT_CHECK_FOR_UPDATES) === 'true' core.getInput(c.INPUT_CHECK_FOR_UPDATES) === 'true'
const enableNativeImageMusl = core.getInput(c.INPUT_NI_MUSL) === 'true' const enableNativeImageMusl = core.getInput(c.INPUT_NI_MUSL) === 'true'
const isGraalVMforJDK17OrLater =
distribution.length > 0 || graalVMVersion.length == 0
if (c.IS_WINDOWS) { if (c.IS_WINDOWS) {
setUpWindowsEnvironment(graalVMVersion) setUpWindowsEnvironment(
javaVersion,
graalVMVersion,
isGraalVMforJDK17OrLater
)
} }
await setUpDependencies(components) await setUpDependencies(components)
if (enableNativeImageMusl) { if (enableNativeImageMusl) {
@@ -39,8 +48,6 @@ async function run(): Promise<void> {
} }
// Download GraalVM JDK // Download GraalVM JDK
const isGraalVMforJDK17OrLater =
distribution.length > 0 || graalVMVersion.length == 0
let graalVMHome let graalVMHome
if (isGraalVMforJDK17OrLater) { if (isGraalVMforJDK17OrLater) {
if ( if (
@@ -52,7 +59,7 @@ async function run(): Promise<void> {
} }
switch (distribution) { switch (distribution) {
case c.DISTRIBUTION_GRAALVM: case c.DISTRIBUTION_GRAALVM:
graalVMHome = await graalvm.setUpGraalVMJDK(javaVersion) graalVMHome = await graalvm.setUpGraalVMJDK(javaVersion, gdsToken)
break break
case c.DISTRIBUTION_GRAALVM_COMMUNITY: case c.DISTRIBUTION_GRAALVM_COMMUNITY:
graalVMHome = await graalvm.setUpGraalVMJDKCE(javaVersion) graalVMHome = await graalvm.setUpGraalVMJDKCE(javaVersion)
@@ -60,6 +67,9 @@ async function run(): Promise<void> {
case c.DISTRIBUTION_MANDREL: case c.DISTRIBUTION_MANDREL:
graalVMHome = await setUpMandrel(graalVMVersion, javaVersion) graalVMHome = await setUpMandrel(graalVMVersion, javaVersion)
break break
case c.DISTRIBUTION_LIBERICA:
graalVMHome = await setUpLiberica(javaVersion, javaPackage)
break
case '': case '':
if (javaVersion === c.VERSION_DEV) { if (javaVersion === c.VERSION_DEV) {
core.info( core.info(
@@ -70,7 +80,7 @@ async function run(): Promise<void> {
core.info( core.info(
`This build is using the new Oracle GraalVM. To select a specific distribution, use the 'distribution' option (see https://github.com/graalvm/setup-graalvm/tree/main#options).` `This build is using the new Oracle GraalVM. To select a specific distribution, use the 'distribution' option (see https://github.com/graalvm/setup-graalvm/tree/main#options).`
) )
graalVMHome = await graalvm.setUpGraalVMJDK(javaVersion) graalVMHome = await graalvm.setUpGraalVMJDK(javaVersion, gdsToken)
} }
break break
default: default:
@@ -88,7 +98,7 @@ async function run(): Promise<void> {
core.info( core.info(
`This build is using the new Oracle GraalVM. To select a specific distribution, use the 'distribution' option (see https://github.com/graalvm/setup-graalvm/tree/main#options).` `This build is using the new Oracle GraalVM. To select a specific distribution, use the 'distribution' option (see https://github.com/graalvm/setup-graalvm/tree/main#options).`
) )
graalVMHome = await graalvm.setUpGraalVMJDK(javaVersion) graalVMHome = await graalvm.setUpGraalVMJDK(javaVersion, gdsToken)
} else { } else {
graalVMHome = await graalvm.setUpGraalVMLatest_22_X( graalVMHome = await graalvm.setUpGraalVMLatest_22_X(
gdsToken, gdsToken,
@@ -109,7 +119,7 @@ async function run(): Promise<void> {
core.warning( core.warning(
`GraalVM dev builds are only available for JDK 21. This build is now using a stable release of GraalVM for JDK ${javaVersion}.` `GraalVM dev builds are only available for JDK 21. This build is now using a stable release of GraalVM for JDK ${javaVersion}.`
) )
graalVMHome = await graalvm.setUpGraalVMJDK(javaVersion) graalVMHome = await graalvm.setUpGraalVMJDK(javaVersion, gdsToken)
} else { } else {
graalVMHome = await graalvm.setUpGraalVMJDKDevBuild() graalVMHome = await graalvm.setUpGraalVMJDKDevBuild()
} }
@@ -150,7 +160,17 @@ async function run(): Promise<void> {
if (cache && isCacheAvailable()) { if (cache && isCacheAvailable()) {
await restore(cache) await restore(cache)
} }
setUpNativeImageBuildReports(isGraalVMforJDK17OrLater, graalVMVersion) setUpNativeImageBuildReports(
isGraalVMforJDK17OrLater,
javaVersion,
graalVMVersion
)
core.startGroup(`Successfully set up '${basename(graalVMHome)}'`)
await exec(join(graalVMHome, 'bin', `java${c.EXECUTABLE_SUFFIX}`), [
javaVersion.startsWith('8') ? '-version' : '--version'
])
core.endGroup()
} catch (error) { } catch (error) {
if (error instanceof Error) core.setFailed(error.message) if (error instanceof Error) core.setFailed(error.message)
} }

View File

@@ -1,4 +1,5 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import * as semver from 'semver'
import {execSync} from 'child_process' import {execSync} from 'child_process'
import {existsSync} from 'fs' import {existsSync} from 'fs'
import {VERSION_DEV} from './constants' import {VERSION_DEV} from './constants'
@@ -27,9 +28,32 @@ function findVcvarsallPath(): string {
throw new Error('Failed to find vcvarsall.bat') throw new Error('Failed to find vcvarsall.bat')
} }
export function setUpWindowsEnvironment(graalVMVersion: string): void { export function needsWindowsEnvironmentSetup(
if (graalVMVersion === VERSION_DEV) { javaVersion: string,
return // no longer required in dev builds graalVMVersion: string,
isGraalVMforJDK17OrLater: boolean
): boolean {
if (javaVersion === VERSION_DEV || graalVMVersion === VERSION_DEV) {
return false // no longer required in dev builds
} else if (isGraalVMforJDK17OrLater) {
return false // no longer required in GraalVM for JDK 17 and later.
}
return true
}
export function setUpWindowsEnvironment(
javaVersion: string,
graalVMVersion: string,
isGraalVMforJDK17OrLater: boolean
): void {
if (
!needsWindowsEnvironmentSetup(
javaVersion,
graalVMVersion,
isGraalVMforJDK17OrLater
)
) {
return
} }
core.startGroup('Updating Windows environment...') core.startGroup('Updating Windows environment...')

View File

@@ -2,6 +2,7 @@ import * as c from './constants'
import * as core from '@actions/core' import * as core from '@actions/core'
import * as github from '@actions/github' import * as github from '@actions/github'
import * as httpClient from '@actions/http-client' import * as httpClient from '@actions/http-client'
import * as semver from 'semver'
import * as tc from '@actions/tool-cache' import * as tc from '@actions/tool-cache'
import {ExecOptions, exec as e} from '@actions/exec' import {ExecOptions, exec as e} from '@actions/exec'
import {readFileSync, readdirSync} from 'fs' import {readFileSync, readdirSync} from 'fs'
@@ -47,7 +48,24 @@ export async function getLatestRelease(
).data ).data
} }
export async function getContents(
repo: string,
path: string
): Promise<c.ContentsResponse['data']> {
const githubToken = getGitHubToken()
const options = githubToken.length > 0 ? {auth: githubToken} : {}
const octokit = new GitHubDotCom(options)
return (
await octokit.request('GET /repos/{owner}/{repo}/contents/{path}', {
owner: c.GRAALVM_GH_USER,
repo,
path
})
).data
}
export async function getTaggedRelease( export async function getTaggedRelease(
owner: string,
repo: string, repo: string,
tag: string tag: string
): Promise<c.LatestReleaseResponse['data']> { ): Promise<c.LatestReleaseResponse['data']> {
@@ -56,7 +74,7 @@ export async function getTaggedRelease(
const octokit = new GitHubDotCom(options) const octokit = new GitHubDotCom(options)
return ( return (
await octokit.request('GET /repos/{owner}/{repo}/releases/tags/{tag}', { await octokit.request('GET /repos/{owner}/{repo}/releases/tags/{tag}', {
owner: c.GRAALVM_GH_USER, owner,
repo, repo,
tag tag
}) })
@@ -64,6 +82,8 @@ export async function getTaggedRelease(
} }
export async function getMatchingTags( export async function getMatchingTags(
owner: string,
repo: string,
tagPrefix: string tagPrefix: string
): Promise<c.MatchingRefsResponse['data']> { ): Promise<c.MatchingRefsResponse['data']> {
const githubToken = getGitHubToken() const githubToken = getGitHubToken()
@@ -73,8 +93,8 @@ export async function getMatchingTags(
await octokit.request( await octokit.request(
'GET /repos/{owner}/{repo}/git/matching-refs/tags/{tagPrefix}', 'GET /repos/{owner}/{repo}/git/matching-refs/tags/{tagPrefix}',
{ {
owner: c.GRAALVM_GH_USER, owner,
repo: c.GRAALVM_RELEASES_REPO, repo,
tagPrefix tagPrefix
} }
) )
@@ -135,17 +155,25 @@ function findJavaHomeInSubfolder(searchPath: string): string {
} }
} }
/**
* This helper turns GraalVM version numbers (e.g., `22.0.0.2`) into valid
* semver.org versions (e.g., `22.0.0-2`), which is needed because
* @actions/tool-cache uses `semver` to validate versions.
*/
export function toSemVer(version: string): string { export function toSemVer(version: string): string {
const parts = version.split('.') const parts = version.split('.')
const major = parts[0] if (parts.length === 4) {
const minor = parts.length > 1 ? parts[1] : '0' /**
const patch = parts.length > 2 ? parts.slice(2).join('-') : '0' * Turn legacy GraalVM version numbers (e.g., `22.0.0.2`) into valid
return `${major}.${minor}.${patch}` * semver.org versions (e.g., `22.0.0-2`).
*/
return `${parts[0]}.${parts[1]}.${parts.slice(2).join('-')}`
}
const versionParts = version.split('-', 2)
const suffix = versionParts.length === 2 ? '-' + versionParts[1] : ''
const validVersion = semver.valid(semver.coerce(versionParts[0]) + suffix)
if (!validVersion) {
throw new Error(
`Unable to convert '${version}' to semantic version. ${c.ERROR_HINT}`
)
}
return validVersion
} }
export function isPREvent(): boolean { export function isPREvent(): boolean {
@@ -156,6 +184,52 @@ function getGitHubToken(): string {
return core.getInput(c.INPUT_GITHUB_TOKEN) return core.getInput(c.INPUT_GITHUB_TOKEN)
} }
export async function findExistingPRCommentId(
bodyStartsWith: string
): Promise<number | undefined> {
if (!isPREvent()) {
throw new Error('Not a PR event.')
}
const context = github.context
const octokit = github.getOctokit(getGitHubToken())
try {
const comments = await octokit.paginate(octokit.rest.issues.listComments, {
...context.repo,
issue_number: context.payload.pull_request?.number as number
})
const matchingComment = comments.reverse().find(comment => {
return comment.body && comment.body.startsWith(bodyStartsWith)
})
return matchingComment ? matchingComment.id : undefined
} catch (err) {
core.error(
`Failed to list pull request comments. Please make sure this job has 'write' permissions for the 'pull-requests' scope (see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions)? Internal error: ${err}`
)
}
}
export async function updatePRComment(
content: string,
commentId: number
): Promise<void> {
if (!isPREvent()) {
throw new Error('Not a PR event.')
}
try {
await github.getOctokit(getGitHubToken()).rest.issues.updateComment({
...github.context.repo,
comment_id: commentId,
body: content
})
} catch (err) {
core.error(
`Failed to update pull request comment. Please make sure this job has 'write' permissions for the 'pull-requests' scope (see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions)? Internal error: ${err}`
)
}
}
export async function createPRComment(content: string): Promise<void> { export async function createPRComment(content: string): Promise<void> {
if (!isPREvent()) { if (!isPREvent()) {
throw new Error('Not a PR event.') throw new Error('Not a PR event.')