mirror of
https://github.com/graalvm/setup-graalvm.git
synced 2025-07-06 01:33:13 +08:00
Compare commits
79 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7de2d094ec | ||
|
d7feb9d031 | ||
|
63e0340562 | ||
|
8ea6c1f538 | ||
|
01ed3ea8d4 | ||
|
e46a5025da | ||
|
4daf9d25d0 | ||
|
6249097607 | ||
|
99513f43da | ||
|
70cc29044a | ||
|
547a84f872 | ||
|
21af6a0ef7 | ||
|
1086d2a1b4 | ||
|
7f61f4917e | ||
|
f3662e4b72 | ||
|
b19c2851fd | ||
|
0027121302 | ||
|
0568ccefb6 | ||
|
a4c8415508 | ||
|
aef1f09405 | ||
|
26a86e7135 | ||
|
01ed653ac8 | ||
|
3ca6fc3a8a | ||
|
271a696e78 | ||
|
2063b36b79 | ||
|
44d0c2f19b | ||
|
26e3dc36fc | ||
|
e6854f2a7c | ||
|
a1c06b5535 | ||
|
e4bdac3847 | ||
|
00f0f13934 | ||
|
63ca6fe724 | ||
|
5b85983c0a | ||
|
f4c22e2c3f | ||
|
2ea5788b37 | ||
|
b5709ab80d | ||
|
6e1c9cebb5 | ||
|
601e3a4caa | ||
|
b0cb26a8da | ||
|
30b157ff45 | ||
|
0f761465f7 | ||
|
f07b5bfaef | ||
|
fcc01ed19b | ||
|
c65e623881 | ||
|
3040d71541 | ||
|
70a5974953 | ||
|
aa331906a0 | ||
|
dea0e3da95 | ||
|
300d65ee39 | ||
|
9d4a7232c4 | ||
|
9b77b7e1c6 | ||
|
93a3b57d30 | ||
|
ebd520e252 | ||
|
02f9160735 | ||
|
ef3ebf8051 | ||
|
ae07e6cc51 | ||
|
49622345c8 | ||
|
a0ea0f7a0a | ||
|
d0b11c9136 | ||
|
eb58450822 | ||
|
af56e29ad9 | ||
|
bc541ab008 | ||
|
d028da6ae3 | ||
|
613c01f0e8 | ||
|
71b1e905e2 | ||
|
7b74bd8bd8 | ||
|
c09e29bb11 | ||
|
04d7e4f4bb | ||
|
64b43dc209 | ||
|
4a200f28cd | ||
|
a8c0509ec2 | ||
|
557ffcf459 | ||
|
f7c3ab9a9a | ||
|
dee12811d5 | ||
|
9dd2b41757 | ||
|
3aaf71e276 | ||
|
17d757cc41 | ||
|
24013ae277 | ||
|
caa712a441 |
@ -1,4 +0,0 @@
|
|||||||
dist/
|
|
||||||
lib/
|
|
||||||
node_modules/
|
|
||||||
jest.config.js
|
|
@ -1,55 +0,0 @@
|
|||||||
{
|
|
||||||
"plugins": ["jest", "@typescript-eslint"],
|
|
||||||
"extends": ["plugin:github/recommended"],
|
|
||||||
"parser": "@typescript-eslint/parser",
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 9,
|
|
||||||
"sourceType": "module",
|
|
||||||
"project": "./tsconfig.json"
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"i18n-text/no-en": "off",
|
|
||||||
"eslint-comments/no-use": "off",
|
|
||||||
"import/no-namespace": "off",
|
|
||||||
"no-unused-vars": "off",
|
|
||||||
"@typescript-eslint/no-unused-vars": "error",
|
|
||||||
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
|
|
||||||
"@typescript-eslint/no-require-imports": "error",
|
|
||||||
"@typescript-eslint/array-type": "error",
|
|
||||||
"@typescript-eslint/await-thenable": "error",
|
|
||||||
"@typescript-eslint/ban-ts-comment": "error",
|
|
||||||
"camelcase": "off",
|
|
||||||
"@typescript-eslint/consistent-type-assertions": "error",
|
|
||||||
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
|
|
||||||
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
|
||||||
"@typescript-eslint/no-array-constructor": "error",
|
|
||||||
"@typescript-eslint/no-empty-interface": "error",
|
|
||||||
"@typescript-eslint/no-explicit-any": "error",
|
|
||||||
"@typescript-eslint/no-extraneous-class": "error",
|
|
||||||
"@typescript-eslint/no-for-in-array": "error",
|
|
||||||
"@typescript-eslint/no-inferrable-types": "error",
|
|
||||||
"@typescript-eslint/no-misused-new": "error",
|
|
||||||
"@typescript-eslint/no-namespace": "error",
|
|
||||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
|
||||||
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
|
||||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
|
||||||
"@typescript-eslint/no-useless-constructor": "error",
|
|
||||||
"@typescript-eslint/no-var-requires": "error",
|
|
||||||
"@typescript-eslint/prefer-for-of": "warn",
|
|
||||||
"@typescript-eslint/prefer-function-type": "warn",
|
|
||||||
"@typescript-eslint/prefer-includes": "error",
|
|
||||||
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
|
||||||
"@typescript-eslint/promise-function-async": "error",
|
|
||||||
"@typescript-eslint/require-array-sort-compare": "error",
|
|
||||||
"@typescript-eslint/restrict-plus-operands": "error",
|
|
||||||
"semi": "off",
|
|
||||||
"@typescript-eslint/semi": ["error", "never"],
|
|
||||||
"@typescript-eslint/type-annotation-spacing": "error",
|
|
||||||
"@typescript-eslint/unbound-method": "error"
|
|
||||||
},
|
|
||||||
"env": {
|
|
||||||
"node": true,
|
|
||||||
"es6": true,
|
|
||||||
"jest/globals": true
|
|
||||||
}
|
|
||||||
}
|
|
30
.github/dependabot.yml
vendored
Normal file
30
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: github-actions
|
||||||
|
directory: /
|
||||||
|
schedule:
|
||||||
|
interval: monthly
|
||||||
|
groups:
|
||||||
|
actions-minor:
|
||||||
|
update-types:
|
||||||
|
- minor
|
||||||
|
- patch
|
||||||
|
|
||||||
|
- package-ecosystem: npm
|
||||||
|
directory: /
|
||||||
|
schedule:
|
||||||
|
interval: monthly
|
||||||
|
ignore:
|
||||||
|
- dependency-name: '@types/node'
|
||||||
|
update-types:
|
||||||
|
- 'version-update:semver-major'
|
||||||
|
groups:
|
||||||
|
npm-development:
|
||||||
|
dependency-type: development
|
||||||
|
update-types:
|
||||||
|
- minor
|
||||||
|
- patch
|
||||||
|
npm-production:
|
||||||
|
dependency-type: production
|
||||||
|
update-types:
|
||||||
|
- patch
|
61
.github/workflows/check-dist.yml
vendored
61
.github/workflows/check-dist.yml
vendored
@ -1,9 +1,13 @@
|
|||||||
# `dist/index.js` is a special file in Actions.
|
# In TypeScript actions, `dist/` is a special directory. When you reference
|
||||||
# When you reference an action with `uses:` in a workflow,
|
# an action with the `uses:` property, `dist/index.js` is the code that will be
|
||||||
# `index.js` is the code that will run.
|
# run. For this project, the `dist/index.js` file is transpiled from other
|
||||||
# For our project, we generate this file through a build process from other source files.
|
# source files. This workflow ensures the `dist/` directory contains the
|
||||||
# We need to make sure the checked-in `index.js` actually matches what we expect it to be.
|
# expected transpiled code.
|
||||||
name: Check dist/
|
#
|
||||||
|
# If this workflow is run from a feature branch, it will act as an additional CI
|
||||||
|
# check and fail if the checked-in `dist/` directory does not match what is
|
||||||
|
# expected from the build.
|
||||||
|
name: Check Transpiled JavaScript
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@ -16,40 +20,57 @@ on:
|
|||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.md'
|
- '**.md'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-dist:
|
check-dist:
|
||||||
|
name: Check dist/
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Checkout
|
||||||
|
id: checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set Node.js 20.x
|
- name: Setup Node.js
|
||||||
|
id: setup-node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20.x
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install Dependencies
|
||||||
|
id: install
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
- name: Rebuild the dist/ directory
|
- name: Build dist/ Directory
|
||||||
run: npm run build
|
id: build
|
||||||
|
run: npm run bundle
|
||||||
|
|
||||||
- name: Compare the expected and actual dist/ directories
|
# This will fail the workflow if the `dist/` directory is different than
|
||||||
|
# expected.
|
||||||
|
- name: Compare Directories
|
||||||
|
id: diff
|
||||||
run: |
|
run: |
|
||||||
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
|
if [ ! -d dist/ ]; then
|
||||||
echo "Detected uncommitted changes after build. See status below:"
|
echo "Expected dist/ directory does not exist. See status below:"
|
||||||
git diff
|
ls -la ./
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ "$(git diff --ignore-space-at-eol --text dist/ | wc -l)" -gt "0" ]; then
|
||||||
|
echo "Detected uncommitted changes after build. See status below:"
|
||||||
|
git diff --ignore-space-at-eol --text dist/
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
id: diff
|
|
||||||
|
|
||||||
# If index.js was different than expected, upload the expected version as an artifact
|
# If `dist/` was different than expected, upload the expected version as a
|
||||||
- uses: actions/upload-artifact@v3
|
# workflow artifact.
|
||||||
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
|
- if: ${{ failure() && steps.diff.outcome == 'failure' }}
|
||||||
|
name: Upload Artifact
|
||||||
|
id: upload
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: dist
|
name: dist
|
||||||
path: dist/
|
path: dist/
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
name: 'build-test'
|
name: Continuous Integration
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@ -8,38 +8,55 @@ on:
|
|||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.md'
|
- '**.md'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build: # make sure build/ci work properly
|
test-typescript:
|
||||||
|
name: TypeScript Tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Checkout
|
||||||
- run: |
|
uses: actions/checkout@v4
|
||||||
npm install
|
- name: Setup Node.js
|
||||||
- run: |
|
uses: actions/setup-node@v4
|
||||||
npm run all
|
with:
|
||||||
test:
|
node-version-file: .node-version
|
||||||
|
cache: npm
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: npm clean-install
|
||||||
|
- name: Check Format
|
||||||
|
run: npm run format:check
|
||||||
|
- name: Lint
|
||||||
|
run: npm run lint
|
||||||
|
- name: Test
|
||||||
|
run: npm run test
|
||||||
|
|
||||||
|
test-action:
|
||||||
name: GraalVM
|
name: GraalVM
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
# Skip builds that require a GDS token but have no access to one (e.g., secrets are unavailable in PR runs)
|
||||||
|
PASSES_GDS_TOKEN_CHECK: ${{ !matrix.set-gds-token || secrets.GDS_TOKEN != '' }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
java-version: ['22', '21', '17', '20', 'dev']
|
java-version: ['24', '21', '17', '20', 'dev']
|
||||||
distribution: ['graalvm', 'graalvm-community']
|
distribution: ['graalvm', 'graalvm-community']
|
||||||
os: [
|
os: [
|
||||||
ubuntu-latest,
|
ubuntu-latest, # Linux on Intel
|
||||||
macos-latest, # macOS on Apple silicon
|
ubuntu-22.04-arm, # Linux on arm64
|
||||||
macos-12, # macOS on Intel
|
macos-latest, # macOS on Apple silicon
|
||||||
windows-latest
|
macos-13, # macOS on Intel
|
||||||
]
|
windows-latest
|
||||||
|
]
|
||||||
set-gds-token: [false]
|
set-gds-token: [false]
|
||||||
components: ['']
|
components: ['']
|
||||||
include:
|
include:
|
||||||
- java-version: 'latest-ea'
|
- java-version: 'latest-ea'
|
||||||
distribution: 'graalvm'
|
distribution: 'graalvm'
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
- java-version: '23-ea'
|
- java-version: '25-ea'
|
||||||
distribution: 'graalvm'
|
distribution: 'graalvm'
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
- java-version: '21'
|
- java-version: '21'
|
||||||
@ -59,7 +76,7 @@ jobs:
|
|||||||
distribution: 'graalvm'
|
distribution: 'graalvm'
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
set-gds-token: true
|
set-gds-token: true
|
||||||
- java-version: '17.0.12' # Upgrade to '17.0.13' after Oct 2024
|
- java-version: '17.0.13'
|
||||||
distribution: 'graalvm'
|
distribution: 'graalvm'
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
set-gds-token: true
|
set-gds-token: true
|
||||||
@ -73,6 +90,7 @@ jobs:
|
|||||||
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 || '' }}
|
gds-token: ${{ matrix.set-gds-token && secrets.GDS_TOKEN || '' }}
|
||||||
|
if: ${{ env.PASSES_GDS_TOKEN_CHECK == 'true' }}
|
||||||
- name: Check environment
|
- name: Check environment
|
||||||
run: |
|
run: |
|
||||||
echo "GRAALVM_HOME: $GRAALVM_HOME"
|
echo "GRAALVM_HOME: $GRAALVM_HOME"
|
||||||
@ -85,15 +103,17 @@ 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: ${{ env.PASSES_GDS_TOKEN_CHECK == 'true' && runner.os != 'Windows' }}
|
||||||
- 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
|
||||||
test-ce: # make sure the action works on a clean machine without building
|
if: ${{ env.PASSES_GDS_TOKEN_CHECK == 'true' && runner.os == 'Windows' }}
|
||||||
needs: test
|
|
||||||
|
test-action-ce: # make sure the action works on a clean machine without building
|
||||||
|
needs: test-action
|
||||||
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:
|
||||||
@ -111,7 +131,7 @@ jobs:
|
|||||||
- version: '22.2.0' # for update notifications
|
- version: '22.2.0' # for update notifications
|
||||||
java-version: '17'
|
java-version: '17'
|
||||||
components: 'native-image'
|
components: 'native-image'
|
||||||
os: ubuntu-20.04
|
os: ubuntu-22.04
|
||||||
- version: '21.2.0'
|
- version: '21.2.0'
|
||||||
java-version: '8' # for JDK 8 notification
|
java-version: '8' # for JDK 8 notification
|
||||||
components: 'native-image'
|
components: 'native-image'
|
||||||
@ -119,7 +139,7 @@ jobs:
|
|||||||
- version: '22.3.1'
|
- version: '22.3.1'
|
||||||
java-version: '11' # for JDK 11 notification
|
java-version: '11' # for JDK 11 notification
|
||||||
components: 'native-image'
|
components: 'native-image'
|
||||||
os: macos-12
|
os: macos-13
|
||||||
- version: '22.3.1'
|
- version: '22.3.1'
|
||||||
java-version: '17'
|
java-version: '17'
|
||||||
components: 'native-image'
|
components: 'native-image'
|
||||||
@ -152,7 +172,7 @@ jobs:
|
|||||||
if [[ "${{ matrix.java-version }}" != "dev" ]]; then
|
if [[ "${{ matrix.java-version }}" != "dev" ]]; then
|
||||||
gu list
|
gu list
|
||||||
fi
|
fi
|
||||||
if: runner.os != 'Windows'
|
if: ${{ runner.os != 'Windows' }}
|
||||||
- name: Check Windows environment
|
- name: Check Windows environment
|
||||||
run: |
|
run: |
|
||||||
echo "GRAALVM_HOME: $env:GRAALVM_HOME"
|
echo "GRAALVM_HOME: $env:GRAALVM_HOME"
|
||||||
@ -160,12 +180,16 @@ jobs:
|
|||||||
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' }}
|
||||||
test-ee:
|
|
||||||
needs: test
|
test-action-ee:
|
||||||
|
needs: test-action
|
||||||
name: EE ${{ matrix.version }} + JDK${{ matrix.java-version }} on ${{ matrix.os }}
|
name: EE ${{ matrix.version }} + JDK${{ matrix.java-version }} on ${{ matrix.os }}
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
# Skip builds that require a GDS token but have no access to one (e.g., secrets are unavailable in PR runs)
|
||||||
|
PASSES_GDS_TOKEN_CHECK: ${{ secrets.GDS_TOKEN != '' }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
version: ['latest']
|
version: ['latest']
|
||||||
@ -191,6 +215,7 @@ jobs:
|
|||||||
java-version: ${{ matrix.java-version }}
|
java-version: ${{ matrix.java-version }}
|
||||||
components: ${{ matrix.components }}
|
components: ${{ matrix.components }}
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
if: ${{ env.PASSES_GDS_TOKEN_CHECK == 'true' }}
|
||||||
- name: Check environment
|
- name: Check environment
|
||||||
run: |
|
run: |
|
||||||
echo "GRAALVM_HOME: $GRAALVM_HOME"
|
echo "GRAALVM_HOME: $GRAALVM_HOME"
|
||||||
@ -200,7 +225,7 @@ jobs:
|
|||||||
java --version | grep -e "GraalVM EE" -e "Oracle GraalVM" || exit 23
|
java --version | grep -e "GraalVM EE" -e "Oracle GraalVM" || exit 23
|
||||||
native-image --version
|
native-image --version
|
||||||
gu list
|
gu list
|
||||||
if: runner.os != 'Windows'
|
if: ${{ env.PASSES_GDS_TOKEN_CHECK == 'true' && runner.os != 'Windows' }}
|
||||||
- name: Check Windows environment
|
- name: Check Windows environment
|
||||||
run: |
|
run: |
|
||||||
echo "GRAALVM_HOME: $env:GRAALVM_HOME"
|
echo "GRAALVM_HOME: $env:GRAALVM_HOME"
|
||||||
@ -208,9 +233,10 @@ jobs:
|
|||||||
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: ${{ env.PASSES_GDS_TOKEN_CHECK == 'true' && runner.os == 'Windows' }}
|
||||||
test-mandrel:
|
|
||||||
needs: test
|
test-action-mandrel:
|
||||||
|
needs: test-action
|
||||||
name: ${{ matrix.version }} + JDK${{ matrix.java-version }} on ${{ matrix.os }}
|
name: ${{ matrix.version }} + JDK${{ matrix.java-version }} on ${{ matrix.os }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
@ -245,16 +271,17 @@ jobs:
|
|||||||
java --version
|
java --version
|
||||||
java --version | grep "Temurin" || exit 23
|
java --version | grep "Temurin" || exit 23
|
||||||
native-image --version
|
native-image --version
|
||||||
if: runner.os != 'Windows'
|
if: ${{ runner.os != 'Windows' }}
|
||||||
- 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'
|
if: ${{ runner.os == 'Windows' }}
|
||||||
test-liberica:
|
|
||||||
needs: test
|
test-action-liberica:
|
||||||
|
needs: test-action
|
||||||
name: Liberica (${{ matrix.java-version }}, '${{ matrix.java-package }}', ${{ matrix.os }})
|
name: Liberica (${{ matrix.java-version }}, '${{ matrix.java-package }}', ${{ matrix.os }})
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
@ -280,7 +307,7 @@ jobs:
|
|||||||
java --version | fgrep -qw ${{ matrix.java-version }} || exit 23
|
java --version | fgrep -qw ${{ matrix.java-version }} || exit 23
|
||||||
native-image --version
|
native-image --version
|
||||||
native-image --version | fgrep -qw ${{ matrix.java-version }} || exit 24
|
native-image --version | fgrep -qw ${{ matrix.java-version }} || exit 24
|
||||||
if: runner.os != 'Windows'
|
if: ${{ runner.os != 'Windows' }}
|
||||||
- name: Check Windows environment
|
- name: Check Windows environment
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
@ -294,8 +321,9 @@ jobs:
|
|||||||
if (!(native-image --version | findstr \<${{ matrix.java-version }}\>)) {
|
if (!(native-image --version | findstr \<${{ matrix.java-version }}\>)) {
|
||||||
exit 24
|
exit 24
|
||||||
}
|
}
|
||||||
if: runner.os == 'Windows'
|
if: ${{ runner.os == 'Windows' }}
|
||||||
test-native-image-windows:
|
|
||||||
|
test-action-native-image-windows:
|
||||||
name: native-image on windows-latest
|
name: native-image on windows-latest
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
permissions:
|
permissions:
|
||||||
@ -317,7 +345,8 @@ jobs:
|
|||||||
javac HelloWorld.java
|
javac HelloWorld.java
|
||||||
native-image HelloWorld
|
native-image HelloWorld
|
||||||
./helloworld
|
./helloworld
|
||||||
test-native-image-windows-msvc:
|
|
||||||
|
test-action-native-image-windows-msvc:
|
||||||
name: native-image on windows-2022
|
name: native-image on windows-2022
|
||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
permissions:
|
permissions:
|
||||||
@ -339,7 +368,8 @@ jobs:
|
|||||||
javac HelloWorld.java
|
javac HelloWorld.java
|
||||||
native-image HelloWorld
|
native-image HelloWorld
|
||||||
./helloworld
|
./helloworld
|
||||||
test-native-image-musl:
|
|
||||||
|
test-action-native-image-musl:
|
||||||
name: native-image-musl on ubuntu-latest
|
name: native-image-musl on ubuntu-latest
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
@ -362,7 +392,8 @@ jobs:
|
|||||||
javac HelloWorld.java
|
javac HelloWorld.java
|
||||||
native-image --static --libc=musl HelloWorld
|
native-image --static --libc=musl HelloWorld
|
||||||
./helloworld
|
./helloworld
|
||||||
test-extensive:
|
|
||||||
|
test-action-extensive:
|
||||||
name: extensive tests on ubuntu-latest
|
name: extensive tests on ubuntu-latest
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
@ -417,3 +448,40 @@ jobs:
|
|||||||
# popd > /dev/null
|
# popd > /dev/null
|
||||||
- name: Remove components
|
- name: Remove components
|
||||||
run: gu remove espresso llvm-toolchain nodejs python ruby wasm
|
run: gu remove espresso llvm-toolchain nodejs python ruby wasm
|
||||||
|
|
||||||
|
test-action-sbom:
|
||||||
|
name: test 'native-image-enable-sbom' option
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
java-version: ['24-ea', 'latest-ea']
|
||||||
|
distribution: ['graalvm']
|
||||||
|
os: [macos-latest, windows-latest, ubuntu-latest, ubuntu-22.04-arm]
|
||||||
|
components: ['']
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Run setup-graalvm action
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
java-version: ${{ matrix.java-version }}
|
||||||
|
distribution: ${{ matrix.distribution }}
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
components: ${{ matrix.components }}
|
||||||
|
native-image-enable-sbom: 'true'
|
||||||
|
cache: 'maven'
|
||||||
|
- name: Build Maven project and verify that SBOM was generated and its contents
|
||||||
|
run: |
|
||||||
|
cd __tests__/sbom/main-test-app
|
||||||
|
mvn --no-transfer-progress -Pnative package
|
||||||
|
bash verify-sbom.sh
|
||||||
|
shell: bash
|
||||||
|
if: ${{ runner.os != 'Windows' }}
|
||||||
|
- name: Build Maven project and verify that SBOM was generated and its contents (Windows)
|
||||||
|
run: |
|
||||||
|
cd __tests__\sbom\main-test-app
|
||||||
|
mvn --no-transfer-progress -Pnative package
|
||||||
|
cmd /c verify-sbom.cmd
|
||||||
|
shell: cmd
|
||||||
|
if: ${{ runner.os == 'Windows' }}
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -96,4 +96,7 @@ Thumbs.db
|
|||||||
|
|
||||||
# Ignore built ts files
|
# Ignore built ts files
|
||||||
__tests__/runner/*
|
__tests__/runner/*
|
||||||
lib/**/*
|
lib/**/*
|
||||||
|
|
||||||
|
# Ignore target directory in __tests__
|
||||||
|
__tests__/**/target
|
||||||
|
1
.node-version
Normal file
1
.node-version
Normal file
@ -0,0 +1 @@
|
|||||||
|
20.9.0
|
@ -1,3 +1,3 @@
|
|||||||
dist/
|
dist/
|
||||||
lib/
|
node_modules/
|
||||||
node_modules/
|
README.md
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"printWidth": 80,
|
|
||||||
"tabWidth": 2,
|
|
||||||
"useTabs": false,
|
|
||||||
"semi": false,
|
|
||||||
"singleQuote": true,
|
|
||||||
"trailingComma": "none",
|
|
||||||
"bracketSpacing": false,
|
|
||||||
"arrowParens": "avoid"
|
|
||||||
}
|
|
16
.prettierrc.yml
Normal file
16
.prettierrc.yml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# See: https://prettier.io/docs/en/configuration
|
||||||
|
|
||||||
|
printWidth: 120
|
||||||
|
tabWidth: 2
|
||||||
|
useTabs: false
|
||||||
|
semi: false
|
||||||
|
singleQuote: true
|
||||||
|
quoteProps: as-needed
|
||||||
|
jsxSingleQuote: false
|
||||||
|
trailingComma: none
|
||||||
|
bracketSpacing: true
|
||||||
|
bracketSameLine: true
|
||||||
|
arrowParens: always
|
||||||
|
proseWrap: always
|
||||||
|
htmlWhitespaceSensitivity: css
|
||||||
|
endOfLine: lf
|
147
README.md
147
README.md
@ -1,5 +1,7 @@
|
|||||||
# GitHub Action for GraalVM [](https://github.com/graalvm/setup-graalvm/actions/workflows/test.yml)
|
# GitHub Action for GraalVM [](https://github.com/graalvm/setup-graalvm/actions/workflows/ci.yml)
|
||||||
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].
|
|
||||||
|
Set up your GitHub Actions workflow with a specific [GraalVM][graalvm] distribution, and use it both as your JDK and for [ahead-of-time Native Image compilation][graalvm].
|
||||||
|
|
||||||
|
|
||||||
## Key Features
|
## Key Features
|
||||||
|
|
||||||
@ -7,12 +9,10 @@ This action:
|
|||||||
|
|
||||||
- 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))
|
- 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`, `javac`, and other JDK 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))
|
||||||
- supports `x64` and `aarch64` (selected automatically, `aarch64` requires a [self-hosted runner][gha-self-hosted-runners])
|
- supports `x64` and `aarch64/arm64` (see how to use [Linux arm64 runners](https://github.blog/changelog/2025-01-16-linux-arm64-hosted-runners-now-available-for-free-in-public-repositories-public-preview/))
|
||||||
- supports dependency caching for Apache Maven, Gradle, and sbt (see [`cache` option](#options))
|
- supports dependency caching for Apache Maven, Gradle, and sbt (see [`cache` option](#options))
|
||||||
- sets up Windows environments with build tools using [vcvarsall.bat][vcvarsall]
|
|
||||||
- has built-in support for GraalVM components and the [GraalVM Updater][gu]
|
|
||||||
|
|
||||||
|
|
||||||
## Templates
|
## Templates
|
||||||
@ -29,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' # See 'Options' section below for all supported versions
|
java-version: '21' # See 'Options' for more details
|
||||||
distribution: 'graalvm' # See 'Options' section below 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: |
|
||||||
@ -74,7 +74,7 @@ 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*
|
||||||
@ -104,41 +104,41 @@ jobs:
|
|||||||
|
|
||||||
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:
|
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
|
```bash
|
||||||
curl -sS -X POST "https://gds.oracle.com/api/20220101/licenseAcceptance" \
|
curl -sS -X POST "https://gds.oracle.com/api/20220101/licenseAcceptance" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "{ \"email\": \"your@email.com\", \"licenseId\": \"D53FA58D12817B3CE0530F15000A74CA\", \"type\": \"GENERATE_TOKEN_AND_ACCEPT_LICENSE\"}"
|
-d "{ \"email\": \"your@email.com\", \"licenseId\": \"D53FA58D12817B3CE0530F15000A74CA\", \"type\": \"GENERATE_TOKEN_AND_ACCEPT_LICENSE\"}"
|
||||||
```
|
```
|
||||||
|
|
||||||
The response should look like this:
|
The response should look like this:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{"token":"<your-token>","status":"UNVERIFIED"}
|
{"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`.
|
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.
|
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:
|
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
|
```yml
|
||||||
name: Build with Oracle GraalVM for JDK 17 via GDS
|
name: Build with Oracle GraalVM for JDK 17 via GDS
|
||||||
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:
|
||||||
distribution: 'graalvm'
|
distribution: 'graalvm'
|
||||||
java-version: '17'
|
java-version: '17'
|
||||||
gds-token: ${{ secrets.GDS_TOKEN }}
|
gds-token: ${{ secrets.GDS_TOKEN }}
|
||||||
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>
|
||||||
|
|
||||||
@ -150,38 +150,52 @@ 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]. In the following 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 | Java version <ul><li>major versions: `'21'`, `'17'`, `'11'`, `'8'`</li><li>specific versions: `'21.0.3'`, `'17.0.11'`</li><li>early access (EA) builds: `'23-ea'` *(requires `distribution: 'graalvm'`)*</li><li>latest EA build: `'latest-ea'` *(requires `distribution: 'graalvm'`)*</li><li>dev builds: `'dev'`</li></ul> |
|
| `java-version`<br>*(required)* | n/a | Java version <ul><li>major versions: `'24'`, `'21'`, `'17'`, `'11'`, `'8'`</li><li>specific versions: `'21.0.3'`, `'17.0.11'`</li><li>early access (EA) builds: `'25-ea'` *(requires `distribution: 'graalvm'`)*</li><li>latest EA build: `'latest-ea'` *(requires `distribution: 'graalvm'`)*</li><li>dev builds: `'dev'`</li></ul> |
|
||||||
| `distribution` | `'graalvm'` | GraalVM distribution <ul><li>Oracle GraalVM: `'graalvm'`</li><li>GraalVM Community Edition: `'graalvm-community'`</li><li>Mandrel: `'mandrel'`</li><li>Liberica: `'liberica'`</li></ul> |
|
| `distribution` | `'graalvm'` | GraalVM distribution (see [supported distributions](#supported-distributions)) |
|
||||||
| `java-package` | `'jdk'` | The package type (`'jdk'` or `'jdk+fx'`). Currently applies to Liberica only. |
|
| `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`. |
|
||||||
@ -191,9 +205,11 @@ jobs:
|
|||||||
| `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`. |
|
| `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`. |
|
||||||
|
| `native-image-enable-sbom` | `'false'` | If set to `'true'`, generate a minimal SBOM based on the Native Image static analysis and submit it to GitHub's dependency submission API. This enables the [dependency graph feature](https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-the-dependency-graph) for dependency tracking and vulnerability analysis. Requires `write` permissions for the [`contents` scope][gha-permissions] and the dependency graph to be actived (on by default for public repositories - see [how to activate](https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/configuring-the-dependency-graph#enabling-and-disabling-the-dependency-graph-for-a-private-repository)). Only available in Oracle GraalVM for JDK 24 or later. |
|
||||||
| `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. at <> Store this token as a [GitHub Action secret][gha-secrets]. For thie followingtemplate, we use the name `GDS_TOKEN`.. 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.*
|
||||||
|
|
||||||
|
|
||||||
@ -231,7 +247,7 @@ can be replaced with:
|
|||||||
# ...
|
# ...
|
||||||
- uses: graalvm/setup-graalvm@v1
|
- uses: graalvm/setup-graalvm@v1
|
||||||
with:
|
with:
|
||||||
java-version: '17.0.7' # for a specific JDK 17; or '17' for the latest JDK 17
|
java-version: '17.0.12' # for a specific JDK 17; or '17' for the latest JDK 17
|
||||||
distribution: 'graalvm' # New 'distribution' option
|
distribution: 'graalvm' # New 'distribution' option
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
@ -254,21 +270,16 @@ Only pull requests from committers that can be verified as having signed the OCA
|
|||||||
[gha-self-hosted-runners]: https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners
|
[gha-self-hosted-runners]: https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners
|
||||||
[gu]: https://www.graalvm.org/reference-manual/graalvm-updater/
|
[gu]: https://www.graalvm.org/reference-manual/graalvm-updater/
|
||||||
[graalvm]: https://www.graalvm.org/
|
[graalvm]: https://www.graalvm.org/
|
||||||
[graalvm-dl]: https://www.oracle.com/java/technologies/downloads/
|
[graalvm-dl]: https://www.graalvm.org/downloads/
|
||||||
[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/
|
[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
|
||||||
[musl]: https://musl.libc.org/
|
[musl]: https://musl.libc.org/
|
||||||
[native-image]: https://www.graalvm.org/native-image/
|
|
||||||
[native-image-musl-build]: https://github.com/graalvm/setup-graalvm/blob/778131f1d6837ccd4b2e91382c31830896a2d56e/.github/workflows/test.yml#L74-L92
|
[native-image-musl-build]: https://github.com/graalvm/setup-graalvm/blob/778131f1d6837ccd4b2e91382c31830896a2d56e/.github/workflows/test.yml#L74-L92
|
||||||
[native-image-static]: https://github.com/oracle/graal/blob/fa6f4a974dedacf4688dcc430dd100849d9882f2/docs/reference-manual/native-image/StaticImages.md
|
[native-image-static]: https://github.com/oracle/graal/blob/fa6f4a974dedacf4688dcc430dd100849d9882f2/docs/reference-manual/native-image/StaticImages.md
|
||||||
[oca]: https://oca.opensource.oracle.com
|
[oca]: https://oca.opensource.oracle.com
|
||||||
[releases]: https://github.com/graalvm/graalvm-ce-builds/releases
|
[releases]: https://github.com/graalvm/graalvm-ce-builds/releases
|
||||||
[repo]: https://github.com/oracle/graal
|
|
||||||
[setup-java-caching]: https://github.com/actions/setup-java/tree/5b36705a13905facb447b6812d613a06a07e371d#caching-packages-dependencies
|
[setup-java-caching]: https://github.com/actions/setup-java/tree/5b36705a13905facb447b6812d613a06a07e371d#caching-packages-dependencies
|
||||||
[stable]: https://github.com/graalvm/graalvm-ce-builds/releases/latest
|
[stable]: https://github.com/graalvm/graalvm-ce-builds/releases/latest
|
||||||
[truffle-languages]: https://www.graalvm.org/reference-manual/languages/
|
|
||||||
[vcvarsall]: https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line
|
|
||||||
|
@ -24,10 +24,10 @@
|
|||||||
* Forked from https://github.com/actions/setup-java/blob/5b36705a13905facb447b6812d613a06a07e371d/__tests__/cache.test.ts
|
* Forked from https://github.com/actions/setup-java/blob/5b36705a13905facb447b6812d613a06a07e371d/__tests__/cache.test.ts
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {mkdtempSync} from 'fs'
|
import { mkdtempSync } from 'fs'
|
||||||
import {tmpdir} from 'os'
|
import { tmpdir } from 'os'
|
||||||
import {join} from 'path'
|
import { join } from 'path'
|
||||||
import {restore, save} from '../src/features/cache'
|
import { restore, save } from '../src/features/cache'
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
import * as os from 'os'
|
import * as os from 'os'
|
||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
@ -86,24 +86,17 @@ describe('dependency cache', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('restore', () => {
|
describe('restore', () => {
|
||||||
let spyCacheRestore: jest.SpyInstance<
|
let spyCacheRestore: jest.SpyInstance<ReturnType<typeof cache.restoreCache>, Parameters<typeof cache.restoreCache>>
|
||||||
ReturnType<typeof cache.restoreCache>,
|
|
||||||
Parameters<typeof cache.restoreCache>
|
|
||||||
>
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyCacheRestore = jest
|
spyCacheRestore = jest
|
||||||
.spyOn(cache, 'restoreCache')
|
.spyOn(cache, 'restoreCache')
|
||||||
.mockImplementation((paths: string[], primaryKey: string) =>
|
.mockImplementation((_paths: string[], _primaryKey: string) => Promise.resolve(undefined))
|
||||||
Promise.resolve(undefined)
|
|
||||||
)
|
|
||||||
spyWarning.mockImplementation(() => null)
|
spyWarning.mockImplementation(() => null)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('throws error if unsupported package manager specified', () => {
|
it('throws error if unsupported package manager specified', () => {
|
||||||
return expect(restore('ant')).rejects.toThrow(
|
return expect(restore('ant')).rejects.toThrow('unknown package manager specified: ant')
|
||||||
'unknown package manager specified: ant'
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('for maven', () => {
|
describe('for maven', () => {
|
||||||
@ -176,24 +169,17 @@ describe('dependency cache', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
describe('save', () => {
|
describe('save', () => {
|
||||||
let spyCacheSave: jest.SpyInstance<
|
let spyCacheSave: jest.SpyInstance<ReturnType<typeof cache.saveCache>, Parameters<typeof cache.saveCache>>
|
||||||
ReturnType<typeof cache.saveCache>,
|
|
||||||
Parameters<typeof cache.saveCache>
|
|
||||||
>
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyCacheSave = jest
|
spyCacheSave = jest
|
||||||
.spyOn(cache, 'saveCache')
|
.spyOn(cache, 'saveCache')
|
||||||
.mockImplementation((paths: string[], key: string) =>
|
.mockImplementation((_paths: string[], _key: string) => Promise.resolve(0))
|
||||||
Promise.resolve(0)
|
|
||||||
)
|
|
||||||
spyWarning.mockImplementation(() => null)
|
spyWarning.mockImplementation(() => null)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('throws error if unsupported package manager specified', () => {
|
it('throws error if unsupported package manager specified', () => {
|
||||||
return expect(save('ant')).rejects.toThrow(
|
return expect(save('ant')).rejects.toThrow('unknown package manager specified: ant')
|
||||||
'unknown package manager specified: ant'
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('save with -1 cacheId , should not fail workflow', async () => {
|
it('save with -1 cacheId , should not fail workflow', async () => {
|
||||||
@ -204,21 +190,15 @@ describe('dependency cache', () => {
|
|||||||
expect(spyCacheSave).toHaveBeenCalled()
|
expect(spyCacheSave).toHaveBeenCalled()
|
||||||
expect(spyWarning).not.toHaveBeenCalled()
|
expect(spyWarning).not.toHaveBeenCalled()
|
||||||
expect(spyInfo).toHaveBeenCalled()
|
expect(spyInfo).toHaveBeenCalled()
|
||||||
expect(spyInfo).toHaveBeenCalledWith(
|
expect(spyInfo).toHaveBeenCalledWith(expect.stringMatching(/^Cache saved with the key:.*/))
|
||||||
expect.stringMatching(/^Cache saved with the key:.*/)
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('saves with error from toolkit, should fail workflow', async () => {
|
it('saves with error from toolkit, should fail workflow', async () => {
|
||||||
spyCacheSave.mockImplementation(() =>
|
spyCacheSave.mockImplementation(() => Promise.reject(new cache.ValidationError('Validation failed')))
|
||||||
Promise.reject(new cache.ValidationError('Validation failed'))
|
|
||||||
)
|
|
||||||
createStateForMissingBuildFile()
|
createStateForMissingBuildFile()
|
||||||
|
|
||||||
expect.assertions(1)
|
expect.assertions(1)
|
||||||
await expect(save('maven')).rejects.toEqual(
|
await expect(save('maven')).rejects.toEqual(new cache.ValidationError('Validation failed'))
|
||||||
new cache.ValidationError('Validation failed')
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('for maven', () => {
|
describe('for maven', () => {
|
||||||
@ -233,9 +213,7 @@ describe('dependency cache', () => {
|
|||||||
|
|
||||||
await save('maven')
|
await save('maven')
|
||||||
expect(spyCacheSave).not.toHaveBeenCalled()
|
expect(spyCacheSave).not.toHaveBeenCalled()
|
||||||
expect(spyWarning).toHaveBeenCalledWith(
|
expect(spyWarning).toHaveBeenCalledWith('Error retrieving key from state.')
|
||||||
'Error retrieving key from state.'
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
it('uploads cache', async () => {
|
it('uploads cache', async () => {
|
||||||
createFile(join(workspace, 'pom.xml'))
|
createFile(join(workspace, 'pom.xml'))
|
||||||
@ -244,9 +222,7 @@ describe('dependency cache', () => {
|
|||||||
await save('maven')
|
await save('maven')
|
||||||
expect(spyCacheSave).toHaveBeenCalled()
|
expect(spyCacheSave).toHaveBeenCalled()
|
||||||
expect(spyWarning).not.toHaveBeenCalled()
|
expect(spyWarning).not.toHaveBeenCalled()
|
||||||
expect(spyInfo).toHaveBeenCalledWith(
|
expect(spyInfo).toHaveBeenCalledWith(expect.stringMatching(/^Cache saved with the key:.*/))
|
||||||
expect.stringMatching(/^Cache saved with the key:.*/)
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
describe('for gradle', () => {
|
describe('for gradle', () => {
|
||||||
@ -262,9 +238,7 @@ describe('dependency cache', () => {
|
|||||||
|
|
||||||
await save('gradle')
|
await save('gradle')
|
||||||
expect(spyCacheSave).not.toHaveBeenCalled()
|
expect(spyCacheSave).not.toHaveBeenCalled()
|
||||||
expect(spyWarning).toHaveBeenCalledWith(
|
expect(spyWarning).toHaveBeenCalledWith('Error retrieving key from state.')
|
||||||
'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'))
|
||||||
@ -273,9 +247,7 @@ describe('dependency cache', () => {
|
|||||||
await save('gradle')
|
await save('gradle')
|
||||||
expect(spyCacheSave).toHaveBeenCalled()
|
expect(spyCacheSave).toHaveBeenCalled()
|
||||||
expect(spyWarning).not.toHaveBeenCalled()
|
expect(spyWarning).not.toHaveBeenCalled()
|
||||||
expect(spyInfo).toHaveBeenCalledWith(
|
expect(spyInfo).toHaveBeenCalledWith(expect.stringMatching(/^Cache saved with the key:.*/))
|
||||||
expect.stringMatching(/^Cache saved with the key:.*/)
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
it('uploads cache based on build.gradle.kts', async () => {
|
it('uploads cache based on build.gradle.kts', async () => {
|
||||||
createFile(join(workspace, 'build.gradle.kts'))
|
createFile(join(workspace, 'build.gradle.kts'))
|
||||||
@ -284,9 +256,7 @@ describe('dependency cache', () => {
|
|||||||
await save('gradle')
|
await save('gradle')
|
||||||
expect(spyCacheSave).toHaveBeenCalled()
|
expect(spyCacheSave).toHaveBeenCalled()
|
||||||
expect(spyWarning).not.toHaveBeenCalled()
|
expect(spyWarning).not.toHaveBeenCalled()
|
||||||
expect(spyInfo).toHaveBeenCalledWith(
|
expect(spyInfo).toHaveBeenCalledWith(expect.stringMatching(/^Cache saved with the key:.*/))
|
||||||
expect.stringMatching(/^Cache saved with the key:.*/)
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
it('uploads cache based on buildSrc/Versions.kt', async () => {
|
it('uploads cache based on buildSrc/Versions.kt', async () => {
|
||||||
createDirectory(join(workspace, 'buildSrc'))
|
createDirectory(join(workspace, 'buildSrc'))
|
||||||
@ -296,9 +266,7 @@ describe('dependency cache', () => {
|
|||||||
await save('gradle')
|
await save('gradle')
|
||||||
expect(spyCacheSave).toHaveBeenCalled()
|
expect(spyCacheSave).toHaveBeenCalled()
|
||||||
expect(spyWarning).not.toHaveBeenCalled()
|
expect(spyWarning).not.toHaveBeenCalled()
|
||||||
expect(spyInfo).toHaveBeenCalledWith(
|
expect(spyInfo).toHaveBeenCalledWith(expect.stringMatching(/^Cache saved with the key:.*/))
|
||||||
expect.stringMatching(/^Cache saved with the key:.*/)
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
describe('for sbt', () => {
|
describe('for sbt', () => {
|
||||||
@ -313,9 +281,7 @@ describe('dependency cache', () => {
|
|||||||
|
|
||||||
await save('sbt')
|
await save('sbt')
|
||||||
expect(spyCacheSave).not.toHaveBeenCalled()
|
expect(spyCacheSave).not.toHaveBeenCalled()
|
||||||
expect(spyWarning).toHaveBeenCalledWith(
|
expect(spyWarning).toHaveBeenCalledWith('Error retrieving key from state.')
|
||||||
'Error retrieving key from state.'
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
it('uploads cache', async () => {
|
it('uploads cache', async () => {
|
||||||
createFile(join(workspace, 'build.sbt'))
|
createFile(join(workspace, 'build.sbt'))
|
||||||
@ -324,9 +290,7 @@ describe('dependency cache', () => {
|
|||||||
await save('sbt')
|
await save('sbt')
|
||||||
expect(spyCacheSave).toHaveBeenCalled()
|
expect(spyCacheSave).toHaveBeenCalled()
|
||||||
expect(spyWarning).not.toHaveBeenCalled()
|
expect(spyWarning).not.toHaveBeenCalled()
|
||||||
expect(spyInfo).toHaveBeenCalledWith(
|
expect(spyInfo).toHaveBeenCalledWith(expect.stringMatching(/^Cache saved with the key:.*/))
|
||||||
expect.stringMatching(/^Cache saved with the key:.*/)
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -340,7 +304,7 @@ function resetState() {
|
|||||||
* Create states to emulate a restore process without build file.
|
* Create states to emulate a restore process without build file.
|
||||||
*/
|
*/
|
||||||
function createStateForMissingBuildFile() {
|
function createStateForMissingBuildFile() {
|
||||||
jest.spyOn(core, 'getState').mockImplementation(name => {
|
jest.spyOn(core, 'getState').mockImplementation((name) => {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'cache-primary-key':
|
case 'cache-primary-key':
|
||||||
return 'setup-graalvm-cache-'
|
return 'setup-graalvm-cache-'
|
||||||
@ -354,7 +318,7 @@ function createStateForMissingBuildFile() {
|
|||||||
* Create states to emulate a successful restore process.
|
* Create states to emulate a successful restore process.
|
||||||
*/
|
*/
|
||||||
function createStateForSuccessfulRestore() {
|
function createStateForSuccessfulRestore() {
|
||||||
jest.spyOn(core, 'getState').mockImplementation(name => {
|
jest.spyOn(core, 'getState').mockImplementation((name) => {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'cache-primary-key':
|
case 'cache-primary-key':
|
||||||
return 'setup-graalvm-cache-primary-key'
|
return 'setup-graalvm-cache-primary-key'
|
||||||
|
@ -24,18 +24,14 @@
|
|||||||
* Forked from https://github.com/actions/setup-java/blob/5b36705a13905facb447b6812d613a06a07e371d/__tests__/cleanup-java.test.ts
|
* Forked from https://github.com/actions/setup-java/blob/5b36705a13905facb447b6812d613a06a07e371d/__tests__/cleanup-java.test.ts
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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'
|
||||||
|
|
||||||
describe('cleanup', () => {
|
describe('cleanup', () => {
|
||||||
let spyWarning: jest.SpyInstance<void, Parameters<typeof core.warning>>
|
let spyWarning: jest.SpyInstance<void, Parameters<typeof core.warning>>
|
||||||
let spyInfo: jest.SpyInstance<void, Parameters<typeof core.info>>
|
let spyInfo: jest.SpyInstance<void, Parameters<typeof core.info>>
|
||||||
let spyCacheSave: jest.SpyInstance<
|
let spyCacheSave: jest.SpyInstance<ReturnType<typeof cache.saveCache>, Parameters<typeof cache.saveCache>>
|
||||||
ReturnType<typeof cache.saveCache>,
|
|
||||||
Parameters<typeof cache.saveCache>
|
|
||||||
>
|
|
||||||
let spyJobStatusSuccess: jest.SpyInstance
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyWarning = jest.spyOn(core, 'warning')
|
spyWarning = jest.spyOn(core, 'warning')
|
||||||
@ -49,12 +45,10 @@ describe('cleanup', () => {
|
|||||||
resetState()
|
resetState()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('does not fail nor warn even when the save provess throws a ReserveCacheError', async () => {
|
it('does not fail nor warn even when the save process throws a ReserveCacheError', async () => {
|
||||||
spyCacheSave.mockImplementation((paths: string[], key: string) =>
|
spyCacheSave.mockImplementation((_paths: string[], _key: string) =>
|
||||||
Promise.reject(
|
Promise.reject(
|
||||||
new cache.ReserveCacheError(
|
new cache.ReserveCacheError('Unable to reserve cache with key, another job may be creating this cache.')
|
||||||
'Unable to reserve cache with key, another job may be creating this cache.'
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
|
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
|
||||||
@ -66,9 +60,7 @@ describe('cleanup', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('does not fail even though the save process throws error', async () => {
|
it('does not fail even though the save process throws error', async () => {
|
||||||
spyCacheSave.mockImplementation((paths: string[], key: string) =>
|
spyCacheSave.mockImplementation((_paths: string[], _key: string) => Promise.reject(new Error('Unexpected error')))
|
||||||
Promise.reject(new Error('Unexpected error'))
|
|
||||||
)
|
|
||||||
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
|
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
|
||||||
return name === 'cache' ? 'gradle' : ''
|
return name === 'cache' ? 'gradle' : ''
|
||||||
})
|
})
|
||||||
@ -85,7 +77,7 @@ function resetState() {
|
|||||||
* Create states to emulate a successful restore process.
|
* Create states to emulate a successful restore process.
|
||||||
*/
|
*/
|
||||||
function createStateForSuccessfulRestore() {
|
function createStateForSuccessfulRestore() {
|
||||||
jest.spyOn(core, 'getState').mockImplementation(name => {
|
jest.spyOn(core, 'getState').mockImplementation((name) => {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'cache-primary-key':
|
case 'cache-primary-key':
|
||||||
return 'setup-java-cache-primary-key'
|
return 'setup-java-cache-primary-key'
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import {
|
import { downloadGraalVM, downloadGraalVMEELegacy, fetchArtifact, fetchArtifactEE } from '../src/gds'
|
||||||
downloadGraalVM,
|
import { expect, test } from '@jest/globals'
|
||||||
downloadGraalVMEELegacy,
|
|
||||||
fetchArtifact,
|
|
||||||
fetchArtifactEE
|
|
||||||
} from '../src/gds'
|
|
||||||
import {expect, test} from '@jest/globals'
|
|
||||||
|
|
||||||
const TEST_USER_AGENT = 'GraalVMGitHubActionTest/1.0.4'
|
const TEST_USER_AGENT = 'GraalVMGitHubActionTest/1.0.4'
|
||||||
|
|
||||||
@ -14,64 +9,42 @@ process.env['RUNNER_TEMP'] = path.join(__dirname, 'TEMP')
|
|||||||
test('fetch artifacts', async () => {
|
test('fetch artifacts', async () => {
|
||||||
let artifact = await fetchArtifact(TEST_USER_AGENT, 'isBase:True', '17.0.12')
|
let artifact = await fetchArtifact(TEST_USER_AGENT, 'isBase:True', '17.0.12')
|
||||||
expect(artifact.id).toBe('1C351E8F41BB8E9EE0631518000AE5F2')
|
expect(artifact.id).toBe('1C351E8F41BB8E9EE0631518000AE5F2')
|
||||||
expect(artifact.checksum).toBe(
|
expect(artifact.checksum).toBe('b6f3dace24cf1960ec790216f4c86f00d4f43df64e4e8b548f6382f04894713f')
|
||||||
'b6f3dace24cf1960ec790216f4c86f00d4f43df64e4e8b548f6382f04894713f'
|
|
||||||
)
|
|
||||||
artifact = await fetchArtifact(TEST_USER_AGENT, 'isBase:True', '17')
|
artifact = await fetchArtifact(TEST_USER_AGENT, 'isBase:True', '17')
|
||||||
expect(artifact.checksum).toHaveLength(
|
expect(artifact.checksum).toHaveLength('b6f3dace24cf1960ec790216f4c86f00d4f43df64e4e8b548f6382f04894713f'.length)
|
||||||
'b6f3dace24cf1960ec790216f4c86f00d4f43df64e4e8b548f6382f04894713f'.length
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('errors when downloading artifacts', async () => {
|
test('errors when downloading artifacts', async () => {
|
||||||
await expect(downloadGraalVM('invalid', '17')).rejects.toThrow(
|
await expect(downloadGraalVM('invalid', '17')).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(downloadGraalVM('invalid', '1')).rejects.toThrow(
|
await expect(downloadGraalVM('invalid', '1')).rejects.toThrow('Unable to find GraalVM for JDK 1')
|
||||||
'Unable to find GraalVM for JDK 1'
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('fetch legacy artifacts', async () => {
|
test('fetch legacy artifacts', async () => {
|
||||||
let artifact = await fetchArtifactEE(
|
let artifact = await fetchArtifactEE(TEST_USER_AGENT, 'isBase:True', '22.1.0', '11')
|
||||||
TEST_USER_AGENT,
|
|
||||||
'isBase:True',
|
|
||||||
'22.1.0',
|
|
||||||
'11'
|
|
||||||
)
|
|
||||||
expect(artifact.id).toBe('DCECD1C1B0B5B8DBE0536E16000A5C74')
|
expect(artifact.id).toBe('DCECD1C1B0B5B8DBE0536E16000A5C74')
|
||||||
expect(artifact.checksum).toBe(
|
expect(artifact.checksum).toBe('4280782f6c7fcabe0ba707e8389cbfaf7bbe6b0cf634d309e6efcd1b172e3ce6')
|
||||||
'4280782f6c7fcabe0ba707e8389cbfaf7bbe6b0cf634d309e6efcd1b172e3ce6'
|
artifact = await fetchArtifactEE(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(fetchArtifactEE(TEST_USER_AGENT, 'isBase:False', '22.1.0', '11')).rejects.toThrow(
|
||||||
fetchArtifactEE(TEST_USER_AGENT, 'isBase:False', '22.1.0', '11')
|
'Found more than one GDS artifact'
|
||||||
).rejects.toThrow('Found more than one GDS artifact')
|
)
|
||||||
await expect(
|
await expect(fetchArtifactEE(TEST_USER_AGENT, 'isBase:True', '1.0.0', '11')).rejects.toThrow(
|
||||||
fetchArtifactEE(TEST_USER_AGENT, 'isBase:True', '1.0.0', '11')
|
'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 legacy artifacts', async () => {
|
test('errors when downloading legacy artifacts', async () => {
|
||||||
await expect(
|
await expect(downloadGraalVMEELegacy('invalid', '22.1.0', '11')).rejects.toThrow(
|
||||||
downloadGraalVMEELegacy('invalid', '22.1.0', '11')
|
|
||||||
).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')).rejects.toThrow(
|
||||||
downloadGraalVMEELegacy('invalid', '1.0.0', '11')
|
'Unable to find JDK11-based GraalVM EE 1.0.0'
|
||||||
).rejects.toThrow('Unable to find JDK11-based GraalVM EE 1.0.0')
|
)
|
||||||
await expect(
|
await expect(downloadGraalVMEELegacy('invalid', '22.1.0', '1')).rejects.toThrow(
|
||||||
downloadGraalVMEELegacy('invalid', '22.1.0', '1')
|
'Unable to find JDK1-based GraalVM EE 22.1.0'
|
||||||
).rejects.toThrow('Unable to find JDK1-based GraalVM EE 22.1.0')
|
)
|
||||||
})
|
})
|
||||||
|
@ -1,19 +1,15 @@
|
|||||||
import * as path from 'path'
|
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 {
|
import { findGraalVMVersion, findHighestJavaVersion, findLatestEABuildDownloadUrl } from '../src/graalvm'
|
||||||
findGraalVMVersion,
|
import { GRAALVM_GH_USER, GRAALVM_RELEASES_REPO } from '../src/constants'
|
||||||
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')
|
||||||
|
|
||||||
test('request invalid version/javaVersion', async () => {
|
test('request invalid version/javaVersion', async () => {
|
||||||
for (var combination of [
|
for (const combination of [
|
||||||
['22.3.0', '7'],
|
['22.3.0', '7'],
|
||||||
['22.3', '17'],
|
['22.3', '17'],
|
||||||
['22.3', '7']
|
['22.3', '7']
|
||||||
@ -23,7 +19,7 @@ test('request invalid version/javaVersion', async () => {
|
|||||||
await graalvm.setUpGraalVMRelease('', combination[0], combination[1])
|
await graalvm.setUpGraalVMRelease('', combination[0], combination[1])
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!(err instanceof Error)) {
|
if (!(err instanceof Error)) {
|
||||||
fail(`Unexpected non-Error: ${err}`)
|
throw new Error(`Unexpected non-Error: ${err}`)
|
||||||
}
|
}
|
||||||
error = err
|
error = err
|
||||||
}
|
}
|
||||||
@ -36,27 +32,23 @@ test('request invalid version/javaVersion', async () => {
|
|||||||
|
|
||||||
test('find version/javaVersion', async () => {
|
test('find version/javaVersion', async () => {
|
||||||
// Make sure the action can find the latest Java version for known major versions
|
// Make sure the action can find the latest Java version for known major versions
|
||||||
for (var majorJavaVersion of ['17', '20']) {
|
for (const majorJavaVersion of ['17', '20']) {
|
||||||
await graalvm.findLatestGraalVMJDKCEJavaVersion(majorJavaVersion)
|
await graalvm.findLatestGraalVMJDKCEJavaVersion(majorJavaVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
let error = new Error('unexpected')
|
let error = new Error('unexpected')
|
||||||
try {
|
try {
|
||||||
await graalvm.findLatestGraalVMJDKCEJavaVersion('11')
|
await graalvm.findLatestGraalVMJDKCEJavaVersion('11')
|
||||||
fail('Should not find Java version for 11')
|
throw new Error('Should not find Java version for 11')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!(err instanceof Error)) {
|
if (!(err instanceof Error)) {
|
||||||
fail(`Unexpected non-Error: ${err}`)
|
throw new Error(`Unexpected non-Error: ${err}`)
|
||||||
}
|
}
|
||||||
error = err
|
error = err
|
||||||
}
|
}
|
||||||
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, 'vm-22.3.1')
|
||||||
GRAALVM_GH_USER,
|
|
||||||
GRAALVM_RELEASES_REPO,
|
|
||||||
'vm-22.3.1'
|
|
||||||
)
|
|
||||||
const latestVersion = findGraalVMVersion(latestRelease)
|
const latestVersion = findGraalVMVersion(latestRelease)
|
||||||
expect(latestVersion).not.toBe('')
|
expect(latestVersion).not.toBe('')
|
||||||
const latestJavaVersion = findHighestJavaVersion(latestRelease, latestVersion)
|
const latestJavaVersion = findHighestJavaVersion(latestRelease, latestVersion)
|
||||||
@ -64,11 +56,11 @@ test('find version/javaVersion', async () => {
|
|||||||
|
|
||||||
error = new Error('unexpected')
|
error = new Error('unexpected')
|
||||||
try {
|
try {
|
||||||
const invalidRelease = {...latestRelease, tag_name: 'invalid'}
|
const invalidRelease = { ...latestRelease, tag_name: 'invalid' }
|
||||||
findGraalVMVersion(invalidRelease)
|
findGraalVMVersion(invalidRelease)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!(err instanceof Error)) {
|
if (!(err instanceof Error)) {
|
||||||
fail(`Unexpected non-Error: ${err}`)
|
throw new Error(`Unexpected non-Error: ${err}`)
|
||||||
}
|
}
|
||||||
error = err
|
error = err
|
||||||
}
|
}
|
||||||
@ -78,17 +70,17 @@ test('find version/javaVersion', async () => {
|
|||||||
findHighestJavaVersion(latestRelease, 'invalid')
|
findHighestJavaVersion(latestRelease, 'invalid')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!(err instanceof Error)) {
|
if (!(err instanceof Error)) {
|
||||||
fail(`Unexpected non-Error: ${err}`)
|
throw new Error(`Unexpected non-Error: ${err}`)
|
||||||
}
|
}
|
||||||
error = err
|
error = err
|
||||||
}
|
}
|
||||||
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 () => {
|
test('find EA version/javaVersion', async () => {
|
||||||
let url22EA = await findLatestEABuildDownloadUrl('22-ea')
|
const url22EA = await findLatestEABuildDownloadUrl('22-ea')
|
||||||
expect(url22EA).not.toBe('')
|
expect(url22EA).not.toBe('')
|
||||||
let urlLatestEA = await findLatestEABuildDownloadUrl('latest-ea')
|
const urlLatestEA = await findLatestEABuildDownloadUrl('latest-ea')
|
||||||
expect(urlLatestEA).not.toBe('')
|
expect(urlLatestEA).not.toBe('')
|
||||||
|
|
||||||
let error = new Error('unexpected')
|
let error = new Error('unexpected')
|
||||||
@ -96,7 +88,7 @@ test('find version/javaVersion', async () => {
|
|||||||
await findLatestEABuildDownloadUrl('8-ea')
|
await findLatestEABuildDownloadUrl('8-ea')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!(err instanceof Error)) {
|
if (!(err instanceof Error)) {
|
||||||
fail(`Unexpected non-Error: ${err}`)
|
throw new Error(`Unexpected non-Error: ${err}`)
|
||||||
}
|
}
|
||||||
error = err
|
error = err
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,13 @@ import * as liberica from '../src/liberica'
|
|||||||
import * as c from '../src/constants'
|
import * as c from '../src/constants'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import * as semver from 'semver'
|
import * as semver from 'semver'
|
||||||
import {expect, test} from '@jest/globals'
|
import { expect, test } from '@jest/globals'
|
||||||
|
|
||||||
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')
|
||||||
|
|
||||||
|
/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "expectLatestToBe", "expectURL"] }] */
|
||||||
|
|
||||||
test('find latest JDK version', async () => {
|
test('find latest JDK version', async () => {
|
||||||
// Make sure the action can find the latest Java version for known major versions
|
// 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', atLeast('11.0.22+12'))
|
||||||
@ -41,29 +43,15 @@ test('find asset URL', async () => {
|
|||||||
|
|
||||||
if (!c.IS_LINUX) {
|
if (!c.IS_LINUX) {
|
||||||
// This check can fail on Linux because there's no `jdk+fx` package for aarch64 and/or musl
|
// This check can fail on Linux because there's no `jdk+fx` package for aarch64 and/or musl
|
||||||
await expectURL(
|
await expectURL('21.0.2+14', 'jdk+fx', 'bellsoft-liberica-vm-full-openjdk21.0.2')
|
||||||
'21.0.2+14',
|
|
||||||
'jdk+fx',
|
|
||||||
'bellsoft-liberica-vm-full-openjdk21.0.2'
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}, 10000)
|
}, 10000)
|
||||||
|
|
||||||
type verifier = (
|
type verifier = (version: string, major: number, minor: number, patch: number) => void
|
||||||
version: string,
|
|
||||||
major: number,
|
|
||||||
minor: number,
|
|
||||||
patch: number
|
|
||||||
) => void
|
|
||||||
|
|
||||||
function atLeast(expectedMinVersion: string): verifier {
|
function atLeast(expectedMinVersion: string): verifier {
|
||||||
const expectedMajor = semver.major(expectedMinVersion)
|
const expectedMajor = semver.major(expectedMinVersion)
|
||||||
return function (
|
return function (version: string, major: number, _minor: number, _patch: number) {
|
||||||
version: string,
|
|
||||||
major: number,
|
|
||||||
minor: number,
|
|
||||||
patch: number
|
|
||||||
) {
|
|
||||||
expect(major).toBe(expectedMajor)
|
expect(major).toBe(expectedMajor)
|
||||||
if (semver.compareBuild(version, expectedMinVersion) < 0) {
|
if (semver.compareBuild(version, expectedMinVersion) < 0) {
|
||||||
throw new Error(`Version ${version} is older than ${expectedMinVersion}`)
|
throw new Error(`Version ${version} is older than ${expectedMinVersion}`)
|
||||||
@ -75,12 +63,7 @@ function upToBuild(expectedMinVersion: string): verifier {
|
|||||||
const expectedMinor = semver.minor(expectedMinVersion)
|
const expectedMinor = semver.minor(expectedMinVersion)
|
||||||
const expectedPatch = semver.patch(expectedMinVersion)
|
const expectedPatch = semver.patch(expectedMinVersion)
|
||||||
const atLeastVerifier = atLeast(expectedMinVersion)
|
const atLeastVerifier = atLeast(expectedMinVersion)
|
||||||
return function (
|
return function (version: string, major: number, minor: number, patch: number) {
|
||||||
version: string,
|
|
||||||
major: number,
|
|
||||||
minor: number,
|
|
||||||
patch: number
|
|
||||||
) {
|
|
||||||
atLeastVerifier(version, major, minor, patch)
|
atLeastVerifier(version, major, minor, patch)
|
||||||
expect(minor).toBe(expectedMinor)
|
expect(minor).toBe(expectedMinor)
|
||||||
expect(patch).toBe(expectedPatch)
|
expect(patch).toBe(expectedPatch)
|
||||||
@ -88,12 +71,7 @@ function upToBuild(expectedMinVersion: string): verifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function exactly(expectedVersion: string): verifier {
|
function exactly(expectedVersion: string): verifier {
|
||||||
return function (
|
return function (version: string, _major: number, _minor: number, _patch: number) {
|
||||||
version: string,
|
|
||||||
major: number,
|
|
||||||
minor: number,
|
|
||||||
patch: number
|
|
||||||
) {
|
|
||||||
if (semver.compareBuild(version, expectedVersion) != 0) {
|
if (semver.compareBuild(version, expectedVersion) != 0) {
|
||||||
throw new Error(`Expected version ${expectedVersion} but got ${version}`)
|
throw new Error(`Expected version ${expectedVersion} but got ${version}`)
|
||||||
}
|
}
|
||||||
@ -112,24 +90,16 @@ async function expectLatestToBe(pattern: string, verify: verifier) {
|
|||||||
async function expectLatestToFail(pattern: string) {
|
async function expectLatestToFail(pattern: string) {
|
||||||
try {
|
try {
|
||||||
const result = await liberica.findLatestLibericaJavaVersion(pattern)
|
const result = await liberica.findLatestLibericaJavaVersion(pattern)
|
||||||
throw new Error(
|
throw new Error(`findLatest(${pattern}) should have failed but returned ${result}`)
|
||||||
`findLatest(${pattern}) should have failed but returned ${result}`
|
|
||||||
)
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!(err instanceof Error)) {
|
if (!(err instanceof Error)) {
|
||||||
throw new Error(`Unexpected non-Error: ${err}`)
|
throw new Error(`Unexpected non-Error: ${err}`)
|
||||||
}
|
}
|
||||||
expect(err.message).toContain(
|
expect(err.message).toContain(`Unable to find the latest version for JDK${pattern}`)
|
||||||
`Unable to find the latest version for JDK${pattern}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function expectURL(
|
async function expectURL(javaVersion: string, javaPackage: string, expectedPrefix: string) {
|
||||||
javaVersion: string,
|
|
||||||
javaPackage: string,
|
|
||||||
expectedPrefix: string
|
|
||||||
) {
|
|
||||||
const url = await liberica.findLibericaURL(javaVersion, javaPackage)
|
const url = await liberica.findLibericaURL(javaVersion, javaPackage)
|
||||||
expect(url).toBeDefined()
|
expect(url).toBeDefined()
|
||||||
const parts = url.split('/')
|
const parts = url.split('/')
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import * as mandrel from '../src/mandrel'
|
import * as mandrel from '../src/mandrel'
|
||||||
import {expect, test} from '@jest/globals'
|
import { expect, test } from '@jest/globals'
|
||||||
import {getLatestRelease} from '../src/utils'
|
import { getLatestRelease } from '../src/utils'
|
||||||
|
|
||||||
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')
|
||||||
|
|
||||||
test('request invalid version/javaVersion combination', async () => {
|
test('request invalid version/javaVersion combination', async () => {
|
||||||
for (var combination of [
|
for (const combination of [
|
||||||
['mandrel-23.1.1.0-Final', '17'],
|
['mandrel-23.1.1.0-Final', '17'],
|
||||||
['mandrel-23.0.2.1-Final', '21']
|
['mandrel-23.0.2.1-Final', '21']
|
||||||
]) {
|
]) {
|
||||||
@ -16,7 +16,7 @@ test('request invalid version/javaVersion combination', async () => {
|
|||||||
await mandrel.setUpMandrel(combination[0], combination[1])
|
await mandrel.setUpMandrel(combination[0], combination[1])
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!(err instanceof Error)) {
|
if (!(err instanceof Error)) {
|
||||||
fail(`Unexpected non-Error: ${err}`)
|
throw new Error(`Unexpected non-Error: ${err}`)
|
||||||
}
|
}
|
||||||
error = err
|
error = err
|
||||||
}
|
}
|
||||||
@ -27,7 +27,7 @@ test('request invalid version/javaVersion combination', async () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
test('request invalid version', async () => {
|
test('request invalid version', async () => {
|
||||||
for (var combination of [
|
for (const combination of [
|
||||||
['mandrel-23.1.1.0', '21'],
|
['mandrel-23.1.1.0', '21'],
|
||||||
['mandrel-23.0.2.1', '17']
|
['mandrel-23.0.2.1', '17']
|
||||||
]) {
|
]) {
|
||||||
@ -36,7 +36,7 @@ test('request invalid version', async () => {
|
|||||||
await mandrel.setUpMandrel(combination[0], combination[1])
|
await mandrel.setUpMandrel(combination[0], combination[1])
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!(err instanceof Error)) {
|
if (!(err instanceof Error)) {
|
||||||
fail(`Unexpected non-Error: ${err}`)
|
throw new Error(`Unexpected non-Error: ${err}`)
|
||||||
}
|
}
|
||||||
error = err
|
error = err
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ test('find latest', async () => {
|
|||||||
|
|
||||||
test('get known latest Mandrel for specific JDK', async () => {
|
test('get known latest Mandrel for specific JDK', async () => {
|
||||||
// Test deprecated versions that won't get updates anymore
|
// Test deprecated versions that won't get updates anymore
|
||||||
for (var combination of [
|
for (const combination of [
|
||||||
['11', '22.2.0.0-Final'],
|
['11', '22.2.0.0-Final'],
|
||||||
['20', '23.0.1.2-Final']
|
['20', '23.0.1.2-Final']
|
||||||
]) {
|
]) {
|
||||||
@ -68,7 +68,7 @@ test('get known latest Mandrel for specific JDK', async () => {
|
|||||||
|
|
||||||
test('get latest Mandrel for specific JDK', async () => {
|
test('get latest Mandrel for specific JDK', async () => {
|
||||||
// Test supported versions
|
// Test supported versions
|
||||||
for (var javaVersion of ['17', '21']) {
|
for (const javaVersion of ['17', '21']) {
|
||||||
const latest = await mandrel.getLatestMandrelReleaseUrl(javaVersion)
|
const latest = await mandrel.getLatestMandrelReleaseUrl(javaVersion)
|
||||||
expect(latest).toContain(`mandrel-java${javaVersion}`)
|
expect(latest).toContain(`mandrel-java${javaVersion}`)
|
||||||
}
|
}
|
||||||
|
@ -1,36 +1,25 @@
|
|||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import {expect, test} from '@jest/globals'
|
import { expect, test } from '@jest/globals'
|
||||||
import {needsWindowsEnvironmentSetup} from '../src/msvc'
|
import { needsWindowsEnvironmentSetup } from '../src/msvc'
|
||||||
import {VERSION_DEV, VERSION_LATEST} from '../src/constants'
|
import { VERSION_DEV, VERSION_LATEST } 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')
|
||||||
|
|
||||||
test('decide whether Window env must be set up for GraalVM for JDK', async () => {
|
test('decide whether Window env must be set up for GraalVM for JDK', async () => {
|
||||||
for (var javaVersion of [
|
for (const javaVersion of ['17', '17.0.8', '17.0', '21', '22', '22-ea', '23-ea', VERSION_DEV]) {
|
||||||
'17',
|
|
||||||
'17.0.8',
|
|
||||||
'17.0',
|
|
||||||
'21',
|
|
||||||
'22',
|
|
||||||
'22-ea',
|
|
||||||
'23-ea',
|
|
||||||
VERSION_DEV
|
|
||||||
]) {
|
|
||||||
expect(needsWindowsEnvironmentSetup(javaVersion, '', true)).toBe(false)
|
expect(needsWindowsEnvironmentSetup(javaVersion, '', true)).toBe(false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
test('decide whether Window env must be set up for legacy GraalVM', async () => {
|
test('decide whether Window env must be set up for legacy GraalVM', async () => {
|
||||||
for (var combination of [
|
for (const combination of [
|
||||||
['7', '22.3.0'],
|
['7', '22.3.0'],
|
||||||
['17', '22.3'],
|
['17', '22.3'],
|
||||||
['7', '22.3'],
|
['7', '22.3'],
|
||||||
['7', VERSION_DEV],
|
['7', VERSION_DEV],
|
||||||
['17', VERSION_LATEST]
|
['17', VERSION_LATEST]
|
||||||
]) {
|
]) {
|
||||||
expect(
|
expect(needsWindowsEnvironmentSetup(combination[0], combination[1], false)).toBe(combination[1] !== VERSION_DEV)
|
||||||
needsWindowsEnvironmentSetup(combination[0], combination[1], false)
|
|
||||||
).toBe(combination[1] !== VERSION_DEV)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
294
__tests__/sbom.test.ts
Normal file
294
__tests__/sbom.test.ts
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
import * as c from '../src/constants'
|
||||||
|
import { setUpSBOMSupport, processSBOM } from '../src/features/sbom'
|
||||||
|
import * as core from '@actions/core'
|
||||||
|
import * as github from '@actions/github'
|
||||||
|
import * as glob from '@actions/glob'
|
||||||
|
import { join } from 'path'
|
||||||
|
import { tmpdir } from 'os'
|
||||||
|
import { mkdtempSync, writeFileSync, rmSync } from 'fs'
|
||||||
|
|
||||||
|
jest.mock('@actions/glob')
|
||||||
|
jest.mock('@actions/github', () => ({
|
||||||
|
getOctokit: jest.fn(() => ({
|
||||||
|
request: jest.fn().mockResolvedValue(undefined)
|
||||||
|
})),
|
||||||
|
context: {
|
||||||
|
repo: {
|
||||||
|
owner: 'test-owner',
|
||||||
|
repo: 'test-repo'
|
||||||
|
},
|
||||||
|
sha: 'test-sha',
|
||||||
|
ref: 'test-ref',
|
||||||
|
workflow: 'test-workflow',
|
||||||
|
job: 'test-job',
|
||||||
|
runId: '12345'
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
function mockFindSBOM(files: string[]) {
|
||||||
|
const mockCreate = jest.fn().mockResolvedValue({
|
||||||
|
glob: jest.fn().mockResolvedValue(files)
|
||||||
|
})
|
||||||
|
;(glob.create as jest.Mock).mockImplementation(mockCreate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mocks the GitHub dependency submission API return value
|
||||||
|
// 'undefined' is treated as a successful request
|
||||||
|
function mockGithubAPIReturnValue(returnValue: Error | undefined = undefined) {
|
||||||
|
const mockOctokit = {
|
||||||
|
request:
|
||||||
|
returnValue === undefined ? jest.fn().mockResolvedValue(returnValue) : jest.fn().mockRejectedValue(returnValue)
|
||||||
|
}
|
||||||
|
;(github.getOctokit as jest.Mock).mockReturnValue(mockOctokit)
|
||||||
|
return mockOctokit
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('sbom feature', () => {
|
||||||
|
let spyInfo: jest.SpyInstance<void, Parameters<typeof core.info>>
|
||||||
|
let spyWarning: jest.SpyInstance<void, Parameters<typeof core.warning>>
|
||||||
|
let spyExportVariable: jest.SpyInstance<void, Parameters<typeof core.exportVariable>>
|
||||||
|
let workspace: string
|
||||||
|
let originalEnv: NodeJS.ProcessEnv
|
||||||
|
const javaVersion = '24.0.0'
|
||||||
|
const distribution = c.DISTRIBUTION_GRAALVM
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
originalEnv = process.env
|
||||||
|
|
||||||
|
process.env = {
|
||||||
|
...process.env,
|
||||||
|
GITHUB_REPOSITORY: 'test-owner/test-repo',
|
||||||
|
GITHUB_TOKEN: 'fake-token'
|
||||||
|
}
|
||||||
|
|
||||||
|
workspace = mkdtempSync(join(tmpdir(), 'setup-graalvm-sbom-'))
|
||||||
|
mockGithubAPIReturnValue()
|
||||||
|
|
||||||
|
spyInfo = jest.spyOn(core, 'info').mockImplementation(() => null)
|
||||||
|
spyWarning = jest.spyOn(core, 'warning').mockImplementation(() => null)
|
||||||
|
spyExportVariable = jest.spyOn(core, 'exportVariable').mockImplementation(() => null)
|
||||||
|
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
|
||||||
|
if (name === 'native-image-enable-sbom') {
|
||||||
|
return 'true'
|
||||||
|
}
|
||||||
|
if (name === 'github-token') {
|
||||||
|
return 'fake-token'
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
process.env = originalEnv
|
||||||
|
jest.clearAllMocks()
|
||||||
|
spyInfo.mockRestore()
|
||||||
|
spyWarning.mockRestore()
|
||||||
|
spyExportVariable.mockRestore()
|
||||||
|
rmSync(workspace, { recursive: true, force: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('setup', () => {
|
||||||
|
it('should throw an error when the distribution is not Oracle GraalVM', () => {
|
||||||
|
const not_supported_distributions = [
|
||||||
|
c.DISTRIBUTION_GRAALVM_COMMUNITY,
|
||||||
|
c.DISTRIBUTION_MANDREL,
|
||||||
|
c.DISTRIBUTION_LIBERICA,
|
||||||
|
''
|
||||||
|
]
|
||||||
|
for (const distribution of not_supported_distributions) {
|
||||||
|
expect(() => setUpSBOMSupport(javaVersion, distribution)).toThrow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should throw an error when the java-version is not supported', () => {
|
||||||
|
const not_supported_versions = ['23', '23-ea', '21.0.3', 'dev', '17', '']
|
||||||
|
for (const version of not_supported_versions) {
|
||||||
|
expect(() => setUpSBOMSupport(version, distribution)).toThrow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not throw an error when the java-version is supported', () => {
|
||||||
|
const supported_versions = ['24', '24-ea', '24.0.2', 'latest-ea']
|
||||||
|
for (const version of supported_versions) {
|
||||||
|
expect(() => setUpSBOMSupport(version, distribution)).not.toThrow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should set the SBOM option when activated', () => {
|
||||||
|
setUpSBOMSupport(javaVersion, distribution)
|
||||||
|
|
||||||
|
expect(spyExportVariable).toHaveBeenCalledWith(
|
||||||
|
c.NATIVE_IMAGE_OPTIONS_ENV,
|
||||||
|
expect.stringContaining('--enable-sbom=export')
|
||||||
|
)
|
||||||
|
expect(spyInfo).toHaveBeenCalledWith('Enabled SBOM generation for Native Image build')
|
||||||
|
expect(spyWarning).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not set the SBOM option when not activated', () => {
|
||||||
|
jest.spyOn(core, 'getInput').mockReturnValue('false')
|
||||||
|
setUpSBOMSupport(javaVersion, distribution)
|
||||||
|
|
||||||
|
expect(spyExportVariable).not.toHaveBeenCalled()
|
||||||
|
expect(spyInfo).not.toHaveBeenCalled()
|
||||||
|
expect(spyWarning).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('process', () => {
|
||||||
|
async function setUpAndProcessSBOM(sbom: object): Promise<void> {
|
||||||
|
setUpSBOMSupport(javaVersion, distribution)
|
||||||
|
spyInfo.mockClear()
|
||||||
|
|
||||||
|
// Mock 'native-image' invocation by creating the SBOM file
|
||||||
|
const sbomPath = join(workspace, 'test.sbom.json')
|
||||||
|
writeFileSync(sbomPath, JSON.stringify(sbom, null, 2))
|
||||||
|
|
||||||
|
mockFindSBOM([sbomPath])
|
||||||
|
jest.spyOn(core, 'getState').mockReturnValue(javaVersion)
|
||||||
|
|
||||||
|
await processSBOM()
|
||||||
|
}
|
||||||
|
|
||||||
|
const sampleSBOM = {
|
||||||
|
bomFormat: 'CycloneDX',
|
||||||
|
specVersion: '1.5',
|
||||||
|
version: 1,
|
||||||
|
serialNumber: 'urn:uuid:52c977f8-6d04-3c07-8826-597a036d61a6',
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
type: 'library',
|
||||||
|
group: 'org.json',
|
||||||
|
name: 'json',
|
||||||
|
version: '20241224',
|
||||||
|
purl: 'pkg:maven/org.json/json@20241224',
|
||||||
|
'bom-ref': 'pkg:maven/org.json/json@20241224',
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
name: 'syft:cpe23',
|
||||||
|
value: 'cpe:2.3:a:json:json:20241224:*:*:*:*:*:*:*'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'library',
|
||||||
|
group: 'com.oracle',
|
||||||
|
name: 'main-test-app',
|
||||||
|
version: '1.0-SNAPSHOT',
|
||||||
|
purl: 'pkg:maven/com.oracle/main-test-app@1.0-SNAPSHOT',
|
||||||
|
'bom-ref': 'pkg:maven/com.oracle/main-test-app@1.0-SNAPSHOT'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
dependencies: [
|
||||||
|
{
|
||||||
|
ref: 'pkg:maven/com.oracle/main-test-app@1.0-SNAPSHOT',
|
||||||
|
dependsOn: ['pkg:maven/org.json/json@20241224']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ref: 'pkg:maven/org.json/json@20241224',
|
||||||
|
dependsOn: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should throw an error if setUpSBOMSupport was not called before processSBOM', async () => {
|
||||||
|
await expect(processSBOM()).rejects.toThrow('setUpSBOMSupport must be called before processSBOM')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should process SBOM and display components', async () => {
|
||||||
|
await setUpAndProcessSBOM(sampleSBOM)
|
||||||
|
|
||||||
|
expect(spyInfo).toHaveBeenCalledWith('Found SBOM: ' + join(workspace, 'test.sbom.json'))
|
||||||
|
expect(spyInfo).toHaveBeenCalledWith('=== SBOM Content ===')
|
||||||
|
expect(spyInfo).toHaveBeenCalledWith('- pkg:maven/org.json/json@20241224')
|
||||||
|
expect(spyInfo).toHaveBeenCalledWith('- pkg:maven/com.oracle/main-test-app@1.0-SNAPSHOT')
|
||||||
|
expect(spyInfo).toHaveBeenCalledWith(' depends on: pkg:maven/org.json/json@20241224')
|
||||||
|
expect(spyWarning).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle components without purl', async () => {
|
||||||
|
const sbomWithoutPurl = {
|
||||||
|
...sampleSBOM,
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
type: 'library',
|
||||||
|
name: 'no-purl-package',
|
||||||
|
version: '1.0.0',
|
||||||
|
'bom-ref': 'no-purl-package@1.0.0'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
await setUpAndProcessSBOM(sbomWithoutPurl)
|
||||||
|
|
||||||
|
expect(spyInfo).toHaveBeenCalledWith('=== SBOM Content ===')
|
||||||
|
expect(spyInfo).toHaveBeenCalledWith('- no-purl-package@1.0.0')
|
||||||
|
expect(spyWarning).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle missing SBOM file', async () => {
|
||||||
|
setUpSBOMSupport(javaVersion, distribution)
|
||||||
|
spyInfo.mockClear()
|
||||||
|
|
||||||
|
mockFindSBOM([])
|
||||||
|
|
||||||
|
await expect(processSBOM()).rejects.toBeInstanceOf(Error)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should throw when JSON contains an invalid SBOM', async () => {
|
||||||
|
const invalidSBOM = {
|
||||||
|
'out-of-spec-field': {}
|
||||||
|
}
|
||||||
|
let error
|
||||||
|
try {
|
||||||
|
await setUpAndProcessSBOM(invalidSBOM)
|
||||||
|
throw new Error('Expected an error since invalid JSON was passed')
|
||||||
|
} catch (e) {
|
||||||
|
error = e
|
||||||
|
} finally {
|
||||||
|
expect(error).toBeInstanceOf(Error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should submit dependencies when processing valid SBOM', async () => {
|
||||||
|
const mockOctokit = mockGithubAPIReturnValue(undefined)
|
||||||
|
await setUpAndProcessSBOM(sampleSBOM)
|
||||||
|
|
||||||
|
expect(mockOctokit.request).toHaveBeenCalledWith(
|
||||||
|
'POST /repos/{owner}/{repo}/dependency-graph/snapshots',
|
||||||
|
expect.objectContaining({
|
||||||
|
owner: 'test-owner',
|
||||||
|
repo: 'test-repo',
|
||||||
|
version: expect.any(Number),
|
||||||
|
sha: 'test-sha',
|
||||||
|
ref: 'test-ref',
|
||||||
|
job: expect.objectContaining({
|
||||||
|
correlator: 'test-workflow_test-job',
|
||||||
|
id: '12345'
|
||||||
|
}),
|
||||||
|
manifests: expect.objectContaining({
|
||||||
|
'test.sbom.json': expect.objectContaining({
|
||||||
|
name: 'test.sbom.json',
|
||||||
|
resolved: expect.objectContaining({
|
||||||
|
json: expect.objectContaining({
|
||||||
|
package_url: 'pkg:maven/org.json/json@20241224',
|
||||||
|
dependencies: []
|
||||||
|
}),
|
||||||
|
'main-test-app': expect.objectContaining({
|
||||||
|
package_url: 'pkg:maven/com.oracle/main-test-app@1.0-SNAPSHOT',
|
||||||
|
dependencies: ['pkg:maven/org.json/json@20241224']
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
expect(spyInfo).toHaveBeenCalledWith('Dependency snapshot submitted successfully.')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle GitHub API submission errors gracefully', async () => {
|
||||||
|
mockGithubAPIReturnValue(new Error('API submission failed'))
|
||||||
|
|
||||||
|
await expect(setUpAndProcessSBOM(sampleSBOM)).rejects.toBeInstanceOf(Error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
54
__tests__/sbom/main-test-app/pom.xml
Normal file
54
__tests__/sbom/main-test-app/pom.xml
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.oracle</groupId>
|
||||||
|
<artifactId>main-test-app</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.json</groupId>
|
||||||
|
<artifactId>json</artifactId>
|
||||||
|
<version>20241224</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>native</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.graalvm.buildtools</groupId>
|
||||||
|
<artifactId>native-maven-plugin</artifactId>
|
||||||
|
<version>0.10.3</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>compile-no-fork</goal>
|
||||||
|
</goals>
|
||||||
|
<phase>package</phase>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<mainClass>com.oracle.sbom.SBOMTestApplication</mainClass>
|
||||||
|
<buildArgs>
|
||||||
|
<buildArg>-Ob</buildArg>
|
||||||
|
<buildArg>--no-fallback</buildArg>
|
||||||
|
<buildArg>-H:+ReportExceptionStackTraces</buildArg>
|
||||||
|
</buildArgs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</project>
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.oracle.sbom;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
public class SBOMTestApplication {
|
||||||
|
public static void main(String argv[]) {
|
||||||
|
JSONObject jo = new JSONObject();
|
||||||
|
jo.put("lorem", "ipsum");
|
||||||
|
jo.put("dolor", "sit amet");
|
||||||
|
System.out.println(jo);
|
||||||
|
}
|
||||||
|
}
|
14
__tests__/sbom/main-test-app/verify-sbom.cmd
Normal file
14
__tests__/sbom/main-test-app/verify-sbom.cmd
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
@echo off
|
||||||
|
set "SCRIPT_DIR=%~dp0"
|
||||||
|
|
||||||
|
for %%p in (
|
||||||
|
"\"pkg:maven/org.json/json@20241224\""
|
||||||
|
"\"main-test-app\""
|
||||||
|
"\"svm\""
|
||||||
|
"\"nativeimage\""
|
||||||
|
) do (
|
||||||
|
echo Checking for %%p
|
||||||
|
findstr /c:%%p "%SCRIPT_DIR%target\main-test-app.sbom.json" || exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo SBOM was successfully generated and contained the expected components
|
19
__tests__/sbom/main-test-app/verify-sbom.sh
Normal file
19
__tests__/sbom/main-test-app/verify-sbom.sh
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
required_patterns=(
|
||||||
|
'"pkg:maven/org.json/json@20241224"'
|
||||||
|
'"main-test-app"'
|
||||||
|
'"svm"'
|
||||||
|
'"nativeimage"'
|
||||||
|
)
|
||||||
|
|
||||||
|
for pattern in "${required_patterns[@]}"; do
|
||||||
|
echo "Checking for $pattern"
|
||||||
|
if ! grep -q "$pattern" "$script_dir/target/main-test-app.sbom.json"; then
|
||||||
|
echo "Pattern not found: $pattern"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "SBOM was successfully generated and contained the expected components"
|
@ -1,9 +1,8 @@
|
|||||||
import * as path from 'path'
|
import { expect, test } from '@jest/globals'
|
||||||
import {expect, test} from '@jest/globals'
|
import { toSemVer } from '../src/utils'
|
||||||
import {toSemVer} from '../src/utils'
|
|
||||||
|
|
||||||
test('convert version', async () => {
|
test('convert version', async () => {
|
||||||
for (var inputAndExpectedOutput of [
|
for (const inputAndExpectedOutput of [
|
||||||
['22', '22.0.0'],
|
['22', '22.0.0'],
|
||||||
['22.0', '22.0.0'],
|
['22.0', '22.0.0'],
|
||||||
['22.0.0', '22.0.0'],
|
['22.0.0', '22.0.0'],
|
||||||
@ -17,13 +16,13 @@ test('convert version', async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('convert invalid version', async () => {
|
test('convert invalid version', async () => {
|
||||||
for (var input of ['dev', 'abc', 'a.b.c']) {
|
for (const input of ['dev', 'abc', 'a.b.c']) {
|
||||||
let error = new Error('unexpected')
|
let error = new Error('unexpected')
|
||||||
try {
|
try {
|
||||||
toSemVer(input)
|
toSemVer(input)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!(err instanceof Error)) {
|
if (!(err instanceof Error)) {
|
||||||
fail(`Unexpected non-Error: ${err}`)
|
throw new Error(`Unexpected non-Error: ${err}`)
|
||||||
}
|
}
|
||||||
error = err
|
error = err
|
||||||
}
|
}
|
||||||
|
17
action.yml
17
action.yml
@ -2,7 +2,7 @@ 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:
|
||||||
@ -22,7 +22,8 @@ inputs:
|
|||||||
default: ''
|
default: ''
|
||||||
github-token:
|
github-token:
|
||||||
required: false
|
required: false
|
||||||
description: 'Set it to secrets.GITHUB_TOKEN to increase rate limits when accessing the GitHub API. Defaults to github.token.'
|
description:
|
||||||
|
'Set it to secrets.GITHUB_TOKEN to increase rate limits when accessing the GitHub API. Defaults to github.token.'
|
||||||
default: ${{ github.token }}
|
default: ${{ github.token }}
|
||||||
set-java-home:
|
set-java-home:
|
||||||
required: false
|
required: false
|
||||||
@ -49,7 +50,14 @@ inputs:
|
|||||||
default: 'false'
|
default: 'false'
|
||||||
native-image-pr-reports-update-existing:
|
native-image-pr-reports-update-existing:
|
||||||
required: false
|
required: false
|
||||||
description: 'Instead of posting another comment, update an existing PR comment with the latest Native Image build report.'
|
description:
|
||||||
|
'Instead of posting another comment, update an existing PR comment with the latest Native Image build report.'
|
||||||
|
default: 'false'
|
||||||
|
native-image-enable-sbom:
|
||||||
|
required: false
|
||||||
|
description:
|
||||||
|
'Automatically generate an SBOM and submit it to the GitHub dependency submission API for vulnerability and
|
||||||
|
dependency tracking.'
|
||||||
default: 'false'
|
default: 'false'
|
||||||
version:
|
version:
|
||||||
required: false
|
required: false
|
||||||
@ -57,7 +65,8 @@ inputs:
|
|||||||
default: ''
|
default: ''
|
||||||
gds-token:
|
gds-token:
|
||||||
required: false
|
required: false
|
||||||
description: 'Download token for the GraalVM Download Service. If provided, the action will set up GraalVM Enterprise Edition.'
|
description:
|
||||||
|
'Download token for the GraalVM Download Service. If provided, the action will set up GraalVM Enterprise Edition.'
|
||||||
outputs:
|
outputs:
|
||||||
cache-hit:
|
cache-hit:
|
||||||
description: 'A boolean value to indicate an exact match was found for the primary key'
|
description: 'A boolean value to indicate an exact match was found for the primary key'
|
||||||
|
75785
dist/cleanup/index.js
generated
vendored
75785
dist/cleanup/index.js
generated
vendored
File diff suppressed because one or more lines are too long
78711
dist/main/index.js
generated
vendored
78711
dist/main/index.js
generated
vendored
File diff suppressed because one or more lines are too long
82
eslint.config.mjs
Normal file
82
eslint.config.mjs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
// See: https://eslint.org/docs/latest/use/configure/configuration-files
|
||||||
|
|
||||||
|
import { fixupPluginRules } from '@eslint/compat'
|
||||||
|
import { FlatCompat } from '@eslint/eslintrc'
|
||||||
|
import js from '@eslint/js'
|
||||||
|
import typescriptEslint from '@typescript-eslint/eslint-plugin'
|
||||||
|
import tsParser from '@typescript-eslint/parser'
|
||||||
|
import _import from 'eslint-plugin-import'
|
||||||
|
import jest from 'eslint-plugin-jest'
|
||||||
|
import prettier from 'eslint-plugin-prettier'
|
||||||
|
import globals from 'globals'
|
||||||
|
import path from 'node:path'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url)
|
||||||
|
const __dirname = path.dirname(__filename)
|
||||||
|
const compat = new FlatCompat({
|
||||||
|
baseDirectory: __dirname,
|
||||||
|
recommendedConfig: js.configs.recommended,
|
||||||
|
allConfig: js.configs.all
|
||||||
|
})
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
ignores: ['**/coverage', '**/dist', '**/linter', '**/node_modules']
|
||||||
|
},
|
||||||
|
...compat.extends(
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:@typescript-eslint/eslint-recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'plugin:jest/recommended',
|
||||||
|
'plugin:prettier/recommended'
|
||||||
|
),
|
||||||
|
{
|
||||||
|
plugins: {
|
||||||
|
import: fixupPluginRules(_import),
|
||||||
|
jest,
|
||||||
|
prettier,
|
||||||
|
'@typescript-eslint': typescriptEslint
|
||||||
|
},
|
||||||
|
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.node,
|
||||||
|
...globals.jest,
|
||||||
|
Atomics: 'readonly',
|
||||||
|
SharedArrayBuffer: 'readonly'
|
||||||
|
},
|
||||||
|
|
||||||
|
parser: tsParser,
|
||||||
|
ecmaVersion: 2023,
|
||||||
|
sourceType: 'module',
|
||||||
|
|
||||||
|
parserOptions: {
|
||||||
|
project: ['tsconfig.eslint.json'],
|
||||||
|
tsconfigRootDir: '.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
settings: {
|
||||||
|
'import/resolver': {
|
||||||
|
typescript: {
|
||||||
|
alwaysTryTypes: true,
|
||||||
|
project: 'tsconfig.eslint.json'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
camelcase: 'off',
|
||||||
|
'eslint-comments/no-use': 'off',
|
||||||
|
'eslint-comments/no-unused-disable': 'off',
|
||||||
|
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||||
|
'i18n-text/no-en': 'off',
|
||||||
|
'import/no-namespace': 'off',
|
||||||
|
'no-console': 'off',
|
||||||
|
'no-shadow': 'off',
|
||||||
|
'no-unused-vars': 'off',
|
||||||
|
'prettier/prettier': 'error'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
@ -1,9 +1,14 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
clearMocks: true,
|
clearMocks: true,
|
||||||
|
collectCoverage: true,
|
||||||
|
collectCoverageFrom: ['./src/**'],
|
||||||
|
coverageDirectory: './coverage',
|
||||||
|
coveragePathIgnorePatterns: ['/node_modules/', '/dist/'],
|
||||||
|
coverageReporters: ['json-summary', 'text', 'lcov'],
|
||||||
moduleFileExtensions: ['js', 'ts'],
|
moduleFileExtensions: ['js', 'ts'],
|
||||||
testMatch: ['**/*.test.ts'],
|
testMatch: ['**/*.test.ts'],
|
||||||
transform: {
|
transform: {
|
||||||
'^.+\\.ts$': 'ts-jest'
|
'^.+\\.ts$': 'ts-jest'
|
||||||
},
|
},
|
||||||
verbose: true
|
verbose: true
|
||||||
}
|
}
|
||||||
|
5787
package-lock.json
generated
5787
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
92
package.json
92
package.json
@ -1,63 +1,75 @@
|
|||||||
{
|
{
|
||||||
"name": "setup-graalvm",
|
"name": "setup-graalvm",
|
||||||
"version": "1.2.4",
|
"author": "GraalVM Community",
|
||||||
"private": true,
|
|
||||||
"description": "GitHub Action for GraalVM",
|
"description": "GitHub Action for GraalVM",
|
||||||
"main": "lib/main.js",
|
"version": "1.3.3",
|
||||||
"scripts": {
|
"private": true,
|
||||||
"build": "tsc",
|
|
||||||
"format": "prettier --write '**/*.ts'",
|
|
||||||
"format-check": "prettier --check '**/*.ts'",
|
|
||||||
"lint": "eslint src/**/*.ts",
|
|
||||||
"package": "ncc build -o dist/main src/main.ts && ncc build -o dist/cleanup src/cleanup.ts",
|
|
||||||
"test": "jest",
|
|
||||||
"all-but-test": "npm run build && npm run format && npm run lint && npm run package",
|
|
||||||
"all": "npm run all-but-test && npm test"
|
|
||||||
},
|
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/graalvm/setup-graalvm.git"
|
"url": "git+https://github.com/graalvm/setup-graalvm.git"
|
||||||
},
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/graalvm/setup-graalvm/issues"
|
||||||
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"graalvm",
|
"graalvm",
|
||||||
"native image",
|
"native image",
|
||||||
"actions",
|
"actions",
|
||||||
"setup"
|
"setup"
|
||||||
],
|
],
|
||||||
"author": "GraalVM Community",
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"bundle": "npm run format:write && npm run package",
|
||||||
|
"format:write": "npx prettier --write .",
|
||||||
|
"format:check": "npx prettier --check .",
|
||||||
|
"lint": "npx eslint .",
|
||||||
|
"package": "npm run package:main && npm run package:cleanup",
|
||||||
|
"package:main": "npx ncc build src/main.ts -o dist/main",
|
||||||
|
"package:cleanup": "npx ncc build src/cleanup.ts -o dist/cleanup",
|
||||||
|
"test": "npx jest",
|
||||||
|
"all": "npm run format:write && npm run lint && npm run test && npm run package"
|
||||||
|
},
|
||||||
"license": "UPL",
|
"license": "UPL",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/cache": "^3.2.4",
|
"@actions/cache": "^4.0.3",
|
||||||
"@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.1",
|
||||||
"@actions/glob": "^0.4.0",
|
"@actions/glob": "^0.5.0",
|
||||||
"@actions/http-client": "^2.2.1",
|
"@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.6.0",
|
"@octokit/types": "^14.1.0",
|
||||||
"semver": "^7.6.0",
|
"@github/dependency-submission-toolkit": "^2.0.5",
|
||||||
"uuid": "^9.0.1"
|
"semver": "^7.7.2",
|
||||||
|
"uuid": "^11.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^29.5.12",
|
"@eslint/compat": "^1.3.1",
|
||||||
"@types/node": "^20.11.28",
|
"@types/jest": "^29.5.14",
|
||||||
"@types/semver": "^7.5.8",
|
"@types/node": "^20.19.4",
|
||||||
"@types/uuid": "^9.0.8",
|
"@types/semver": "^7.7.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.2.0",
|
"@types/uuid": "^10.0.0",
|
||||||
"@typescript-eslint/parser": "^7.2.0",
|
"@typescript-eslint/eslint-plugin": "^8.35.1",
|
||||||
"@vercel/ncc": "^0.38.1",
|
"@typescript-eslint/parser": "^8.31.1",
|
||||||
"eslint": "^8.57.0",
|
"@vercel/ncc": "^0.38.3",
|
||||||
"eslint-plugin-github": "^4.10.2",
|
"eslint": "^9.30.1",
|
||||||
"eslint-plugin-jest": "^27.9.0",
|
"eslint-config-prettier": "^10.1.5",
|
||||||
"eslint-plugin-jsonc": "^2.14.0",
|
"eslint-import-resolver-typescript": "^4.4.4",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-import": "^2.32.0",
|
||||||
|
"eslint-plugin-jest": "^29.0.1",
|
||||||
|
"eslint-plugin-jsonc": "^2.20.1",
|
||||||
|
"eslint-plugin-node": "^11.1.0",
|
||||||
|
"eslint-plugin-prettier": "^5.5.1",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.6.2",
|
||||||
"prettier-eslint": "^16.3.0",
|
"prettier-eslint": "^16.4.2",
|
||||||
"ts-jest": "^29.1.2",
|
"ts-jest": "^29.4.0",
|
||||||
"typescript": "^5.3.3"
|
"ts-node": "^10.9.2",
|
||||||
|
"typescript": "^5.8.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,9 @@
|
|||||||
|
|
||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import * as constants from './constants'
|
import * as constants from './constants'
|
||||||
import {save} from './features/cache'
|
import { save } from './features/cache'
|
||||||
import {generateReports} from './features/reports'
|
import { generateReports } from './features/reports'
|
||||||
|
import { processSBOM } from './features/sbom'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check given input and run a save process for the specified package manager
|
* Check given input and run a save process for the specified package manager
|
||||||
@ -45,10 +46,9 @@ async function saveCache(): Promise<void> {
|
|||||||
* @returns Promise that will ignore error reported by the given promise
|
* @returns Promise that will ignore error reported by the given promise
|
||||||
*/
|
*/
|
||||||
async function ignoreErrors(promise: Promise<void>): Promise<unknown> {
|
async function ignoreErrors(promise: Promise<void>): Promise<unknown> {
|
||||||
/* eslint-disable github/no-then */
|
return new Promise((resolve) => {
|
||||||
return new Promise(resolve => {
|
|
||||||
promise
|
promise
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
core.warning(error)
|
core.warning(error)
|
||||||
resolve(void 0)
|
resolve(void 0)
|
||||||
})
|
})
|
||||||
@ -58,12 +58,8 @@ async function ignoreErrors(promise: Promise<void>): Promise<unknown> {
|
|||||||
|
|
||||||
export async function run(): Promise<void> {
|
export async function run(): Promise<void> {
|
||||||
await ignoreErrors(generateReports())
|
await ignoreErrors(generateReports())
|
||||||
|
await ignoreErrors(processSBOM())
|
||||||
await ignoreErrors(saveCache())
|
await ignoreErrors(saveCache())
|
||||||
}
|
}
|
||||||
|
|
||||||
if (require.main === module) {
|
run()
|
||||||
run()
|
|
||||||
} else {
|
|
||||||
// https://nodejs.org/api/modules.html#modules_accessing_the_main_module
|
|
||||||
core.info('the script is loaded as a module, so skipping the execution')
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import * as otypes from '@octokit/types'
|
import * as otypes from '@octokit/types'
|
||||||
|
|
||||||
export const ACTION_VERSION = '1.2.4'
|
export const ACTION_VERSION = '1.3.3'
|
||||||
|
|
||||||
export const INPUT_VERSION = 'version'
|
export const INPUT_VERSION = 'version'
|
||||||
export const INPUT_GDS_TOKEN = 'gds-token'
|
export const INPUT_GDS_TOKEN = 'gds-token'
|
||||||
@ -14,6 +14,8 @@ export const INPUT_CACHE = 'cache'
|
|||||||
export const INPUT_CHECK_FOR_UPDATES = 'check-for-updates'
|
export const INPUT_CHECK_FOR_UPDATES = 'check-for-updates'
|
||||||
export const INPUT_NI_MUSL = 'native-image-musl'
|
export const INPUT_NI_MUSL = 'native-image-musl'
|
||||||
|
|
||||||
|
export const NATIVE_IMAGE_OPTIONS_ENV = 'NATIVE_IMAGE_OPTIONS'
|
||||||
|
|
||||||
export const IS_LINUX = process.platform === 'linux'
|
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'
|
||||||
@ -46,23 +48,18 @@ 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 =
|
export const ERROR_REQUEST = 'Please file an issue at: https://github.com/graalvm/setup-graalvm/issues.'
|
||||||
'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.'
|
||||||
|
|
||||||
export type LatestReleaseResponse =
|
export type LatestReleaseResponse = otypes.Endpoints['GET /repos/{owner}/{repo}/releases/latest']['response']
|
||||||
otypes.Endpoints['GET /repos/{owner}/{repo}/releases/latest']['response']
|
|
||||||
|
|
||||||
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 =
|
export type ReleasesResponse = otypes.Endpoints['GET /repos/{owner}/{repo}/releases']['response']
|
||||||
otypes.Endpoints['GET /repos/{owner}/{repo}/releases']['response']
|
|
||||||
|
|
||||||
export type ContentsResponse =
|
export type ContentsResponse = otypes.Endpoints['GET /repos/{owner}/{repo}/contents/{path}']['response']
|
||||||
otypes.Endpoints['GET /repos/{owner}/{repo}/contents/{path}']['response']
|
|
||||||
|
|
||||||
export interface OracleGraalVMEAFile {
|
export interface OracleGraalVMEAFile {
|
||||||
filename: string
|
filename: string
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import {GRAALVM_PLATFORM} from './constants'
|
import { GRAALVM_PLATFORM } from './constants'
|
||||||
import {exec} from './utils'
|
import { exec } from './utils'
|
||||||
|
|
||||||
const APT_GET_INSTALL_BASE = 'sudo apt-get -y --no-upgrade install'
|
const APT_GET_INSTALL_BASE = 'sudo apt-get -y --no-upgrade install'
|
||||||
const COMPONENT_TO_DEPS = new Map<string, Map<string, string>>([
|
const COMPONENT_TO_DEPS = new Map<string, Map<string, string>>([
|
||||||
@ -9,10 +9,7 @@ const COMPONENT_TO_DEPS = new Map<string, Map<string, string>>([
|
|||||||
new Map<string, string>([
|
new Map<string, string>([
|
||||||
['nodejs', `${APT_GET_INSTALL_BASE} g++ make`],
|
['nodejs', `${APT_GET_INSTALL_BASE} g++ make`],
|
||||||
['ruby', `${APT_GET_INSTALL_BASE} make gcc libssl-dev libz-dev`],
|
['ruby', `${APT_GET_INSTALL_BASE} make gcc libssl-dev libz-dev`],
|
||||||
[
|
['R', `${APT_GET_INSTALL_BASE} libgomp1 build-essential gfortran libxml2 libc++-dev`]
|
||||||
'R',
|
|
||||||
`${APT_GET_INSTALL_BASE} libgomp1 build-essential gfortran libxml2 libc++-dev`
|
|
||||||
]
|
|
||||||
])
|
])
|
||||||
],
|
],
|
||||||
['darwin', new Map<string, string>([['ruby', 'brew install openssl']])]
|
['darwin', new Map<string, string>([['ruby', 'brew install openssl']])]
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
* @fileoverview this file provides methods handling dependency cache
|
* @fileoverview this file provides methods handling dependency cache
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {join} from 'path'
|
import { join } from 'path'
|
||||||
import os from 'os'
|
import os from 'os'
|
||||||
import * as cache from '@actions/cache'
|
import * as cache from '@actions/cache'
|
||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
@ -53,17 +53,9 @@ const supportedPackageManager: PackageManager[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'gradle',
|
id: 'gradle',
|
||||||
path: [
|
path: [join(os.homedir(), '.gradle', 'caches'), join(os.homedir(), '.gradle', 'wrapper')],
|
||||||
join(os.homedir(), '.gradle', 'caches'),
|
|
||||||
join(os.homedir(), '.gradle', 'wrapper')
|
|
||||||
],
|
|
||||||
// https://github.com/actions/cache/blob/0638051e9af2c23d10bb70fa9beffcad6cff9ce3/examples.md#java---gradle
|
// https://github.com/actions/cache/blob/0638051e9af2c23d10bb70fa9beffcad6cff9ce3/examples.md#java---gradle
|
||||||
pattern: [
|
pattern: ['**/*.gradle*', '**/gradle-wrapper.properties', 'buildSrc/**/Versions.kt', 'buildSrc/**/Dependencies.kt']
|
||||||
'**/*.gradle*',
|
|
||||||
'**/gradle-wrapper.properties',
|
|
||||||
'buildSrc/**/Versions.kt',
|
|
||||||
'buildSrc/**/Dependencies.kt'
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'sbt',
|
id: 'sbt',
|
||||||
@ -76,23 +68,18 @@ const supportedPackageManager: PackageManager[] = [
|
|||||||
`!${join(os.homedir(), '.sbt', '*.lock')}`,
|
`!${join(os.homedir(), '.sbt', '*.lock')}`,
|
||||||
`!${join(os.homedir(), '**', 'ivydata-*.properties')}`
|
`!${join(os.homedir(), '**', 'ivydata-*.properties')}`
|
||||||
],
|
],
|
||||||
pattern: [
|
pattern: ['**/*.sbt', '**/project/build.properties', '**/project/**.{scala,sbt}']
|
||||||
'**/*.sbt',
|
|
||||||
'**/project/build.properties',
|
|
||||||
'**/project/**.{scala,sbt}'
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
function getCoursierCachePath(): string {
|
function getCoursierCachePath(): string {
|
||||||
if (os.type() === 'Linux') return join(os.homedir(), '.cache', 'coursier')
|
if (os.type() === 'Linux') return join(os.homedir(), '.cache', 'coursier')
|
||||||
if (os.type() === 'Darwin')
|
if (os.type() === 'Darwin') return join(os.homedir(), 'Library', 'Caches', 'Coursier')
|
||||||
return join(os.homedir(), 'Library', 'Caches', 'Coursier')
|
|
||||||
return join(os.homedir(), 'AppData', 'Local', 'Coursier', 'Cache')
|
return join(os.homedir(), 'AppData', 'Local', 'Coursier', 'Cache')
|
||||||
}
|
}
|
||||||
|
|
||||||
function findPackageManager(id: string): PackageManager {
|
function findPackageManager(id: string): PackageManager {
|
||||||
const packageManager = supportedPackageManager.find(pm => pm.id === id)
|
const packageManager = supportedPackageManager.find((pm) => pm.id === id)
|
||||||
if (packageManager === undefined) {
|
if (packageManager === undefined) {
|
||||||
throw new Error(`unknown package manager specified: ${id}`)
|
throw new Error(`unknown package manager specified: ${id}`)
|
||||||
}
|
}
|
||||||
@ -105,9 +92,7 @@ function findPackageManager(id: string): PackageManager {
|
|||||||
* If there is no file matched to {@link PackageManager.path}, the generated key ends with a dash (-).
|
* If there is no file matched to {@link PackageManager.path}, the generated key ends with a dash (-).
|
||||||
* @see {@link https://docs.github.com/en/actions/guides/caching-dependencies-to-speed-up-workflows#matching-a-cache-key|spec of cache key}
|
* @see {@link https://docs.github.com/en/actions/guides/caching-dependencies-to-speed-up-workflows#matching-a-cache-key|spec of cache key}
|
||||||
*/
|
*/
|
||||||
async function computeCacheKey(
|
async function computeCacheKey(packageManager: PackageManager): Promise<string> {
|
||||||
packageManager: PackageManager
|
|
||||||
): Promise<string> {
|
|
||||||
const hash = await glob.hashFiles(packageManager.pattern.join('\n'))
|
const hash = await glob.hashFiles(packageManager.pattern.join('\n'))
|
||||||
return `${CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${packageManager.id}-${hash}`
|
return `${CACHE_KEY_PREFIX}-${process.env['RUNNER_OS']}-${packageManager.id}-${hash}`
|
||||||
}
|
}
|
||||||
@ -158,9 +143,7 @@ export async function save(id: string): Promise<void> {
|
|||||||
return
|
return
|
||||||
} else if (matchedKey === primaryKey) {
|
} else if (matchedKey === primaryKey) {
|
||||||
// no change in target directories
|
// no change in target directories
|
||||||
core.info(
|
core.info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`)
|
||||||
`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@ -190,14 +173,8 @@ export async function save(id: string): Promise<void> {
|
|||||||
* @returns true if the given error seems related to the {@link https://github.com/actions/cache/issues/454|running Gradle Daemon issue}.
|
* @returns true if the given error seems related to the {@link https://github.com/actions/cache/issues/454|running Gradle Daemon issue}.
|
||||||
* @see {@link https://github.com/actions/cache/issues/454#issuecomment-840493935|why --no-daemon is necessary}
|
* @see {@link https://github.com/actions/cache/issues/454#issuecomment-840493935|why --no-daemon is necessary}
|
||||||
*/
|
*/
|
||||||
function isProbablyGradleDaemonProblem(
|
function isProbablyGradleDaemonProblem(packageManager: PackageManager, error: Error): boolean {
|
||||||
packageManager: PackageManager,
|
if (packageManager.id !== 'gradle' || process.env['RUNNER_OS'] !== 'Windows') {
|
||||||
error: Error
|
|
||||||
): boolean {
|
|
||||||
if (
|
|
||||||
packageManager.id !== 'gradle' ||
|
|
||||||
process.env['RUNNER_OS'] !== 'Windows'
|
|
||||||
) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const message = error.message || ''
|
const message = error.message || ''
|
||||||
|
@ -1,19 +1,13 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
|
|
||||||
export function checkForUpdates(
|
export function checkForUpdates(graalVMVersion: string, javaVersion: string): void {
|
||||||
graalVMVersion: string,
|
|
||||||
javaVersion: string
|
|
||||||
): void {
|
|
||||||
if (javaVersion === '20') {
|
if (javaVersion === '20') {
|
||||||
core.notice(
|
core.notice(
|
||||||
'A new GraalVM release is available! Please consider upgrading to GraalVM for JDK 21: https://medium.com/graalvm/graalvm-for-jdk-21-is-here-ee01177dd12d'
|
'A new GraalVM release is available! Please consider upgrading to GraalVM for JDK 21: https://medium.com/graalvm/graalvm-for-jdk-21-is-here-ee01177dd12d'
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (
|
if (graalVMVersion.length > 0 && (javaVersion === '17' || javaVersion === '19')) {
|
||||||
graalVMVersion.length > 0 &&
|
|
||||||
(javaVersion === '17' || javaVersion === '19')
|
|
||||||
) {
|
|
||||||
const recommendedJDK = javaVersion === '17' ? '17' : '21'
|
const recommendedJDK = javaVersion === '17' ? '17' : '21'
|
||||||
core.notice(
|
core.notice(
|
||||||
`A new GraalVM release is available! Please consider upgrading to GraalVM for JDK ${recommendedJDK}. Instructions: https://github.com/graalvm/setup-graalvm#migrating-from-graalvm-223-or-earlier-to-the-new-graalvm-for-jdk-17-and-later`
|
`A new GraalVM release is available! Please consider upgrading to GraalVM for JDK ${recommendedJDK}. Instructions: https://github.com/graalvm/setup-graalvm#migrating-from-graalvm-223-or-earlier-to-the-new-graalvm-for-jdk-17-and-later`
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import * as c from '../constants'
|
import * as c from '../constants'
|
||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import * as tc from '@actions/tool-cache'
|
import * as tc from '@actions/tool-cache'
|
||||||
import {exec} from '../utils'
|
import { exec } from '../utils'
|
||||||
import {join} from 'path'
|
import { join } from 'path'
|
||||||
|
|
||||||
const MUSL_NAME = 'x86_64-linux-musl-native'
|
const MUSL_NAME = 'x86_64-linux-musl-native'
|
||||||
const MUSL_VERSION = '10.2.1'
|
const MUSL_VERSION = '10.2.1'
|
||||||
@ -24,9 +24,7 @@ export async function setUpNativeImageMusl(): Promise<void> {
|
|||||||
const muslPath = join(muslExtractPath, MUSL_NAME)
|
const muslPath = join(muslExtractPath, MUSL_NAME)
|
||||||
|
|
||||||
const zlibCommit = 'ec3df00224d4b396e2ac6586ab5d25f673caa4c2'
|
const zlibCommit = 'ec3df00224d4b396e2ac6586ab5d25f673caa4c2'
|
||||||
const zlibDownloadPath = await tc.downloadTool(
|
const zlibDownloadPath = await tc.downloadTool(`https://github.com/madler/zlib/archive/${zlibCommit}.tar.gz`)
|
||||||
`https://github.com/madler/zlib/archive/${zlibCommit}.tar.gz`
|
|
||||||
)
|
|
||||||
const zlibExtractPath = await tc.extractTar(zlibDownloadPath)
|
const zlibExtractPath = await tc.extractTar(zlibDownloadPath)
|
||||||
const zlibPath = join(zlibExtractPath, `zlib-${zlibCommit}`)
|
const zlibPath = join(zlibExtractPath, `zlib-${zlibCommit}`)
|
||||||
const zlibBuildOptions = {
|
const zlibBuildOptions = {
|
||||||
@ -36,13 +34,9 @@ export async function setUpNativeImageMusl(): Promise<void> {
|
|||||||
CC: join(muslPath, 'bin', 'gcc')
|
CC: join(muslPath, 'bin', 'gcc')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await exec(
|
await exec('./configure', [`--prefix=${muslPath}`, '--static'], zlibBuildOptions)
|
||||||
'./configure',
|
|
||||||
[`--prefix=${muslPath}`, '--static'],
|
|
||||||
zlibBuildOptions
|
|
||||||
)
|
|
||||||
await exec('make', [], zlibBuildOptions)
|
await exec('make', [], zlibBuildOptions)
|
||||||
await exec('make', ['install'], {cwd: zlibPath})
|
await exec('make', ['install'], { cwd: zlibPath })
|
||||||
|
|
||||||
core.info(`Adding ${MUSL_NAME} ${MUSL_VERSION} to tool-cache ...`)
|
core.info(`Adding ${MUSL_NAME} ${MUSL_VERSION} to tool-cache ...`)
|
||||||
toolPath = await tc.cacheDir(muslPath, MUSL_NAME, MUSL_VERSION)
|
toolPath = await tc.cacheDir(muslPath, MUSL_NAME, MUSL_VERSION)
|
||||||
|
@ -3,31 +3,24 @@ 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 * as semver from 'semver'
|
||||||
import {join} from 'path'
|
|
||||||
import {tmpdir} from 'os'
|
|
||||||
import {
|
import {
|
||||||
createPRComment,
|
createPRComment,
|
||||||
findExistingPRCommentId,
|
findExistingPRCommentId,
|
||||||
isPREvent,
|
isPREvent,
|
||||||
toSemVer,
|
toSemVer,
|
||||||
updatePRComment
|
updatePRComment,
|
||||||
|
tmpfile,
|
||||||
|
setNativeImageOption
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
const BUILD_OUTPUT_JSON_PATH = join(tmpdir(), 'native-image-build-output.json')
|
const BUILD_OUTPUT_JSON_PATH = tmpfile('native-image-build-output.json')
|
||||||
const BYTES_TO_KiB = 1024
|
const BYTES_TO_KiB = 1024
|
||||||
const BYTES_TO_MiB = 1024 * 1024
|
const BYTES_TO_MiB = 1024 * 1024
|
||||||
const BYTES_TO_GiB = 1024 * 1024 * 1024
|
const BYTES_TO_GiB = 1024 * 1024 * 1024
|
||||||
const DOCS_BASE =
|
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 INPUT_NI_PR_REPORTS_UPDATE = 'native-image-pr-reports-update-existing'
|
||||||
const NATIVE_IMAGE_CONFIG_FILE = join(
|
|
||||||
tmpdir(),
|
|
||||||
'native-image-options.properties'
|
|
||||||
)
|
|
||||||
const NATIVE_IMAGE_OPTIONS_ENV = 'NATIVE_IMAGE_OPTIONS'
|
|
||||||
const NATIVE_IMAGE_CONFIG_FILE_ENV = 'NATIVE_IMAGE_CONFIG_FILE'
|
|
||||||
const PR_COMMENT_TITLE = '## GraalVM Native Image Build Report'
|
const PR_COMMENT_TITLE = '## GraalVM Native Image Build Report'
|
||||||
|
|
||||||
interface AnalysisResult {
|
interface AnalysisResult {
|
||||||
@ -111,18 +104,14 @@ export async function setUpNativeImageBuildReports(
|
|||||||
isGraalVMforJDK17OrLater ||
|
isGraalVMforJDK17OrLater ||
|
||||||
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) && semver.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}.`
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setNativeImageOption(
|
setNativeImageOption(javaVersionOrDev, `-H:BuildOutputJSONFile=${BUILD_OUTPUT_JSON_PATH.replace(/\\/g, '\\\\')}`) // Escape backslashes for Windows
|
||||||
javaVersionOrDev,
|
|
||||||
`-H:BuildOutputJSONFile=${BUILD_OUTPUT_JSON_PATH.replace(/\\/g, '\\\\')}`
|
|
||||||
) // Escape backslashes for Windows
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generateReports(): Promise<void> {
|
export async function generateReports(): Promise<void> {
|
||||||
@ -133,9 +122,7 @@ export async function generateReports(): Promise<void> {
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const buildOutput: BuildOutput = JSON.parse(
|
const buildOutput: BuildOutput = JSON.parse(fs.readFileSync(BUILD_OUTPUT_JSON_PATH, 'utf8'))
|
||||||
fs.readFileSync(BUILD_OUTPUT_JSON_PATH, 'utf8')
|
|
||||||
)
|
|
||||||
const report = createReport(buildOutput)
|
const report = createReport(buildOutput)
|
||||||
if (areJobReportsEnabled()) {
|
if (areJobReportsEnabled()) {
|
||||||
core.summary.addRaw(report)
|
core.summary.addRaw(report)
|
||||||
@ -150,9 +137,7 @@ export async function generateReports(): Promise<void> {
|
|||||||
}
|
}
|
||||||
return createPRComment(report)
|
return createPRComment(report)
|
||||||
} else if (arePRReportsUpdateEnabled()) {
|
} else if (arePRReportsUpdateEnabled()) {
|
||||||
throw new Error(
|
throw new Error(`'${INPUT_NI_PR_REPORTS_UPDATE}' option requires '${INPUT_NI_PR_REPORTS}' to be set 'true'`)
|
||||||
`'${INPUT_NI_PR_REPORTS_UPDATE}' option requires '${INPUT_NI_PR_REPORTS}' to be set 'true'`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,43 +154,6 @@ function arePRReportsUpdateEnabled(): boolean {
|
|||||||
return isPREvent() && core.getInput(INPUT_NI_PR_REPORTS_UPDATE) === 'true'
|
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 {
|
|
||||||
let optionsFile = process.env[NATIVE_IMAGE_CONFIG_FILE_ENV]
|
|
||||||
if (optionsFile === undefined) {
|
|
||||||
optionsFile = NATIVE_IMAGE_CONFIG_FILE
|
|
||||||
core.exportVariable(NATIVE_IMAGE_CONFIG_FILE_ENV, optionsFile)
|
|
||||||
}
|
|
||||||
return optionsFile
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
||||||
@ -217,11 +165,7 @@ function createReport(data: BuildOutput): string {
|
|||||||
objectCount = `${details.image_heap.objects.count.toLocaleString()} objects, `
|
objectCount = `${details.image_heap.objects.count.toLocaleString()} objects, `
|
||||||
}
|
}
|
||||||
const debugInfoBytes = details.debug_info ? details.debug_info.bytes : 0
|
const debugInfoBytes = details.debug_info ? details.debug_info.bytes : 0
|
||||||
const otherBytes =
|
const otherBytes = details.total_bytes - details.code_area.bytes - details.image_heap.bytes - debugInfoBytes
|
||||||
details.total_bytes -
|
|
||||||
details.code_area.bytes -
|
|
||||||
details.image_heap.bytes -
|
|
||||||
debugInfoBytes
|
|
||||||
let debugInfoLine = ''
|
let debugInfoLine = ''
|
||||||
if (details.debug_info) {
|
if (details.debug_info) {
|
||||||
debugInfoLine = `
|
debugInfoLine = `
|
||||||
@ -253,8 +197,7 @@ function createReport(data: BuildOutput): string {
|
|||||||
let graalLine
|
let graalLine
|
||||||
if (info.graal_compiler) {
|
if (info.graal_compiler) {
|
||||||
let pgoSuffix = ''
|
let pgoSuffix = ''
|
||||||
const isOracleGraalVM =
|
const isOracleGraalVM = info.vendor_version && info.vendor_version.includes('Oracle GraalVM')
|
||||||
info.vendor_version && info.vendor_version.includes('Oracle GraalVM')
|
|
||||||
if (isOracleGraalVM) {
|
if (isOracleGraalVM) {
|
||||||
const pgo = info.graal_compiler.pgo
|
const pgo = info.graal_compiler.pgo
|
||||||
const pgoText = pgo ? pgo.join('+') : 'off'
|
const pgoText = pgo ? pgo.join('+') : 'off'
|
||||||
@ -276,10 +219,7 @@ function createReport(data: BuildOutput): string {
|
|||||||
let gcTotalTimeRatio = ''
|
let gcTotalTimeRatio = ''
|
||||||
if (resources.total_secs) {
|
if (resources.total_secs) {
|
||||||
totalTime = ` in ${secondsToHuman(resources.total_secs)}`
|
totalTime = ` in ${secondsToHuman(resources.total_secs)}`
|
||||||
gcTotalTimeRatio = ` (${toPercent(
|
gcTotalTimeRatio = ` (${toPercent(resources.garbage_collection.total_secs, resources.total_secs)} of total time)`
|
||||||
resources.garbage_collection.total_secs,
|
|
||||||
resources.total_secs
|
|
||||||
)} of total time)`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${PR_COMMENT_TITLE}
|
return `${PR_COMMENT_TITLE}
|
||||||
@ -321,56 +261,29 @@ function createReport(data: BuildOutput): string {
|
|||||||
<tr>
|
<tr>
|
||||||
<td align="left"><a href="${DOCS_BASE}#glossary-reachability" target="_blank">Reachable</a></td>
|
<td align="left"><a href="${DOCS_BASE}#glossary-reachability" target="_blank">Reachable</a></td>
|
||||||
<td align="right">${analysisTypes.reachable.toLocaleString()}</td>
|
<td align="right">${analysisTypes.reachable.toLocaleString()}</td>
|
||||||
<td align="right">${toPercent(
|
<td align="right">${toPercent(analysisTypes.reachable, analysisTypes.total)}</td>
|
||||||
analysisTypes.reachable,
|
|
||||||
analysisTypes.total
|
|
||||||
)}</td>
|
|
||||||
<td align="right">${analysis.fields.reachable.toLocaleString()}</td>
|
<td align="right">${analysis.fields.reachable.toLocaleString()}</td>
|
||||||
<td align="right">${toPercent(
|
<td align="right">${toPercent(analysis.fields.reachable, analysis.fields.total)}</td>
|
||||||
analysis.fields.reachable,
|
|
||||||
analysis.fields.total
|
|
||||||
)}</td>
|
|
||||||
<td align="right">${analysis.methods.reachable.toLocaleString()}</td>
|
<td align="right">${analysis.methods.reachable.toLocaleString()}</td>
|
||||||
<td align="right">${toPercent(
|
<td align="right">${toPercent(analysis.methods.reachable, analysis.methods.total)}</td>
|
||||||
analysis.methods.reachable,
|
|
||||||
analysis.methods.total
|
|
||||||
)}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="left"><a href="${DOCS_BASE}#glossary-reflection-registrations" target="_blank">Reflection</a></td>
|
<td align="left"><a href="${DOCS_BASE}#glossary-reflection-registrations" target="_blank">Reflection</a></td>
|
||||||
<td align="right">${analysisTypes.reflection.toLocaleString()}</td>
|
<td align="right">${analysisTypes.reflection.toLocaleString()}</td>
|
||||||
<td align="right">${toPercent(
|
<td align="right">${toPercent(analysisTypes.reflection, analysisTypes.total)}</td>
|
||||||
analysisTypes.reflection,
|
|
||||||
analysisTypes.total
|
|
||||||
)}</td>
|
|
||||||
<td align="right">${analysis.fields.reflection.toLocaleString()}</td>
|
<td align="right">${analysis.fields.reflection.toLocaleString()}</td>
|
||||||
<td align="right">${toPercent(
|
<td align="right">${toPercent(analysis.fields.reflection, analysis.fields.total)}</td>
|
||||||
analysis.fields.reflection,
|
|
||||||
analysis.fields.total
|
|
||||||
)}</td>
|
|
||||||
<td align="right">${analysis.methods.reflection.toLocaleString()}</td>
|
<td align="right">${analysis.methods.reflection.toLocaleString()}</td>
|
||||||
<td align="right">${toPercent(
|
<td align="right">${toPercent(analysis.methods.reflection, analysis.methods.total)}</td>
|
||||||
analysis.methods.reflection,
|
|
||||||
analysis.methods.total
|
|
||||||
)}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="left"><a href="${DOCS_BASE}#glossary-jni-access-registrations" target="_blank">JNI</a></td>
|
<td align="left"><a href="${DOCS_BASE}#glossary-jni-access-registrations" target="_blank">JNI</a></td>
|
||||||
<td align="right">${analysisTypes.jni.toLocaleString()}</td>
|
<td align="right">${analysisTypes.jni.toLocaleString()}</td>
|
||||||
<td align="right">${toPercent(
|
<td align="right">${toPercent(analysisTypes.jni, analysisTypes.total)}</td>
|
||||||
analysisTypes.jni,
|
|
||||||
analysisTypes.total
|
|
||||||
)}</td>
|
|
||||||
<td align="right">${analysis.fields.jni.toLocaleString()}</td>
|
<td align="right">${analysis.fields.jni.toLocaleString()}</td>
|
||||||
<td align="right">${toPercent(
|
<td align="right">${toPercent(analysis.fields.jni, analysis.fields.total)}</td>
|
||||||
analysis.fields.jni,
|
|
||||||
analysis.fields.total
|
|
||||||
)}</td>
|
|
||||||
<td align="right">${analysis.methods.jni.toLocaleString()}</td>
|
<td align="right">${analysis.methods.jni.toLocaleString()}</td>
|
||||||
<td align="right">${toPercent(
|
<td align="right">${toPercent(analysis.methods.jni, analysis.methods.total)}</td>
|
||||||
analysis.methods.jni,
|
|
||||||
analysis.methods.total
|
|
||||||
)}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="left"><a href="${DOCS_BASE}#glossary-reachability" target="_blank">Loaded</a></td>
|
<td align="left"><a href="${DOCS_BASE}#glossary-reachability" target="_blank">Loaded</a></td>
|
||||||
@ -399,19 +312,13 @@ function createReport(data: BuildOutput): string {
|
|||||||
<tr>
|
<tr>
|
||||||
<td align="left"><a href="${DOCS_BASE}#glossary-code-area" target="_blank">Code area</a></td>
|
<td align="left"><a href="${DOCS_BASE}#glossary-code-area" target="_blank">Code area</a></td>
|
||||||
<td align="right">${bytesToHuman(details.code_area.bytes)}</td>
|
<td align="right">${bytesToHuman(details.code_area.bytes)}</td>
|
||||||
<td align="right">${toPercent(
|
<td align="right">${toPercent(details.code_area.bytes, details.total_bytes)}</td>
|
||||||
details.code_area.bytes,
|
|
||||||
details.total_bytes
|
|
||||||
)}</td>
|
|
||||||
<td align="left">${details.code_area.compilation_units.toLocaleString()} compilation units</td>
|
<td align="left">${details.code_area.compilation_units.toLocaleString()} compilation units</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="left"><a href="${DOCS_BASE}#glossary-image-heap" target="_blank">Image heap</a></td>
|
<td align="left"><a href="${DOCS_BASE}#glossary-image-heap" target="_blank">Image heap</a></td>
|
||||||
<td align="right">${bytesToHuman(details.image_heap.bytes)}</td>
|
<td align="right">${bytesToHuman(details.image_heap.bytes)}</td>
|
||||||
<td align="right">${toPercent(
|
<td align="right">${toPercent(details.image_heap.bytes, details.total_bytes)}</td>
|
||||||
details.image_heap.bytes,
|
|
||||||
details.total_bytes
|
|
||||||
)}</td>
|
|
||||||
<td align="left">${objectCount}${bytesToHuman(
|
<td align="left">${objectCount}${bytesToHuman(
|
||||||
details.image_heap.resources.bytes
|
details.image_heap.resources.bytes
|
||||||
)} for ${details.image_heap.resources.count.toLocaleString()} resources</td>
|
)} for ${details.image_heap.resources.count.toLocaleString()} resources</td>
|
||||||
@ -424,9 +331,7 @@ function createReport(data: BuildOutput): string {
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="left">Total</td>
|
<td align="left">Total</td>
|
||||||
<td align="right"><strong>${bytesToHuman(
|
<td align="right"><strong>${bytesToHuman(details.total_bytes)}</strong></td>
|
||||||
details.total_bytes
|
|
||||||
)}</strong></td>
|
|
||||||
<td align="right">100.000%</td>
|
<td align="right">100.000%</td>
|
||||||
<td align="left"></td>
|
<td align="left"></td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -445,9 +350,7 @@ function createReport(data: BuildOutput): string {
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="left"><a href="${DOCS_BASE}#glossary-peak-rss" target="_blank">Peak RSS</a></td>
|
<td align="left"><a href="${DOCS_BASE}#glossary-peak-rss" target="_blank">Peak RSS</a></td>
|
||||||
<td align="left">${bytesToHuman(
|
<td align="left">${bytesToHuman(resources.memory.peak_rss_bytes)} (${toPercent(
|
||||||
resources.memory.peak_rss_bytes
|
|
||||||
)} (${toPercent(
|
|
||||||
resources.memory.peak_rss_bytes,
|
resources.memory.peak_rss_bytes,
|
||||||
resources.memory.system_total
|
resources.memory.system_total
|
||||||
)} of ${bytesToHuman(resources.memory.system_total)} system memory)</td>
|
)} of ${bytesToHuman(resources.memory.system_total)} system memory)</td>
|
||||||
|
271
src/features/sbom.ts
Normal file
271
src/features/sbom.ts
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
import * as c from '../constants'
|
||||||
|
import * as core from '@actions/core'
|
||||||
|
import * as fs from 'fs'
|
||||||
|
import * as github from '@actions/github'
|
||||||
|
import * as glob from '@actions/glob'
|
||||||
|
import { basename } from 'path'
|
||||||
|
import * as semver from 'semver'
|
||||||
|
import { setNativeImageOption } from '../utils'
|
||||||
|
|
||||||
|
const INPUT_NI_SBOM = 'native-image-enable-sbom'
|
||||||
|
const SBOM_FILE_SUFFIX = '.sbom.json'
|
||||||
|
const MIN_JAVA_VERSION = '24.0.0'
|
||||||
|
const javaVersionKey = 'javaVersionKey'
|
||||||
|
|
||||||
|
interface SBOM {
|
||||||
|
components: Component[]
|
||||||
|
dependencies: Dependency[]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Component {
|
||||||
|
name: string
|
||||||
|
version?: string
|
||||||
|
purl?: string
|
||||||
|
dependencies?: string[]
|
||||||
|
'bom-ref': string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Dependency {
|
||||||
|
ref: string
|
||||||
|
dependsOn: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DependencySnapshot {
|
||||||
|
version: number
|
||||||
|
sha: string
|
||||||
|
ref: string
|
||||||
|
job: {
|
||||||
|
correlator: string
|
||||||
|
id: string
|
||||||
|
html_url?: string
|
||||||
|
}
|
||||||
|
detector: {
|
||||||
|
name: string
|
||||||
|
version: string
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
scanned: string
|
||||||
|
manifests: Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
name: string
|
||||||
|
metadata?: Record<string, string>
|
||||||
|
// Not including the 'file' property because we cannot specify any reasonable value for 'source_location'
|
||||||
|
// since the SBOM will not necessarily be saved in the repository of the user.
|
||||||
|
// GitHub docs: https://docs.github.com/en/rest/dependency-graph/dependency-submission?apiVersion=2022-11-28#create-a-snapshot-of-dependencies-for-a-repository
|
||||||
|
resolved: Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
package_url: string
|
||||||
|
relationship?: 'direct'
|
||||||
|
scope?: 'runtime'
|
||||||
|
dependencies?: string[]
|
||||||
|
}
|
||||||
|
>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setUpSBOMSupport(javaVersion: string, distribution: string): void {
|
||||||
|
if (!isFeatureEnabled()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
validateJavaVersionAndDistribution(javaVersion, distribution)
|
||||||
|
core.saveState(javaVersionKey, javaVersion)
|
||||||
|
setNativeImageOption(javaVersion, '--enable-sbom=export')
|
||||||
|
core.info('Enabled SBOM generation for Native Image build')
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateJavaVersionAndDistribution(javaVersion: string, distribution: string): void {
|
||||||
|
if (distribution !== c.DISTRIBUTION_GRAALVM) {
|
||||||
|
throw new Error(
|
||||||
|
`The '${INPUT_NI_SBOM}' option is only supported for Oracle GraalVM (distribution '${c.DISTRIBUTION_GRAALVM}'), but found distribution '${distribution}'.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (javaVersion === 'dev') {
|
||||||
|
throw new Error(`The '${INPUT_NI_SBOM}' option is not supported for java-version 'dev'.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (javaVersion === 'latest-ea') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const coercedJavaVersion = semver.coerce(javaVersion)
|
||||||
|
if (!coercedJavaVersion || semver.gt(MIN_JAVA_VERSION, coercedJavaVersion)) {
|
||||||
|
throw new Error(
|
||||||
|
`The '${INPUT_NI_SBOM}' option is only supported for GraalVM for JDK ${MIN_JAVA_VERSION} or later, but found java-version '${javaVersion}'.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function processSBOM(): Promise<void> {
|
||||||
|
if (!isFeatureEnabled()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const javaVersion = core.getState(javaVersionKey)
|
||||||
|
if (!javaVersion) {
|
||||||
|
throw new Error('setUpSBOMSupport must be called before processSBOM')
|
||||||
|
}
|
||||||
|
|
||||||
|
const sbomPath = await findSBOMFilePath()
|
||||||
|
try {
|
||||||
|
const sbomContent = fs.readFileSync(sbomPath, 'utf8')
|
||||||
|
const sbomData = parseSBOM(sbomContent)
|
||||||
|
const components = mapToComponentsWithDependencies(sbomData)
|
||||||
|
printSBOMContent(components)
|
||||||
|
const snapshot = convertSBOMToSnapshot(javaVersion, sbomPath, components)
|
||||||
|
await submitDependencySnapshot(snapshot)
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to process and submit SBOM to the GitHub dependency submission API: ${error instanceof Error ? error.message : String(error)}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFeatureEnabled(): boolean {
|
||||||
|
return core.getInput(INPUT_NI_SBOM) === 'true'
|
||||||
|
}
|
||||||
|
|
||||||
|
async function findSBOMFilePath(): Promise<string> {
|
||||||
|
const globber = await glob.create(`**/*${SBOM_FILE_SUFFIX}`)
|
||||||
|
const sbomFiles = await globber.glob()
|
||||||
|
|
||||||
|
if (sbomFiles.length === 0) {
|
||||||
|
throw new Error('No SBOM found. Make sure native-image build completed successfully.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sbomFiles.length > 1) {
|
||||||
|
throw new Error(`Expected one SBOM but found multiple: ${sbomFiles.join(', ')}.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
core.info(`Found SBOM: ${sbomFiles[0]}`)
|
||||||
|
return sbomFiles[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseSBOM(jsonString: string): SBOM {
|
||||||
|
try {
|
||||||
|
const sbomData: SBOM = JSON.parse(jsonString)
|
||||||
|
return sbomData
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Failed to parse SBOM JSON: ${error instanceof Error ? error.message : String(error)}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maps the SBOM to a list of components with their dependencies
|
||||||
|
function mapToComponentsWithDependencies(sbom: SBOM): Component[] {
|
||||||
|
if (!sbom || sbom.components.length === 0) {
|
||||||
|
throw new Error('Invalid SBOM data or no components found.')
|
||||||
|
}
|
||||||
|
|
||||||
|
return sbom.components.map((component: Component) => {
|
||||||
|
const dependencies = sbom.dependencies?.find((dep: Dependency) => dep.ref === component['bom-ref'])?.dependsOn || []
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: component.name,
|
||||||
|
version: component.version,
|
||||||
|
purl: component.purl,
|
||||||
|
dependencies,
|
||||||
|
'bom-ref': component['bom-ref']
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function printSBOMContent(components: Component[]): void {
|
||||||
|
core.info('=== SBOM Content ===')
|
||||||
|
for (const component of components) {
|
||||||
|
core.info(`- ${component['bom-ref']}`)
|
||||||
|
if (component.dependencies && component.dependencies.length > 0) {
|
||||||
|
core.info(` depends on: ${component.dependencies.join(', ')}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
core.info('==================')
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertSBOMToSnapshot(javaVersion: string, sbomPath: string, components: Component[]): DependencySnapshot {
|
||||||
|
const context = github.context
|
||||||
|
const sbomFileName = basename(sbomPath)
|
||||||
|
|
||||||
|
if (!sbomFileName.endsWith(SBOM_FILE_SUFFIX)) {
|
||||||
|
throw new Error(`Invalid SBOM file name: ${sbomFileName}. Expected a file ending with ${SBOM_FILE_SUFFIX}.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
version: 0,
|
||||||
|
sha: context.sha,
|
||||||
|
ref: context.ref,
|
||||||
|
job: {
|
||||||
|
correlator: `${context.workflow}_${context.job}`,
|
||||||
|
id: context.runId.toString(),
|
||||||
|
html_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`
|
||||||
|
},
|
||||||
|
detector: {
|
||||||
|
name: 'Oracle GraalVM',
|
||||||
|
version: javaVersion,
|
||||||
|
url: 'https://www.graalvm.org/'
|
||||||
|
},
|
||||||
|
scanned: new Date().toISOString(),
|
||||||
|
manifests: {
|
||||||
|
[sbomFileName]: {
|
||||||
|
name: sbomFileName,
|
||||||
|
resolved: mapComponentsToGithubAPIFormat(components),
|
||||||
|
metadata: {
|
||||||
|
generated_by: 'SBOM generated by GraalVM Native Image',
|
||||||
|
action_version: c.ACTION_VERSION
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapComponentsToGithubAPIFormat(
|
||||||
|
components: Component[]
|
||||||
|
): Record<string, { package_url: string; dependencies?: string[] }> {
|
||||||
|
return Object.fromEntries(
|
||||||
|
components
|
||||||
|
.filter((component) => {
|
||||||
|
if (!component.purl) {
|
||||||
|
core.info(`Component ${component.name} does not have a valid package URL (purl). Skipping.`)
|
||||||
|
}
|
||||||
|
return component.purl
|
||||||
|
})
|
||||||
|
.map((component) => [
|
||||||
|
component.name,
|
||||||
|
{
|
||||||
|
package_url: component.purl as string,
|
||||||
|
dependencies: component.dependencies || []
|
||||||
|
}
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submitDependencySnapshot(snapshotData: DependencySnapshot): Promise<void> {
|
||||||
|
const token = core.getInput(c.INPUT_GITHUB_TOKEN, { required: true })
|
||||||
|
const octokit = github.getOctokit(token)
|
||||||
|
const context = github.context
|
||||||
|
|
||||||
|
try {
|
||||||
|
await octokit.request('POST /repos/{owner}/{repo}/dependency-graph/snapshots', {
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
version: snapshotData.version,
|
||||||
|
sha: snapshotData.sha,
|
||||||
|
ref: snapshotData.ref,
|
||||||
|
job: snapshotData.job,
|
||||||
|
detector: snapshotData.detector,
|
||||||
|
metadata: {},
|
||||||
|
scanned: snapshotData.scanned,
|
||||||
|
manifests: snapshotData.manifests,
|
||||||
|
headers: {
|
||||||
|
'X-GitHub-Api-Version': '2022-11-28'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
core.info('Dependency snapshot submitted successfully.')
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to submit dependency snapshot for SBOM: ${error instanceof Error ? error.message : String(error)}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
100
src/gds.ts
100
src/gds.ts
@ -7,11 +7,11 @@ 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 * 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'
|
||||||
import {ok} from 'assert'
|
import { ok } from 'assert'
|
||||||
import {v4 as uuidv4} from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
|
||||||
interface GDSArtifactsResponse {
|
interface GDSArtifactsResponse {
|
||||||
readonly items: GDSArtifact[]
|
readonly items: GDSArtifact[]
|
||||||
@ -27,39 +27,19 @@ interface GDSErrorResponse {
|
|||||||
readonly message: string
|
readonly message: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function downloadGraalVM(
|
export async function downloadGraalVM(gdsToken: string, javaVersion: string): Promise<string> {
|
||||||
gdsToken: string,
|
|
||||||
javaVersion: string
|
|
||||||
): Promise<string> {
|
|
||||||
const userAgent = `GraalVMGitHubAction/${c.ACTION_VERSION} (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 fetchArtifact(userAgent, 'isBase:True', javaVersion)
|
||||||
userAgent,
|
|
||||||
'isBase:True',
|
|
||||||
javaVersion
|
|
||||||
)
|
|
||||||
return downloadArtifact(gdsToken, userAgent, baseArtifact)
|
return downloadArtifact(gdsToken, userAgent, baseArtifact)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function downloadGraalVMEELegacy(
|
export async function downloadGraalVMEELegacy(gdsToken: string, version: string, javaVersion: string): Promise<string> {
|
||||||
gdsToken: string,
|
|
||||||
version: string,
|
|
||||||
javaVersion: string
|
|
||||||
): Promise<string> {
|
|
||||||
const userAgent = `GraalVMGitHubAction/${c.ACTION_VERSION} (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 fetchArtifactEE(
|
const baseArtifact = await fetchArtifactEE(userAgent, 'isBase:True', version, javaVersion)
|
||||||
userAgent,
|
|
||||||
'isBase:True',
|
|
||||||
version,
|
|
||||||
javaVersion
|
|
||||||
)
|
|
||||||
return downloadArtifact(gdsToken, userAgent, baseArtifact)
|
return downloadArtifact(gdsToken, userAgent, baseArtifact)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchArtifact(
|
export async function fetchArtifact(userAgent: string, metadata: string, javaVersion: string): Promise<GDSArtifact> {
|
||||||
userAgent: string,
|
|
||||||
metadata: string,
|
|
||||||
javaVersion: string
|
|
||||||
): Promise<GDSArtifact> {
|
|
||||||
const http = new httpClient.HttpClient(userAgent)
|
const http = new httpClient.HttpClient(userAgent)
|
||||||
|
|
||||||
let filter
|
let filter
|
||||||
@ -79,15 +59,13 @@ export async function fetchArtifact(
|
|||||||
const catalogOS = c.IS_MACOS ? 'macos' : c.GRAALVM_PLATFORM
|
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`
|
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}`)
|
core.debug(`Requesting ${requestUrl}`)
|
||||||
const response = await http.get(requestUrl, {accept: 'application/json'})
|
const response = await http.get(requestUrl, { accept: 'application/json' })
|
||||||
if (response.message.statusCode !== 200) {
|
if (response.message.statusCode !== 200) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unable to find GraalVM for JDK ${javaVersion}. Are you sure java-version: '${javaVersion}' is correct?`
|
`Unable to find GraalVM for JDK ${javaVersion}. Are you sure java-version: '${javaVersion}' is correct?`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
const artifactResponse = JSON.parse(
|
const artifactResponse = JSON.parse(await response.readBody()) as GDSArtifactsResponse
|
||||||
await response.readBody()
|
|
||||||
) as GDSArtifactsResponse
|
|
||||||
if (artifactResponse.items.length !== 1) {
|
if (artifactResponse.items.length !== 1) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
artifactResponse.items.length > 1
|
artifactResponse.items.length > 1
|
||||||
@ -116,15 +94,11 @@ export async function fetchArtifactEE(
|
|||||||
const catalogOS = c.IS_MACOS ? 'macos' : c.GRAALVM_PLATFORM
|
const catalogOS = c.IS_MACOS ? 'macos' : c.GRAALVM_PLATFORM
|
||||||
const requestUrl = `${c.GDS_BASE}/artifacts?productId=${c.GDS_GRAALVM_PRODUCT_ID}&${filter}&metadata=java:jdk${javaVersion}&metadata=os:${catalogOS}&metadata=arch:${c.GRAALVM_ARCH}&metadata=${metadata}&status=PUBLISHED&responseFields=id&responseFields=checksum`
|
const requestUrl = `${c.GDS_BASE}/artifacts?productId=${c.GDS_GRAALVM_PRODUCT_ID}&${filter}&metadata=java:jdk${javaVersion}&metadata=os:${catalogOS}&metadata=arch:${c.GRAALVM_ARCH}&metadata=${metadata}&status=PUBLISHED&responseFields=id&responseFields=checksum`
|
||||||
core.debug(`Requesting ${requestUrl}`)
|
core.debug(`Requesting ${requestUrl}`)
|
||||||
const response = await http.get(requestUrl, {accept: 'application/json'})
|
const response = await http.get(requestUrl, { accept: 'application/json' })
|
||||||
if (response.message.statusCode !== 200) {
|
if (response.message.statusCode !== 200) {
|
||||||
throw new Error(
|
throw new Error(`Unable to find JDK${javaVersion}-based GraalVM EE ${version}`)
|
||||||
`Unable to find JDK${javaVersion}-based GraalVM EE ${version}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
const artifactResponse = JSON.parse(
|
const artifactResponse = JSON.parse(await response.readBody()) as GDSArtifactsResponse
|
||||||
await response.readBody()
|
|
||||||
) as GDSArtifactsResponse
|
|
||||||
if (artifactResponse.items.length !== 1) {
|
if (artifactResponse.items.length !== 1) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
artifactResponse.items.length > 1
|
artifactResponse.items.length > 1
|
||||||
@ -135,21 +109,13 @@ export async function fetchArtifactEE(
|
|||||||
return artifactResponse.items[0]
|
return artifactResponse.items[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadArtifact(
|
async function downloadArtifact(gdsToken: string, userAgent: string, artifact: GDSArtifact): Promise<string> {
|
||||||
gdsToken: string,
|
|
||||||
userAgent: string,
|
|
||||||
artifact: GDSArtifact
|
|
||||||
): Promise<string> {
|
|
||||||
let downloadPath
|
let downloadPath
|
||||||
try {
|
try {
|
||||||
downloadPath = await downloadTool(
|
downloadPath = await downloadTool(`${c.GDS_BASE}/artifacts/${artifact.id}/content`, userAgent, {
|
||||||
`${c.GDS_BASE}/artifacts/${artifact.id}/content`,
|
accept: 'application/x-yaml',
|
||||||
userAgent,
|
'x-download-token': gdsToken
|
||||||
{
|
})
|
||||||
accept: 'application/x-yaml',
|
|
||||||
'x-download-token': gdsToken
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof HTTPError && err.httpStatusCode) {
|
if (err instanceof HTTPError && err.httpStatusCode) {
|
||||||
if (err.httpStatusCode === 401) {
|
if (err.httpStatusCode === 401) {
|
||||||
@ -162,9 +128,7 @@ async function downloadArtifact(
|
|||||||
}
|
}
|
||||||
const sha256 = calculateSHA256(downloadPath)
|
const sha256 = calculateSHA256(downloadPath)
|
||||||
if (sha256.toLowerCase() !== artifact.checksum.toLowerCase()) {
|
if (sha256.toLowerCase() !== artifact.checksum.toLowerCase()) {
|
||||||
throw new Error(
|
throw new Error(`Checksum does not match (expected: "${artifact.checksum}", got: "${sha256}")`)
|
||||||
`Checksum does not match (expected: "${artifact.checksum}", got: "${sha256}")`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return downloadPath
|
return downloadPath
|
||||||
}
|
}
|
||||||
@ -185,11 +149,7 @@ class HTTPError extends Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadTool(
|
async function downloadTool(url: string, userAgent: string, headers?: OutgoingHttpHeaders): Promise<string> {
|
||||||
url: string,
|
|
||||||
userAgent: string,
|
|
||||||
headers?: OutgoingHttpHeaders
|
|
||||||
): Promise<string> {
|
|
||||||
const dest = path.join(getTempDirectory(), uuidv4())
|
const dest = path.join(getTempDirectory(), uuidv4())
|
||||||
await io.mkdirP(path.dirname(dest))
|
await io.mkdirP(path.dirname(dest))
|
||||||
core.debug(`Downloading ${url}`)
|
core.debug(`Downloading ${url}`)
|
||||||
@ -206,11 +166,7 @@ async function downloadTool(
|
|||||||
(err: Error) => {
|
(err: Error) => {
|
||||||
if (err instanceof HTTPError && err.httpStatusCode) {
|
if (err instanceof HTTPError && err.httpStatusCode) {
|
||||||
// Don't retry anything less than 500, except 408 Request Timeout and 429 Too Many Requests
|
// Don't retry anything less than 500, except 408 Request Timeout and 429 Too Many Requests
|
||||||
if (
|
if (err.httpStatusCode < 500 && err.httpStatusCode !== 408 && err.httpStatusCode !== 429) {
|
||||||
err.httpStatusCode < 500 &&
|
|
||||||
err.httpStatusCode !== 408 &&
|
|
||||||
err.httpStatusCode !== 429
|
|
||||||
) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,14 +194,8 @@ async function downloadToolAttempt(
|
|||||||
|
|
||||||
const response: httpClient.HttpClientResponse = await http.get(url, headers)
|
const response: httpClient.HttpClientResponse = await http.get(url, headers)
|
||||||
if (response.message.statusCode !== 200) {
|
if (response.message.statusCode !== 200) {
|
||||||
const errorResponse = JSON.parse(
|
const errorResponse = JSON.parse(await response.readBody()) as GDSErrorResponse
|
||||||
await response.readBody()
|
const err = new HTTPError(response.message.statusCode, errorResponse, response.message.headers)
|
||||||
) as GDSErrorResponse
|
|
||||||
const err = new HTTPError(
|
|
||||||
response.message.statusCode,
|
|
||||||
errorResponse,
|
|
||||||
response.message.headers
|
|
||||||
)
|
|
||||||
core.debug(
|
core.debug(
|
||||||
`Failed to download from "${url}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`
|
`Failed to download from "${url}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`
|
||||||
)
|
)
|
||||||
|
158
src/graalvm.ts
158
src/graalvm.ts
@ -9,9 +9,9 @@ import {
|
|||||||
getMatchingTags,
|
getMatchingTags,
|
||||||
getTaggedRelease
|
getTaggedRelease
|
||||||
} from './utils'
|
} from './utils'
|
||||||
import {downloadGraalVM, 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`
|
||||||
@ -23,10 +23,7 @@ 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, gdsToken: string): Promise<string> {
|
||||||
javaVersionOrDev: string,
|
|
||||||
gdsToken: string
|
|
||||||
): Promise<string> {
|
|
||||||
if (javaVersionOrDev === c.VERSION_DEV) {
|
if (javaVersionOrDev === c.VERSION_DEV) {
|
||||||
return setUpGraalVMJDKDevBuild()
|
return setUpGraalVMJDKDevBuild()
|
||||||
}
|
}
|
||||||
@ -52,9 +49,7 @@ export async function setUpGraalVMJDK(
|
|||||||
const filename = basename(downloadUrl)
|
const filename = basename(downloadUrl)
|
||||||
const resolvedVersion = semver.valid(semver.coerce(filename))
|
const resolvedVersion = semver.valid(semver.coerce(filename))
|
||||||
if (!resolvedVersion) {
|
if (!resolvedVersion) {
|
||||||
throw new Error(
|
throw new Error(`Unable to determine resolved version based on '${filename}'. ${c.ERROR_REQUEST}`)
|
||||||
`Unable to determine resolved version based on '${filename}'. ${c.ERROR_REQUEST}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
javaVersion = resolvedVersion
|
javaVersion = resolvedVersion
|
||||||
} else if (javaVersion.includes('.')) {
|
} else if (javaVersion.includes('.')) {
|
||||||
@ -80,57 +75,37 @@ export async function setUpGraalVMJDK(
|
|||||||
return downloadExtractAndCacheJDK(downloader, toolName, javaVersion)
|
return downloadExtractAndCacheJDK(downloader, toolName, javaVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function findLatestEABuildDownloadUrl(
|
export async function findLatestEABuildDownloadUrl(javaEaVersion: string): Promise<string> {
|
||||||
javaEaVersion: string
|
|
||||||
): Promise<string> {
|
|
||||||
const filePath = `versions/${javaEaVersion}.json`
|
const filePath = `versions/${javaEaVersion}.json`
|
||||||
let response
|
let response
|
||||||
try {
|
try {
|
||||||
response = await getContents(ORACLE_GRAALVM_REPO_EA_BUILDS, filePath)
|
response = await getContents(ORACLE_GRAALVM_REPO_EA_BUILDS, filePath)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unable to resolve download URL for '${javaEaVersion}'. Please make sure the java-version is set correctly. ${c.ERROR_HINT}`
|
`Unable to resolve download URL for '${javaEaVersion}' (reason: ${error}). Please make sure the java-version is set correctly. ${c.ERROR_HINT}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (
|
if (Array.isArray(response) || response.type !== 'file' || !response.content) {
|
||||||
Array.isArray(response) ||
|
throw new Error(`Unexpected response when resolving download URL for '${javaEaVersion}'. ${c.ERROR_REQUEST}`)
|
||||||
response.type !== 'file' ||
|
|
||||||
!response.content
|
|
||||||
) {
|
|
||||||
throw new Error(
|
|
||||||
`Unexpected response when resolving download URL for '${javaEaVersion}'. ${c.ERROR_REQUEST}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
const versionData = JSON.parse(
|
const versionData = JSON.parse(Buffer.from(response.content, 'base64').toString('utf-8'))
|
||||||
Buffer.from(response.content, 'base64').toString('utf-8')
|
|
||||||
)
|
|
||||||
let latestVersion
|
let latestVersion
|
||||||
if (javaEaVersion === ORACLE_GRAALVM_REPO_EA_BUILDS_LATEST_SYMBOL) {
|
if (javaEaVersion === ORACLE_GRAALVM_REPO_EA_BUILDS_LATEST_SYMBOL) {
|
||||||
latestVersion = versionData as c.OracleGraalVMEAVersion
|
latestVersion = versionData as c.OracleGraalVMEAVersion
|
||||||
} else {
|
} else {
|
||||||
latestVersion = (versionData as c.OracleGraalVMEAVersion[]).find(
|
latestVersion = (versionData as c.OracleGraalVMEAVersion[]).find((v) => v.latest)
|
||||||
v => v.latest
|
|
||||||
)
|
|
||||||
if (!latestVersion) {
|
if (!latestVersion) {
|
||||||
throw new Error(
|
throw new Error(`Unable to find latest version for '${javaEaVersion}'. ${c.ERROR_REQUEST}`)
|
||||||
`Unable to find latest version for '${javaEaVersion}'. ${c.ERROR_REQUEST}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const file = latestVersion.files.find(
|
const file = latestVersion.files.find((f) => f.arch === c.JDK_ARCH && f.platform === c.GRAALVM_PLATFORM)
|
||||||
f => f.arch === c.JDK_ARCH && f.platform === c.GRAALVM_PLATFORM
|
|
||||||
)
|
|
||||||
if (!file || !file.filename.startsWith('graalvm-jdk-')) {
|
if (!file || !file.filename.startsWith('graalvm-jdk-')) {
|
||||||
throw new Error(
|
throw new Error(`Unable to find file metadata for '${javaEaVersion}'. ${c.ERROR_REQUEST}`)
|
||||||
`Unable to find file metadata for '${javaEaVersion}'. ${c.ERROR_REQUEST}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return `${latestVersion.download_base_url}${file.filename}`
|
return `${latestVersion.download_base_url}${file.filename}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setUpGraalVMJDKCE(
|
export async function setUpGraalVMJDKCE(javaVersionOrDev: string): Promise<string> {
|
||||||
javaVersionOrDev: string
|
|
||||||
): Promise<string> {
|
|
||||||
if (javaVersionOrDev === c.VERSION_DEV) {
|
if (javaVersionOrDev === c.VERSION_DEV) {
|
||||||
return setUpGraalVMJDKDevBuild()
|
return setUpGraalVMJDKDevBuild()
|
||||||
}
|
}
|
||||||
@ -149,9 +124,7 @@ export async function setUpGraalVMJDKCE(
|
|||||||
return downloadExtractAndCacheJDK(downloader, toolName, javaVersion)
|
return downloadExtractAndCacheJDK(downloader, toolName, javaVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function findLatestGraalVMJDKCEJavaVersion(
|
export async function findLatestGraalVMJDKCEJavaVersion(majorJavaVersion: string): Promise<string> {
|
||||||
majorJavaVersion: string
|
|
||||||
): Promise<string> {
|
|
||||||
const matchingRefs = await getMatchingTags(
|
const matchingRefs = await getMatchingTags(
|
||||||
c.GRAALVM_GH_USER,
|
c.GRAALVM_GH_USER,
|
||||||
c.GRAALVM_RELEASES_REPO,
|
c.GRAALVM_RELEASES_REPO,
|
||||||
@ -162,10 +135,7 @@ export async function findLatestGraalVMJDKCEJavaVersion(
|
|||||||
const versionNumberStartIndex = `refs/tags/${GRAALVM_JDK_TAG_PREFIX}`.length
|
const versionNumberStartIndex = `refs/tags/${GRAALVM_JDK_TAG_PREFIX}`.length
|
||||||
for (const matchingRef of matchingRefs) {
|
for (const matchingRef of matchingRefs) {
|
||||||
const currentVersion = matchingRef.ref.substring(versionNumberStartIndex)
|
const currentVersion = matchingRef.ref.substring(versionNumberStartIndex)
|
||||||
if (
|
if (semver.valid(currentVersion) && semver.gt(currentVersion, highestVersion)) {
|
||||||
semver.valid(currentVersion) &&
|
|
||||||
semver.gt(currentVersion, highestVersion)
|
|
||||||
) {
|
|
||||||
highestVersion = currentVersion
|
highestVersion = currentVersion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,29 +148,20 @@ export async function findLatestGraalVMJDKCEJavaVersion(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function determineToolName(javaVersion: string, isCommunity: boolean) {
|
function determineToolName(javaVersion: string, isCommunity: boolean) {
|
||||||
return `graalvm${isCommunity ? '-community' : ''}-jdk-${javaVersion}_${
|
return `graalvm${isCommunity ? '-community' : ''}-jdk-${javaVersion}_${c.JDK_PLATFORM}-${c.JDK_ARCH}_bin`
|
||||||
c.JDK_PLATFORM
|
|
||||||
}-${c.JDK_ARCH}_bin`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadGraalVMJDK(
|
async function downloadGraalVMJDK(downloadUrl: string, javaVersion: string): Promise<string> {
|
||||||
downloadUrl: string,
|
|
||||||
javaVersion: string
|
|
||||||
): Promise<string> {
|
|
||||||
try {
|
try {
|
||||||
return await downloadTool(downloadUrl)
|
return await downloadTool(downloadUrl)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Error && error.message.includes('404')) {
|
if (error instanceof Error && error.message.includes('404')) {
|
||||||
// Not Found
|
// Not Found
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Failed to download ${basename(
|
`Failed to download ${basename(downloadUrl)}. Are you sure java-version: '${javaVersion}' is correct?`
|
||||||
downloadUrl
|
|
||||||
)}. Are you sure java-version: '${javaVersion}' is correct?`
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
throw new Error(
|
throw new Error(`Failed to download ${basename(downloadUrl)} (error: ${error}).`)
|
||||||
`Failed to download ${basename(downloadUrl)} (error: ${error}).`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,28 +169,15 @@ async function downloadGraalVMJDK(
|
|||||||
|
|
||||||
export async function setUpGraalVMJDKDevBuild(): Promise<string> {
|
export async function setUpGraalVMJDKDevBuild(): Promise<string> {
|
||||||
const latestDevBuild = await getLatestRelease(GRAALVM_REPO_DEV_BUILDS)
|
const latestDevBuild = await getLatestRelease(GRAALVM_REPO_DEV_BUILDS)
|
||||||
const resolvedJavaVersion = findHighestJavaVersion(
|
const resolvedJavaVersion = findHighestJavaVersion(latestDevBuild, c.VERSION_DEV)
|
||||||
latestDevBuild,
|
|
||||||
c.VERSION_DEV
|
|
||||||
)
|
|
||||||
const downloadUrl = findDownloadUrl(latestDevBuild, resolvedJavaVersion)
|
const downloadUrl = findDownloadUrl(latestDevBuild, resolvedJavaVersion)
|
||||||
return downloadAndExtractJDK(downloadUrl)
|
return downloadAndExtractJDK(downloadUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function findHighestJavaVersion(
|
export function findHighestJavaVersion(release: c.LatestReleaseResponse['data'], version: string): string {
|
||||||
release: c.LatestReleaseResponse['data'],
|
const graalVMIdentifierPattern = determineGraalVMLegacyIdentifier(false, version, '(\\d+)')
|
||||||
version: string
|
|
||||||
): string {
|
|
||||||
const graalVMIdentifierPattern = determineGraalVMLegacyIdentifier(
|
|
||||||
false,
|
|
||||||
version,
|
|
||||||
'(\\d+)'
|
|
||||||
)
|
|
||||||
const expectedFileNameRegExp = new RegExp(
|
const expectedFileNameRegExp = new RegExp(
|
||||||
`^${graalVMIdentifierPattern}${c.GRAALVM_FILE_EXTENSION.replace(
|
`^${graalVMIdentifierPattern}${c.GRAALVM_FILE_EXTENSION.replace(/\./g, '\\.')}$`
|
||||||
/\./g,
|
|
||||||
'\\.'
|
|
||||||
)}$`
|
|
||||||
)
|
)
|
||||||
let highestJavaVersion = 0
|
let highestJavaVersion = 0
|
||||||
for (const asset of release.assets) {
|
for (const asset of release.assets) {
|
||||||
@ -252,10 +200,7 @@ export function findHighestJavaVersion(
|
|||||||
|
|
||||||
// Support for GraalVM 22.X releases and earlier
|
// Support for GraalVM 22.X releases and earlier
|
||||||
|
|
||||||
export async function setUpGraalVMLatest_22_X(
|
export async function setUpGraalVMLatest_22_X(gdsToken: string, javaVersion: string): Promise<string> {
|
||||||
gdsToken: string,
|
|
||||||
javaVersion: string
|
|
||||||
): Promise<string> {
|
|
||||||
const lockedVersion = javaVersion === '19' ? '22.3.1' : '22.3.3'
|
const lockedVersion = javaVersion === '19' ? '22.3.1' : '22.3.3'
|
||||||
if (gdsToken.length > 0) {
|
if (gdsToken.length > 0) {
|
||||||
return setUpGraalVMRelease(gdsToken, lockedVersion, javaVersion)
|
return setUpGraalVMRelease(gdsToken, lockedVersion, javaVersion)
|
||||||
@ -277,32 +222,20 @@ export function findGraalVMVersion(release: c.LatestReleaseResponse['data']) {
|
|||||||
return tag_name.substring(GRAALVM_TAG_PREFIX.length, tag_name.length)
|
return tag_name.substring(GRAALVM_TAG_PREFIX.length, tag_name.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setUpGraalVMRelease(
|
export async function setUpGraalVMRelease(gdsToken: string, version: string, javaVersion: string): Promise<string> {
|
||||||
gdsToken: string,
|
|
||||||
version: string,
|
|
||||||
javaVersion: string
|
|
||||||
): Promise<string> {
|
|
||||||
const isEE = gdsToken.length > 0
|
const isEE = gdsToken.length > 0
|
||||||
const toolName = determineLegacyToolName(isEE, version, javaVersion)
|
const toolName = determineLegacyToolName(isEE, version, javaVersion)
|
||||||
let downloader: () => Promise<string>
|
let downloader: () => Promise<string>
|
||||||
if (isEE) {
|
if (isEE) {
|
||||||
downloader = async () =>
|
downloader = async () => downloadGraalVMEELegacy(gdsToken, version, javaVersion)
|
||||||
downloadGraalVMEELegacy(gdsToken, version, javaVersion)
|
|
||||||
} else {
|
} else {
|
||||||
downloader = async () => downloadGraalVMCELegacy(version, javaVersion)
|
downloader = async () => downloadGraalVMCELegacy(version, javaVersion)
|
||||||
}
|
}
|
||||||
return downloadExtractAndCacheJDK(downloader, toolName, version)
|
return downloadExtractAndCacheJDK(downloader, toolName, version)
|
||||||
}
|
}
|
||||||
|
|
||||||
function findDownloadUrl(
|
function findDownloadUrl(release: c.LatestReleaseResponse['data'], javaVersion: string): string {
|
||||||
release: c.LatestReleaseResponse['data'],
|
const graalVMIdentifier = determineGraalVMLegacyIdentifier(false, c.VERSION_DEV, javaVersion)
|
||||||
javaVersion: string
|
|
||||||
): string {
|
|
||||||
const graalVMIdentifier = determineGraalVMLegacyIdentifier(
|
|
||||||
false,
|
|
||||||
c.VERSION_DEV,
|
|
||||||
javaVersion
|
|
||||||
)
|
|
||||||
const expectedFileName = `${graalVMIdentifier}${c.GRAALVM_FILE_EXTENSION}`
|
const expectedFileName = `${graalVMIdentifier}${c.GRAALVM_FILE_EXTENSION}`
|
||||||
for (const asset of release.assets) {
|
for (const asset of release.assets) {
|
||||||
if (asset.name === expectedFileName) {
|
if (asset.name === expectedFileName) {
|
||||||
@ -314,34 +247,17 @@ function findDownloadUrl(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function determineGraalVMLegacyIdentifier(
|
function determineGraalVMLegacyIdentifier(isEE: boolean, version: string, javaVersion: string): string {
|
||||||
isEE: boolean,
|
return `${determineLegacyToolName(isEE, version, javaVersion)}-${c.GRAALVM_ARCH}-${version}`
|
||||||
version: string,
|
|
||||||
javaVersion: string
|
|
||||||
): string {
|
|
||||||
return `${determineLegacyToolName(isEE, version, javaVersion)}-${
|
|
||||||
c.GRAALVM_ARCH
|
|
||||||
}-${version}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function determineLegacyToolName(
|
function determineLegacyToolName(isEE: boolean, version: string, javaVersion: string): string {
|
||||||
isEE: boolean,
|
|
||||||
version: string,
|
|
||||||
javaVersion: string
|
|
||||||
): string {
|
|
||||||
const infix = isEE ? 'ee' : version === c.VERSION_DEV ? 'community' : 'ce'
|
const infix = isEE ? 'ee' : version === c.VERSION_DEV ? 'community' : 'ce'
|
||||||
return `graalvm-${infix}-java${javaVersion}-${c.GRAALVM_PLATFORM}`
|
return `graalvm-${infix}-java${javaVersion}-${c.GRAALVM_PLATFORM}`
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadGraalVMCELegacy(
|
async function downloadGraalVMCELegacy(version: string, javaVersion: string): Promise<string> {
|
||||||
version: string,
|
const graalVMIdentifier = determineGraalVMLegacyIdentifier(false, version, javaVersion)
|
||||||
javaVersion: string
|
|
||||||
): Promise<string> {
|
|
||||||
const graalVMIdentifier = determineGraalVMLegacyIdentifier(
|
|
||||||
false,
|
|
||||||
version,
|
|
||||||
javaVersion
|
|
||||||
)
|
|
||||||
const downloadUrl = `${GRAALVM_CE_DL_BASE}/${GRAALVM_TAG_PREFIX}${version}/${graalVMIdentifier}${c.GRAALVM_FILE_EXTENSION}`
|
const downloadUrl = `${GRAALVM_CE_DL_BASE}/${GRAALVM_TAG_PREFIX}${version}/${graalVMIdentifier}${c.GRAALVM_FILE_EXTENSION}`
|
||||||
try {
|
try {
|
||||||
return await downloadTool(downloadUrl)
|
return await downloadTool(downloadUrl)
|
||||||
@ -352,8 +268,6 @@ async function downloadGraalVMCELegacy(
|
|||||||
`Failed to download ${graalVMIdentifier}. Are you sure version: '${version}' and java-version: '${javaVersion}' are correct?`
|
`Failed to download ${graalVMIdentifier}. Are you sure version: '${version}' and java-version: '${javaVersion}' are correct?`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
throw new Error(
|
throw new Error(`Failed to download ${graalVMIdentifier} (error: ${error}).`)
|
||||||
`Failed to download ${graalVMIdentifier} (error: ${error}).`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
src/gu.ts
16
src/gu.ts
@ -1,9 +1,9 @@
|
|||||||
import * as c from './constants'
|
import * as c from './constants'
|
||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import * as semver from 'semver'
|
import * as semver from 'semver'
|
||||||
import {GRAALVM_PLATFORM} from './constants'
|
import { GRAALVM_PLATFORM } from './constants'
|
||||||
import {exec} from './utils'
|
import { exec } from './utils'
|
||||||
import {join} from 'path'
|
import { join } from 'path'
|
||||||
|
|
||||||
const BASE_FLAGS = ['--non-interactive', 'install', '--no-progress']
|
const BASE_FLAGS = ['--non-interactive', 'install', '--no-progress']
|
||||||
const COMPONENT_TO_POST_INSTALL_HOOK = new Map<string, Map<string, string>>([
|
const COMPONENT_TO_POST_INSTALL_HOOK = new Map<string, Map<string, string>>([
|
||||||
@ -52,19 +52,13 @@ export async function setUpGUComponents(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if (graalVMVersion.startsWith(c.MANDREL_NAMESPACE)) {
|
} else if (graalVMVersion.startsWith(c.MANDREL_NAMESPACE)) {
|
||||||
core.warning(
|
core.warning(`Mandrel does not support GraalVM component(s): '${components.join(',')}'`)
|
||||||
`Mandrel does not support GraalVM component(s): '${components.join(',')}'`
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
await installGUComponents(gdsToken, graalVMHome, components)
|
await installGUComponents(gdsToken, graalVMHome, components)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function installGUComponents(
|
async function installGUComponents(gdsToken: string, graalVMHome: string, components: string[]): Promise<void> {
|
||||||
gdsToken: string,
|
|
||||||
graalVMHome: string,
|
|
||||||
components: string[]
|
|
||||||
): Promise<void> {
|
|
||||||
await exec('gu', BASE_FLAGS.concat(components), {
|
await exec('gu', BASE_FLAGS.concat(components), {
|
||||||
env: {
|
env: {
|
||||||
...process.env,
|
...process.env,
|
||||||
|
@ -1,35 +1,22 @@
|
|||||||
import * as c from './constants'
|
import * as c from './constants'
|
||||||
import * as semver from 'semver'
|
import * as semver from 'semver'
|
||||||
import {
|
import { downloadExtractAndCacheJDK, getTaggedRelease, getMatchingTags } from './utils'
|
||||||
downloadExtractAndCacheJDK,
|
import { downloadTool } from '@actions/tool-cache'
|
||||||
getTaggedRelease,
|
import { spawnSync } from 'child_process'
|
||||||
getMatchingTags
|
|
||||||
} from './utils'
|
|
||||||
import {downloadTool} from '@actions/tool-cache'
|
|
||||||
import {spawnSync} from 'child_process'
|
|
||||||
|
|
||||||
const LIBERICA_GH_USER = 'bell-sw'
|
const LIBERICA_GH_USER = 'bell-sw'
|
||||||
const LIBERICA_RELEASES_REPO = 'LibericaNIK'
|
const LIBERICA_RELEASES_REPO = 'LibericaNIK'
|
||||||
const LIBERICA_JDK_TAG_PREFIX = 'jdk-'
|
const LIBERICA_JDK_TAG_PREFIX = 'jdk-'
|
||||||
const LIBERICA_VM_PREFIX = 'bellsoft-liberica-vm-'
|
const LIBERICA_VM_PREFIX = 'bellsoft-liberica-vm-'
|
||||||
|
|
||||||
export async function setUpLiberica(
|
export async function setUpLiberica(javaVersion: string, javaPackage: string): Promise<string> {
|
||||||
javaVersion: string,
|
|
||||||
javaPackage: string
|
|
||||||
): Promise<string> {
|
|
||||||
const resolvedJavaVersion = await findLatestLibericaJavaVersion(javaVersion)
|
const resolvedJavaVersion = await findLatestLibericaJavaVersion(javaVersion)
|
||||||
const downloadUrl = await findLibericaURL(resolvedJavaVersion, javaPackage)
|
const downloadUrl = await findLibericaURL(resolvedJavaVersion, javaPackage)
|
||||||
const toolName = determineToolName(javaVersion, javaPackage)
|
const toolName = determineToolName(javaVersion, javaPackage)
|
||||||
return downloadExtractAndCacheJDK(
|
return downloadExtractAndCacheJDK(async () => downloadTool(downloadUrl), toolName, javaVersion)
|
||||||
async () => downloadTool(downloadUrl),
|
|
||||||
toolName,
|
|
||||||
javaVersion
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function findLatestLibericaJavaVersion(
|
export async function findLatestLibericaJavaVersion(javaVersion: string): Promise<string> {
|
||||||
javaVersion: string
|
|
||||||
): Promise<string> {
|
|
||||||
const matchingRefs = await getMatchingTags(
|
const matchingRefs = await getMatchingTags(
|
||||||
LIBERICA_GH_USER,
|
LIBERICA_GH_USER,
|
||||||
LIBERICA_RELEASES_REPO,
|
LIBERICA_RELEASES_REPO,
|
||||||
@ -44,8 +31,7 @@ export async function findLatestLibericaJavaVersion(
|
|||||||
if (
|
if (
|
||||||
semver.valid(version) &&
|
semver.valid(version) &&
|
||||||
// pattern '17.0.1' should match '17.0.1+12' but not '17.0.10'
|
// pattern '17.0.1' should match '17.0.1+12' but not '17.0.10'
|
||||||
(version.length <= patternLength ||
|
(version.length <= patternLength || !isDigit(version.charAt(patternLength))) &&
|
||||||
!isDigit(version.charAt(patternLength))) &&
|
|
||||||
semver.compareBuild(version, bestMatch) == 1
|
semver.compareBuild(version, bestMatch) == 1
|
||||||
) {
|
) {
|
||||||
bestMatch = version
|
bestMatch = version
|
||||||
@ -59,25 +45,17 @@ export async function findLatestLibericaJavaVersion(
|
|||||||
return bestMatch
|
return bestMatch
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function findLibericaURL(
|
export async function findLibericaURL(javaVersion: string, javaPackage: string): Promise<string> {
|
||||||
javaVersion: string,
|
|
||||||
javaPackage: string
|
|
||||||
): Promise<string> {
|
|
||||||
const release = await getTaggedRelease(
|
const release = await getTaggedRelease(
|
||||||
LIBERICA_GH_USER,
|
LIBERICA_GH_USER,
|
||||||
LIBERICA_RELEASES_REPO,
|
LIBERICA_RELEASES_REPO,
|
||||||
LIBERICA_JDK_TAG_PREFIX + javaVersion
|
LIBERICA_JDK_TAG_PREFIX + javaVersion
|
||||||
)
|
)
|
||||||
const platform = determinePlatformPart()
|
const platform = determinePlatformPart()
|
||||||
const assetPrefix = `${LIBERICA_VM_PREFIX}${determineVariantPart(
|
const assetPrefix = `${LIBERICA_VM_PREFIX}${determineVariantPart(javaPackage)}openjdk${javaVersion}`
|
||||||
javaPackage
|
|
||||||
)}openjdk${javaVersion}`
|
|
||||||
const assetSuffix = `-${platform}${c.GRAALVM_FILE_EXTENSION}`
|
const assetSuffix = `-${platform}${c.GRAALVM_FILE_EXTENSION}`
|
||||||
for (const asset of release.assets) {
|
for (const asset of release.assets) {
|
||||||
if (
|
if (asset.name.startsWith(assetPrefix) && asset.name.endsWith(assetSuffix)) {
|
||||||
asset.name.startsWith(assetPrefix) &&
|
|
||||||
asset.name.endsWith(assetSuffix)
|
|
||||||
) {
|
|
||||||
return asset.browser_download_url
|
return asset.browser_download_url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
86
src/main.ts
86
src/main.ts
@ -2,45 +2,37 @@ import * as c from './constants'
|
|||||||
import * as core from '@actions/core'
|
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 {basename, 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 { 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'
|
import { exec } from '@actions/exec'
|
||||||
|
import { setUpSBOMSupport } from './features/sbom'
|
||||||
|
|
||||||
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 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)
|
||||||
const componentsString: string = core.getInput(c.INPUT_COMPONENTS)
|
const componentsString: string = core.getInput(c.INPUT_COMPONENTS)
|
||||||
const components: string[] =
|
const components: string[] = componentsString.length > 0 ? componentsString.split(',').map((x) => x.trim()) : []
|
||||||
componentsString.length > 0
|
|
||||||
? componentsString.split(',').map(x => x.trim())
|
|
||||||
: []
|
|
||||||
const setJavaHome = core.getInput(c.INPUT_SET_JAVA_HOME) === 'true'
|
const setJavaHome = core.getInput(c.INPUT_SET_JAVA_HOME) === 'true'
|
||||||
const cache = core.getInput(c.INPUT_CACHE)
|
const cache = core.getInput(c.INPUT_CACHE)
|
||||||
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 =
|
const isGraalVMforJDK17OrLater = distribution.length > 0 || graalVMVersion.length == 0
|
||||||
distribution.length > 0 || graalVMVersion.length == 0
|
|
||||||
|
|
||||||
if (c.IS_WINDOWS) {
|
if (c.IS_WINDOWS) {
|
||||||
setUpWindowsEnvironment(
|
setUpWindowsEnvironment(javaVersion, graalVMVersion, isGraalVMforJDK17OrLater)
|
||||||
javaVersion,
|
|
||||||
graalVMVersion,
|
|
||||||
isGraalVMforJDK17OrLater
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
await setUpDependencies(components)
|
await setUpDependencies(components)
|
||||||
if (enableNativeImageMusl) {
|
if (enableNativeImageMusl) {
|
||||||
@ -52,8 +44,7 @@ async function run(): Promise<void> {
|
|||||||
if (isGraalVMforJDK17OrLater) {
|
if (isGraalVMforJDK17OrLater) {
|
||||||
if (
|
if (
|
||||||
enableCheckForUpdates &&
|
enableCheckForUpdates &&
|
||||||
(distribution === c.DISTRIBUTION_GRAALVM ||
|
(distribution === c.DISTRIBUTION_GRAALVM || distribution === c.DISTRIBUTION_GRAALVM_COMMUNITY)
|
||||||
distribution === c.DISTRIBUTION_GRAALVM_COMMUNITY)
|
|
||||||
) {
|
) {
|
||||||
checkForUpdates(graalVMVersion, javaVersion)
|
checkForUpdates(graalVMVersion, javaVersion)
|
||||||
}
|
}
|
||||||
@ -92,30 +83,21 @@ async function run(): Promise<void> {
|
|||||||
case c.VERSION_LATEST:
|
case c.VERSION_LATEST:
|
||||||
if (
|
if (
|
||||||
javaVersion.startsWith('17') ||
|
javaVersion.startsWith('17') ||
|
||||||
(coercedJavaVersion !== null &&
|
(coercedJavaVersion !== null && semver.gte(coercedJavaVersion, '20.0.0'))
|
||||||
semver.gte(coercedJavaVersion, '20.0.0'))
|
|
||||||
) {
|
) {
|
||||||
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, gdsToken)
|
graalVMHome = await graalvm.setUpGraalVMJDK(javaVersion, gdsToken)
|
||||||
} else {
|
} else {
|
||||||
graalVMHome = await graalvm.setUpGraalVMLatest_22_X(
|
graalVMHome = await graalvm.setUpGraalVMLatest_22_X(gdsToken, javaVersion)
|
||||||
gdsToken,
|
|
||||||
javaVersion
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case c.VERSION_DEV:
|
case c.VERSION_DEV:
|
||||||
if (gdsToken.length > 0) {
|
if (gdsToken.length > 0) {
|
||||||
throw new Error(
|
throw new Error('Downloading GraalVM EE dev builds is not supported')
|
||||||
'Downloading GraalVM EE dev builds is not supported'
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (
|
if (coercedJavaVersion !== null && !semver.gte(coercedJavaVersion, '21.0.0')) {
|
||||||
coercedJavaVersion !== null &&
|
|
||||||
!semver.gte(coercedJavaVersion, '21.0.0')
|
|
||||||
) {
|
|
||||||
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}.`
|
||||||
)
|
)
|
||||||
@ -131,11 +113,7 @@ async function run(): Promise<void> {
|
|||||||
if (enableCheckForUpdates) {
|
if (enableCheckForUpdates) {
|
||||||
checkForUpdates(graalVMVersion, javaVersion)
|
checkForUpdates(graalVMVersion, javaVersion)
|
||||||
}
|
}
|
||||||
graalVMHome = await graalvm.setUpGraalVMRelease(
|
graalVMHome = await graalvm.setUpGraalVMRelease(gdsToken, graalVMVersion, javaVersion)
|
||||||
gdsToken,
|
|
||||||
graalVMVersion,
|
|
||||||
javaVersion
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -148,23 +126,13 @@ async function run(): Promise<void> {
|
|||||||
if (setJavaHome) {
|
if (setJavaHome) {
|
||||||
core.exportVariable('JAVA_HOME', graalVMHome)
|
core.exportVariable('JAVA_HOME', graalVMHome)
|
||||||
}
|
}
|
||||||
|
await setUpGUComponents(javaVersion, graalVMVersion, graalVMHome, components, gdsToken)
|
||||||
await setUpGUComponents(
|
|
||||||
javaVersion,
|
|
||||||
graalVMVersion,
|
|
||||||
graalVMHome,
|
|
||||||
components,
|
|
||||||
gdsToken
|
|
||||||
)
|
|
||||||
|
|
||||||
if (cache && isCacheAvailable()) {
|
if (cache && isCacheAvailable()) {
|
||||||
await restore(cache)
|
await restore(cache)
|
||||||
}
|
}
|
||||||
setUpNativeImageBuildReports(
|
setUpNativeImageBuildReports(isGraalVMforJDK17OrLater, javaVersion, graalVMVersion)
|
||||||
isGraalVMforJDK17OrLater,
|
setUpSBOMSupport(javaVersion, distribution)
|
||||||
javaVersion,
|
|
||||||
graalVMVersion
|
|
||||||
)
|
|
||||||
|
|
||||||
core.startGroup(`Successfully set up '${basename(graalVMHome)}'`)
|
core.startGroup(`Successfully set up '${basename(graalVMHome)}'`)
|
||||||
await exec(join(graalVMHome, 'bin', `java${c.EXECUTABLE_SUFFIX}`), [
|
await exec(join(graalVMHome, 'bin', `java${c.EXECUTABLE_SUFFIX}`), [
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import * as c from './constants'
|
import * as c from './constants'
|
||||||
import * as httpClient from '@actions/http-client'
|
import * as httpClient from '@actions/http-client'
|
||||||
import {downloadExtractAndCacheJDK, getLatestRelease} from './utils'
|
import { downloadExtractAndCacheJDK } from './utils'
|
||||||
import {downloadTool} from '@actions/tool-cache'
|
import { downloadTool } from '@actions/tool-cache'
|
||||||
import {basename} from 'path'
|
import { basename } from 'path'
|
||||||
|
|
||||||
export const MANDREL_REPO = 'mandrel'
|
export const MANDREL_REPO = 'mandrel'
|
||||||
export const MANDREL_TAG_PREFIX = c.MANDREL_NAMESPACE
|
export const MANDREL_TAG_PREFIX = c.MANDREL_NAMESPACE
|
||||||
@ -11,18 +11,19 @@ const DISCO_API_BASE = 'https://api.foojay.io/disco/v3.0/packages/jdks'
|
|||||||
|
|
||||||
interface JdkData {
|
interface JdkData {
|
||||||
message: string
|
message: string
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
result: any
|
result: any
|
||||||
|
/* eslint-enable @typescript-eslint/no-explicit-any */
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setUpMandrel(
|
export async function setUpMandrel(mandrelVersion: string, javaVersion: string): Promise<string> {
|
||||||
mandrelVersion: string,
|
|
||||||
javaVersion: string
|
|
||||||
): Promise<string> {
|
|
||||||
const version = stripMandrelNamespace(mandrelVersion)
|
const version = stripMandrelNamespace(mandrelVersion)
|
||||||
let mandrelHome
|
let mandrelHome
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case '':
|
case '':
|
||||||
// fetch latest if no version is specified
|
// fetch latest if no version is specified
|
||||||
|
mandrelHome = await setUpMandrelLatest(javaVersion)
|
||||||
|
break
|
||||||
case 'latest':
|
case 'latest':
|
||||||
mandrelHome = await setUpMandrelLatest(javaVersion)
|
mandrelHome = await setUpMandrelLatest(javaVersion)
|
||||||
break
|
break
|
||||||
@ -40,11 +41,7 @@ async function setUpMandrelLatest(javaVersion: string): Promise<string> {
|
|||||||
const version = stripMandrelNamespace(version_tag)
|
const version = stripMandrelNamespace(version_tag)
|
||||||
|
|
||||||
const toolName = determineToolName(javaVersion)
|
const toolName = determineToolName(javaVersion)
|
||||||
return downloadExtractAndCacheJDK(
|
return downloadExtractAndCacheJDK(async () => downloadTool(latest_release_url), toolName, version)
|
||||||
async () => downloadTool(latest_release_url),
|
|
||||||
toolName,
|
|
||||||
version
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Download URIs are of the form https://github.com/graalvm/mandrel/releases/download/<tag>/<archive-name>
|
// Download URIs are of the form https://github.com/graalvm/mandrel/releases/download/<tag>/<archive-name>
|
||||||
@ -57,29 +54,19 @@ function getTagFromURI(uri: string): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getLatestMandrelReleaseUrl(
|
export async function getLatestMandrelReleaseUrl(javaVersion: string): Promise<string> {
|
||||||
javaVersion: string
|
|
||||||
): Promise<string> {
|
|
||||||
const url = `${DISCO_API_BASE}?jdk_version=${javaVersion}&distribution=${c.DISTRIBUTION_MANDREL}&architecture=${c.JDK_ARCH}&operating_system=${c.JDK_PLATFORM}&latest=per_distro`
|
const url = `${DISCO_API_BASE}?jdk_version=${javaVersion}&distribution=${c.DISTRIBUTION_MANDREL}&architecture=${c.JDK_ARCH}&operating_system=${c.JDK_PLATFORM}&latest=per_distro`
|
||||||
const _http = new httpClient.HttpClient()
|
const _http = new httpClient.HttpClient()
|
||||||
const response = await _http.getJson<JdkData>(url)
|
const response = await _http.getJson<JdkData>(url)
|
||||||
if (response.statusCode !== 200) {
|
if (response.statusCode !== 200) {
|
||||||
throw new Error(
|
throw new Error(`Failed to fetch latest Mandrel release for Java ${javaVersion} from DISCO API: ${response.result}`)
|
||||||
`Failed to fetch latest Mandrel release for Java ${javaVersion} from DISCO API: ${response.result}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
const result = response.result?.result[0]
|
const result = response.result?.result[0]
|
||||||
try {
|
try {
|
||||||
const pkg_info_uri = result.links.pkg_info_uri
|
const pkg_info_uri = result.links.pkg_info_uri
|
||||||
return await getLatestMandrelReleaseUrlHelper(
|
return await getLatestMandrelReleaseUrlHelper(_http, javaVersion, pkg_info_uri)
|
||||||
_http,
|
|
||||||
javaVersion,
|
|
||||||
pkg_info_uri
|
|
||||||
)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(
|
throw new Error(`Failed to get latest Mandrel release for Java ${javaVersion} from DISCO API: ${error}`)
|
||||||
`Failed to get latest Mandrel release for Java ${javaVersion} from DISCO API: ${error}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,22 +91,12 @@ async function getLatestMandrelReleaseUrlHelper(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setUpMandrelRelease(
|
async function setUpMandrelRelease(version: string, javaVersion: string): Promise<string> {
|
||||||
version: string,
|
|
||||||
javaVersion: string
|
|
||||||
): Promise<string> {
|
|
||||||
const toolName = determineToolName(javaVersion)
|
const toolName = determineToolName(javaVersion)
|
||||||
return downloadExtractAndCacheJDK(
|
return downloadExtractAndCacheJDK(async () => downloadMandrelJDK(version, javaVersion), toolName, version)
|
||||||
async () => downloadMandrelJDK(version, javaVersion),
|
|
||||||
toolName,
|
|
||||||
version
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadMandrelJDK(
|
async function downloadMandrelJDK(version: string, javaVersion: string): Promise<string> {
|
||||||
version: string,
|
|
||||||
javaVersion: string
|
|
||||||
): Promise<string> {
|
|
||||||
const identifier = determineMandrelIdentifier(version, javaVersion)
|
const identifier = determineMandrelIdentifier(version, javaVersion)
|
||||||
const downloadUrl = `${MANDREL_DL_BASE}/${MANDREL_TAG_PREFIX}${version}/${identifier}${c.GRAALVM_FILE_EXTENSION}`
|
const downloadUrl = `${MANDREL_DL_BASE}/${MANDREL_TAG_PREFIX}${version}/${identifier}${c.GRAALVM_FILE_EXTENSION}`
|
||||||
try {
|
try {
|
||||||
@ -133,16 +110,11 @@ async function downloadMandrelJDK(
|
|||||||
)}. Are you sure version: '${version}' and java-version: '${javaVersion}' are correct?`
|
)}. Are you sure version: '${version}' and java-version: '${javaVersion}' are correct?`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
throw new Error(
|
throw new Error(`Failed to download ${basename(downloadUrl)} (error: ${error}).`)
|
||||||
`Failed to download ${basename(downloadUrl)} (error: ${error}).`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function determineMandrelIdentifier(
|
function determineMandrelIdentifier(version: string, javaVersion: string): string {
|
||||||
version: string,
|
|
||||||
javaVersion: string
|
|
||||||
): string {
|
|
||||||
return `mandrel-java${javaVersion}-${c.GRAALVM_PLATFORM}-${c.GRAALVM_ARCH}-${version}`
|
return `mandrel-java${javaVersion}-${c.GRAALVM_PLATFORM}-${c.GRAALVM_ARCH}-${version}`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,10 +124,7 @@ function determineToolName(javaVersion: string): string {
|
|||||||
|
|
||||||
export function stripMandrelNamespace(graalVMVersion: string) {
|
export function stripMandrelNamespace(graalVMVersion: string) {
|
||||||
if (graalVMVersion.startsWith(c.MANDREL_NAMESPACE)) {
|
if (graalVMVersion.startsWith(c.MANDREL_NAMESPACE)) {
|
||||||
return graalVMVersion.substring(
|
return graalVMVersion.substring(c.MANDREL_NAMESPACE.length, graalVMVersion.length)
|
||||||
c.MANDREL_NAMESPACE.length,
|
|
||||||
graalVMVersion.length
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
return graalVMVersion
|
return graalVMVersion
|
||||||
}
|
}
|
||||||
|
26
src/msvc.ts
26
src/msvc.ts
@ -1,8 +1,7 @@
|
|||||||
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'
|
|
||||||
|
|
||||||
// Keep in sync with https://github.com/actions/virtual-environments
|
// Keep in sync with https://github.com/actions/virtual-environments
|
||||||
const KNOWN_VISUAL_STUDIO_INSTALLATIONS = [
|
const KNOWN_VISUAL_STUDIO_INSTALLATIONS = [
|
||||||
@ -12,9 +11,7 @@ const KNOWN_VISUAL_STUDIO_INSTALLATIONS = [
|
|||||||
]
|
]
|
||||||
if (process.env['VSINSTALLDIR']) {
|
if (process.env['VSINSTALLDIR']) {
|
||||||
// if VSINSTALLDIR is set, make it the first known installation
|
// if VSINSTALLDIR is set, make it the first known installation
|
||||||
KNOWN_VISUAL_STUDIO_INSTALLATIONS.unshift(
|
KNOWN_VISUAL_STUDIO_INSTALLATIONS.unshift(process.env['VSINSTALLDIR'].replace(/\\$/, ''))
|
||||||
process.env['VSINSTALLDIR'].replace(/\\$/, '')
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
const VCVARSALL_SUBPATH = 'VC\\Auxiliary\\Build\\vcvarsall.bat'
|
const VCVARSALL_SUBPATH = 'VC\\Auxiliary\\Build\\vcvarsall.bat'
|
||||||
|
|
||||||
@ -46,13 +43,7 @@ export function setUpWindowsEnvironment(
|
|||||||
graalVMVersion: string,
|
graalVMVersion: string,
|
||||||
isGraalVMforJDK17OrLater: boolean
|
isGraalVMforJDK17OrLater: boolean
|
||||||
): void {
|
): void {
|
||||||
if (
|
if (!needsWindowsEnvironmentSetup(javaVersion, graalVMVersion, isGraalVMforJDK17OrLater)) {
|
||||||
!needsWindowsEnvironmentSetup(
|
|
||||||
javaVersion,
|
|
||||||
graalVMVersion,
|
|
||||||
isGraalVMforJDK17OrLater
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,10 +51,9 @@ export function setUpWindowsEnvironment(
|
|||||||
|
|
||||||
const vcvarsallPath = findVcvarsallPath()
|
const vcvarsallPath = findVcvarsallPath()
|
||||||
core.debug(`Calling "${vcvarsallPath}"...`)
|
core.debug(`Calling "${vcvarsallPath}"...`)
|
||||||
const [originalEnv, vcvarsallOutput, updatedEnv] = execSync(
|
const [originalEnv, vcvarsallOutput, updatedEnv] = execSync(`set && cls && "${vcvarsallPath}" x64 && cls && set`, {
|
||||||
`set && cls && "${vcvarsallPath}" x64 && cls && set`,
|
shell: 'cmd'
|
||||||
{shell: 'cmd'}
|
})
|
||||||
)
|
|
||||||
.toString()
|
.toString()
|
||||||
.split('\f') // form feed page break (printed by `cls`)
|
.split('\f') // form feed page break (printed by `cls`)
|
||||||
core.debug(vcvarsallOutput)
|
core.debug(vcvarsallOutput)
|
||||||
|
125
src/utils.ts
125
src/utils.ts
@ -4,11 +4,13 @@ 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 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 * as fs from 'fs'
|
||||||
import {readFileSync, readdirSync} from 'fs'
|
import { ExecOptions, exec as e } from '@actions/exec'
|
||||||
import {Octokit} from '@octokit/core'
|
import { readFileSync, readdirSync } from 'fs'
|
||||||
import {createHash} from 'crypto'
|
import { Octokit } from '@octokit/core'
|
||||||
import {join} from 'path'
|
import { createHash } from 'crypto'
|
||||||
|
import { join } from 'path'
|
||||||
|
import { tmpdir } from 'os'
|
||||||
|
|
||||||
// Set up Octokit for github.com only and in the same way as @actions/github (see https://git.io/Jy9YP)
|
// Set up Octokit for github.com only and in the same way as @actions/github (see https://git.io/Jy9YP)
|
||||||
const baseUrl = 'https://api.github.com'
|
const baseUrl = 'https://api.github.com'
|
||||||
@ -19,26 +21,16 @@ const GitHubDotCom = Octokit.defaults({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export async function exec(
|
export async function exec(commandLine: string, args?: string[], options?: ExecOptions | undefined): Promise<void> {
|
||||||
commandLine: string,
|
|
||||||
args?: string[],
|
|
||||||
options?: ExecOptions | undefined
|
|
||||||
): Promise<void> {
|
|
||||||
const exitCode = await e(commandLine, args, options)
|
const exitCode = await e(commandLine, args, options)
|
||||||
if (exitCode !== 0) {
|
if (exitCode !== 0) {
|
||||||
throw new Error(
|
throw new Error(`'${[commandLine].concat(args || []).join(' ')}' exited with a non-zero code: ${exitCode}`)
|
||||||
`'${[commandLine]
|
|
||||||
.concat(args || [])
|
|
||||||
.join(' ')}' exited with a non-zero code: ${exitCode}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getLatestRelease(
|
export async function getLatestRelease(repo: string): Promise<c.LatestReleaseResponse['data']> {
|
||||||
repo: string
|
|
||||||
): Promise<c.LatestReleaseResponse['data']> {
|
|
||||||
const githubToken = getGitHubToken()
|
const githubToken = getGitHubToken()
|
||||||
const options = githubToken.length > 0 ? {auth: githubToken} : {}
|
const options = githubToken.length > 0 ? { auth: githubToken } : {}
|
||||||
const octokit = new GitHubDotCom(options)
|
const octokit = new GitHubDotCom(options)
|
||||||
return (
|
return (
|
||||||
await octokit.request('GET /repos/{owner}/{repo}/releases/latest', {
|
await octokit.request('GET /repos/{owner}/{repo}/releases/latest', {
|
||||||
@ -48,12 +40,9 @@ export async function getLatestRelease(
|
|||||||
).data
|
).data
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getContents(
|
export async function getContents(repo: string, path: string): Promise<c.ContentsResponse['data']> {
|
||||||
repo: string,
|
|
||||||
path: string
|
|
||||||
): Promise<c.ContentsResponse['data']> {
|
|
||||||
const githubToken = getGitHubToken()
|
const githubToken = getGitHubToken()
|
||||||
const options = githubToken.length > 0 ? {auth: githubToken} : {}
|
const options = githubToken.length > 0 ? { auth: githubToken } : {}
|
||||||
const octokit = new GitHubDotCom(options)
|
const octokit = new GitHubDotCom(options)
|
||||||
return (
|
return (
|
||||||
await octokit.request('GET /repos/{owner}/{repo}/contents/{path}', {
|
await octokit.request('GET /repos/{owner}/{repo}/contents/{path}', {
|
||||||
@ -70,7 +59,7 @@ export async function getTaggedRelease(
|
|||||||
tag: string
|
tag: string
|
||||||
): Promise<c.LatestReleaseResponse['data']> {
|
): Promise<c.LatestReleaseResponse['data']> {
|
||||||
const githubToken = getGitHubToken()
|
const githubToken = getGitHubToken()
|
||||||
const options = githubToken.length > 0 ? {auth: githubToken} : {}
|
const options = githubToken.length > 0 ? { auth: githubToken } : {}
|
||||||
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}', {
|
||||||
@ -87,26 +76,19 @@ export async function getMatchingTags(
|
|||||||
tagPrefix: string
|
tagPrefix: string
|
||||||
): Promise<c.MatchingRefsResponse['data']> {
|
): Promise<c.MatchingRefsResponse['data']> {
|
||||||
const githubToken = getGitHubToken()
|
const githubToken = getGitHubToken()
|
||||||
const options = githubToken.length > 0 ? {auth: githubToken} : {}
|
const options = githubToken.length > 0 ? { auth: githubToken } : {}
|
||||||
const octokit = new GitHubDotCom(options)
|
const octokit = new GitHubDotCom(options)
|
||||||
return (
|
return (
|
||||||
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,
|
||||||
{
|
repo,
|
||||||
owner,
|
tagPrefix
|
||||||
repo,
|
})
|
||||||
tagPrefix
|
|
||||||
}
|
|
||||||
)
|
|
||||||
).data
|
).data
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function downloadAndExtractJDK(
|
export async function downloadAndExtractJDK(downloadUrl: string): Promise<string> {
|
||||||
downloadUrl: string
|
return findJavaHomeInSubfolder(await extract(await tc.downloadTool(downloadUrl)))
|
||||||
): Promise<string> {
|
|
||||||
return findJavaHomeInSubfolder(
|
|
||||||
await extract(await tc.downloadTool(downloadUrl))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function downloadExtractAndCacheJDK(
|
export async function downloadExtractAndCacheJDK(
|
||||||
@ -138,9 +120,7 @@ async function extract(downloadPath: string): Promise<string> {
|
|||||||
} else if (c.GRAALVM_FILE_EXTENSION === '.zip') {
|
} else if (c.GRAALVM_FILE_EXTENSION === '.zip') {
|
||||||
return await tc.extractZip(downloadPath)
|
return await tc.extractZip(downloadPath)
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(`Unexpected filetype downloaded: ${c.GRAALVM_FILE_EXTENSION}`)
|
||||||
`Unexpected filetype downloaded: ${c.GRAALVM_FILE_EXTENSION}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,9 +129,7 @@ function findJavaHomeInSubfolder(searchPath: string): string {
|
|||||||
if (baseContents.length === 1) {
|
if (baseContents.length === 1) {
|
||||||
return join(searchPath, baseContents[0], c.JDK_HOME_SUFFIX)
|
return join(searchPath, baseContents[0], c.JDK_HOME_SUFFIX)
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(`Unexpected amount of directory items found: ${baseContents.length}`)
|
||||||
`Unexpected amount of directory items found: ${baseContents.length}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,9 +147,7 @@ export function toSemVer(version: string): string {
|
|||||||
const suffix = versionParts.length === 2 ? '-' + versionParts[1] : ''
|
const suffix = versionParts.length === 2 ? '-' + versionParts[1] : ''
|
||||||
const validVersion = semver.valid(semver.coerce(versionParts[0]) + suffix)
|
const validVersion = semver.valid(semver.coerce(versionParts[0]) + suffix)
|
||||||
if (!validVersion) {
|
if (!validVersion) {
|
||||||
throw new Error(
|
throw new Error(`Unable to convert '${version}' to semantic version. ${c.ERROR_HINT}`)
|
||||||
`Unable to convert '${version}' to semantic version. ${c.ERROR_HINT}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return validVersion
|
return validVersion
|
||||||
}
|
}
|
||||||
@ -184,9 +160,7 @@ function getGitHubToken(): string {
|
|||||||
return core.getInput(c.INPUT_GITHUB_TOKEN)
|
return core.getInput(c.INPUT_GITHUB_TOKEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function findExistingPRCommentId(
|
export async function findExistingPRCommentId(bodyStartsWith: string): Promise<number | undefined> {
|
||||||
bodyStartsWith: string
|
|
||||||
): Promise<number | undefined> {
|
|
||||||
if (!isPREvent()) {
|
if (!isPREvent()) {
|
||||||
throw new Error('Not a PR event.')
|
throw new Error('Not a PR event.')
|
||||||
}
|
}
|
||||||
@ -198,7 +172,7 @@ export async function findExistingPRCommentId(
|
|||||||
...context.repo,
|
...context.repo,
|
||||||
issue_number: context.payload.pull_request?.number as number
|
issue_number: context.payload.pull_request?.number as number
|
||||||
})
|
})
|
||||||
const matchingComment = comments.reverse().find(comment => {
|
const matchingComment = comments.reverse().find((comment) => {
|
||||||
return comment.body && comment.body.startsWith(bodyStartsWith)
|
return comment.body && comment.body.startsWith(bodyStartsWith)
|
||||||
})
|
})
|
||||||
return matchingComment ? matchingComment.id : undefined
|
return matchingComment ? matchingComment.id : undefined
|
||||||
@ -209,10 +183,7 @@ export async function findExistingPRCommentId(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updatePRComment(
|
export async function updatePRComment(content: string, commentId: number): Promise<void> {
|
||||||
content: string,
|
|
||||||
commentId: number
|
|
||||||
): Promise<void> {
|
|
||||||
if (!isPREvent()) {
|
if (!isPREvent()) {
|
||||||
throw new Error('Not a PR event.')
|
throw new Error('Not a PR event.')
|
||||||
}
|
}
|
||||||
@ -247,3 +218,43 @@ export async function createPRComment(content: string): Promise<void> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function tmpfile(fileName: string) {
|
||||||
|
return join(tmpdir(), fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
export 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[c.NATIVE_IMAGE_OPTIONS_ENV]
|
||||||
|
if (existingOptions) {
|
||||||
|
newOptionValue = `${existingOptions} ${newOptionValue}`
|
||||||
|
}
|
||||||
|
core.exportVariable(c.NATIVE_IMAGE_OPTIONS_ENV, newOptionValue)
|
||||||
|
} else {
|
||||||
|
const optionsFile = getNativeImageOptionsFile()
|
||||||
|
if (fs.existsSync(optionsFile)) {
|
||||||
|
fs.appendFileSync(optionsFile, ` ${optionValue}`)
|
||||||
|
} else {
|
||||||
|
fs.writeFileSync(optionsFile, `NativeImageArgs = ${optionValue}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const NATIVE_IMAGE_CONFIG_FILE = tmpfile('native-image-options.properties')
|
||||||
|
const NATIVE_IMAGE_CONFIG_FILE_ENV = 'NATIVE_IMAGE_CONFIG_FILE'
|
||||||
|
|
||||||
|
function getNativeImageOptionsFile(): string {
|
||||||
|
let optionsFile = process.env[NATIVE_IMAGE_CONFIG_FILE_ENV]
|
||||||
|
if (optionsFile === undefined) {
|
||||||
|
optionsFile = NATIVE_IMAGE_CONFIG_FILE
|
||||||
|
core.exportVariable(NATIVE_IMAGE_CONFIG_FILE_ENV, optionsFile)
|
||||||
|
}
|
||||||
|
return optionsFile
|
||||||
|
}
|
||||||
|
23
tsconfig.base.json
Normal file
23
tsconfig.base.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"declaration": false,
|
||||||
|
"declarationMap": false,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"lib": ["ES2022"],
|
||||||
|
"module": "NodeNext",
|
||||||
|
"moduleResolution": "NodeNext",
|
||||||
|
"newLine": "lf",
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"pretty": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"strict": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"target": "ES2022"
|
||||||
|
}
|
||||||
|
}
|
10
tsconfig.eslint.json
Normal file
10
tsconfig.eslint.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"extends": "./tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowJs": true,
|
||||||
|
"noEmit": true
|
||||||
|
},
|
||||||
|
"exclude": ["dist", "node_modules"],
|
||||||
|
"include": ["__tests__", "src", "eslint.config.mjs", "jest.config.js"]
|
||||||
|
}
|
@ -1,12 +1,11 @@
|
|||||||
{
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"extends": "./tsconfig.base.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
"module": "NodeNext",
|
||||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
"moduleResolution": "NodeNext",
|
||||||
"outDir": "./lib", /* Redirect output structure to the directory. */
|
"outDir": "./dist"
|
||||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
|
||||||
"strict": true, /* Enable all strict type-checking options. */
|
|
||||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
|
||||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
|
||||||
},
|
},
|
||||||
"exclude": ["node_modules", "**/*.test.ts"]
|
"exclude": ["__fixtures__", "__tests__", "coverage", "dist", "node_modules"],
|
||||||
|
"include": ["src"]
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user