diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2642a1f..901be4d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,408 +12,434 @@ permissions: contents: read jobs: - build: # make sure build/ci work properly - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: | - npm install - - run: | - npm run all - test: - name: GraalVM - runs-on: ${{ matrix.os }} - strategy: - matrix: - java-version: ['23', '21', '17', '20', 'dev'] - distribution: ['graalvm', 'graalvm-community'] - os: [ - ubuntu-latest, - macos-latest, # macOS on Apple silicon - macos-13, # macOS on Intel - windows-latest - ] - set-gds-token: [false] - components: [''] - include: - - java-version: 'latest-ea' - distribution: 'graalvm' - os: ubuntu-latest - - java-version: '24-ea' - distribution: 'graalvm' - os: ubuntu-latest - - java-version: '21' - distribution: '' - os: ubuntu-latest - - java-version: 'dev' - distribution: '' - os: windows-latest - - java-version: '21' - distribution: 'graalvm-community' - os: ubuntu-latest - components: 'native-image' # should print a warning but not fail - - java-version: '21.0.0' # test for GA version (see #63) - distribution: 'graalvm' - os: ubuntu-latest - - java-version: '17' - distribution: 'graalvm' - os: ubuntu-latest - set-gds-token: true - - java-version: '17.0.13' - distribution: 'graalvm' - os: ubuntu-latest - set-gds-token: true - steps: - - 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 }} - gds-token: ${{ matrix.set-gds-token && secrets.GDS_TOKEN || '' }} - - name: Check environment - run: | - echo "GRAALVM_HOME: $GRAALVM_HOME" - if [[ "${{ matrix.java-version }}" == "dev" ]]; then - [[ "$GRAALVM_HOME" == *"$RUNNER_TEMP"* ]] || exit 12 - else - [[ "$GRAALVM_HOME" == *"$RUNNER_TOOL_CACHE"* ]] || exit 23 - fi - echo "JAVA_HOME: $JAVA_HOME" - java --version - java --version | grep "GraalVM" || exit 34 - native-image --version - if: runner.os != 'Windows' - - name: Check Windows environment - run: | - echo "GRAALVM_HOME: $env:GRAALVM_HOME" - echo "JAVA_HOME: $env:JAVA_HOME" - java --version - native-image --version - test-ce: # make sure the action works on a clean machine without building - needs: test - name: CE ${{ matrix.version }} + JDK${{ matrix.java-version }} on ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - matrix: - version: ['latest', 'dev'] - java-version: ['17', '20'] - components: ['native-image'] - os: [macos-latest, windows-latest, ubuntu-latest] - exclude: - - version: 'latest' - java-version: '20' - - version: 'dev' - java-version: '19' - include: - - version: '22.2.0' # for update notifications - java-version: '17' - components: 'native-image' - os: ubuntu-20.04 - - version: '21.2.0' - java-version: '8' # for JDK 8 notification - components: 'native-image' - os: ubuntu-latest - - version: '22.3.1' - java-version: '11' # for JDK 11 notification - components: 'native-image' - os: macos-13 - - version: '22.3.1' - java-version: '17' - components: 'native-image' - os: windows-2022 - - version: 'dev' - java-version: 'dev' - components: 'native-image' - os: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Run setup-graalvm action - uses: ./ - with: - version: ${{ matrix.version }} - java-version: ${{ matrix.java-version }} - components: ${{ matrix.components }} - github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Check environment - run: | - echo "GRAALVM_HOME: $GRAALVM_HOME" - if [[ "${{ matrix.version }}" == "dev" ]] && [[ "${{ matrix.java-version }}" == "dev" ]]; then - [[ "$GRAALVM_HOME" == *"$RUNNER_TEMP"* ]] || exit 12 - else - [[ "$GRAALVM_HOME" == *"$RUNNER_TOOL_CACHE"* ]] || exit 23 - fi - echo "JAVA_HOME: $JAVA_HOME" - java -version - java -version 2>&1 | grep "GraalVM" || exit 34 - native-image --version - if [[ "${{ matrix.java-version }}" != "dev" ]]; then - gu list - fi - if: runner.os != 'Windows' - - name: Check Windows environment - run: | - echo "GRAALVM_HOME: $env:GRAALVM_HOME" - echo "JAVA_HOME: $env:JAVA_HOME" - java -version - native-image --version - gu.cmd remove native-image - if: runner.os == 'Windows' - test-ee: - needs: test - name: EE ${{ matrix.version }} + JDK${{ matrix.java-version }} on ${{ matrix.os }} - if: github.event_name != 'pull_request' - runs-on: ${{ matrix.os }} - strategy: - matrix: - version: ['latest'] - java-version: ['17'] - components: ['native-image'] - os: [macos-latest, windows-latest, ubuntu-latest] - include: - - version: '22.3.3' - java-version: '11' - components: 'native-image' - os: ubuntu-latest - - version: '22.3.3' - java-version: '17' - components: 'native-image' - os: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Run setup-graalvm action - uses: ./ - with: - version: ${{ matrix.version }} - gds-token: ${{ secrets.GDS_TOKEN }} - java-version: ${{ matrix.java-version }} - components: ${{ matrix.components }} - github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Check environment - run: | - echo "GRAALVM_HOME: $GRAALVM_HOME" - [[ "$GRAALVM_HOME" == *"$RUNNER_TOOL_CACHE"* ]] || exit 12 - echo "JAVA_HOME: $JAVA_HOME" - java --version - java --version | grep -e "GraalVM EE" -e "Oracle GraalVM" || exit 23 - native-image --version - gu list - if: runner.os != 'Windows' - - name: Check Windows environment - run: | - echo "GRAALVM_HOME: $env:GRAALVM_HOME" - echo "JAVA_HOME: $env:JAVA_HOME" - java --version - native-image --version - gu.cmd remove native-image - if: runner.os == 'Windows' - test-mandrel: - needs: test - name: ${{ matrix.version }} + JDK${{ matrix.java-version }} on ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - matrix: - version: ['mandrel-22.2.0.0-Final', '23.0.1.2-Final', 'mandrel-latest'] - java-version: ['17'] - distribution: ['mandrel'] - os: [windows-latest, ubuntu-latest] - include: - - version: 'mandrel-latest' - java-version: '17' - distribution: '' # test empty distribution for backward compatibility - os: ubuntu-latest - - version: '' # test with no version - java-version: '21' - distribution: 'mandrel' - os: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Run setup-graalvm action - uses: ./ - with: - version: ${{ matrix.version }} - distribution: ${{ matrix.distribution }} - java-version: ${{ matrix.java-version }} - github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Check environment - run: | - echo "GRAALVM_HOME: $GRAALVM_HOME" - [[ "$GRAALVM_HOME" == *"$RUNNER_TOOL_CACHE"* ]] || exit 12 - echo "JAVA_HOME: $JAVA_HOME" - java --version - java --version | grep "Temurin" || exit 23 - native-image --version - if: runner.os != 'Windows' - - name: Check Windows environment - run: | - echo "GRAALVM_HOME: $env:GRAALVM_HOME" - echo "JAVA_HOME: $env:JAVA_HOME" - java --version - native-image --version - if: runner.os == 'Windows' - test-liberica: - needs: test - name: Liberica (${{ matrix.java-version }}, '${{ matrix.java-package }}', ${{ matrix.os }}) - runs-on: ${{ matrix.os }} - strategy: - matrix: - java-version: ['17', '21.0.2'] - java-package: ['', 'jdk', 'jdk+fx'] - os: [ubuntu-latest, macos-latest, windows-latest] - steps: - - uses: actions/checkout@v4 - - name: Run setup-graalvm action - uses: ./ - with: - distribution: liberica - java-version: ${{ matrix.java-version }} - java-package: ${{ matrix.java-package }} - github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Check environment - run: | - echo "GRAALVM_HOME: $GRAALVM_HOME" - [[ "$GRAALVM_HOME" == *"$RUNNER_TOOL_CACHE"* ]] || exit 12 - echo "JAVA_HOME: $JAVA_HOME" - java --version - java --version | fgrep -qw ${{ matrix.java-version }} || exit 23 - native-image --version - native-image --version | fgrep -qw ${{ matrix.java-version }} || exit 24 - if: runner.os != 'Windows' - - name: Check Windows environment - shell: pwsh - run: | - echo "GRAALVM_HOME: $env:GRAALVM_HOME" - echo "JAVA_HOME: $env:JAVA_HOME" - java --version - if (!(java --version | findstr \<${{ matrix.java-version }}\>)) { - exit 23 - } - native-image --version - if (!(native-image --version | findstr \<${{ matrix.java-version }}\>)) { - exit 24 - } - if: runner.os == 'Windows' - test-native-image-windows: - name: native-image on windows-latest - runs-on: windows-latest - permissions: - contents: read - pull-requests: write # for `native-image-pr-reports` option - steps: - - uses: actions/checkout@v4 - - name: Run setup-graalvm action - uses: ./ - with: - java-version: 'dev' - distribution: 'graalvm-community' - native-image-job-reports: 'true' - native-image-pr-reports: 'true' - github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Build HelloWorld executable with GraalVM Native Image on Windows - run: | - echo 'public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }' > HelloWorld.java - javac HelloWorld.java - native-image HelloWorld - ./helloworld - test-native-image-windows-msvc: - name: native-image on windows-2022 - runs-on: windows-2022 - permissions: - contents: read - pull-requests: write # for `native-image-pr-reports` option - steps: - - uses: actions/checkout@v4 - - name: Run setup-graalvm action - uses: ./ - with: - java-version: '17' - distribution: 'graalvm' - native-image-job-reports: 'true' - native-image-pr-reports: 'true' - github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Build HelloWorld executable with GraalVM Native Image on Windows - run: | - echo 'public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }' > HelloWorld.java - javac HelloWorld.java - native-image HelloWorld - ./helloworld - test-native-image-musl: - name: native-image-musl on ubuntu-latest - runs-on: ubuntu-latest + # build: # make sure build/ci work properly + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # - run: | + # npm install + # - run: | + # npm run build && npm run package && npm run test + # test: + # name: GraalVM + # runs-on: ${{ matrix.os }} + # strategy: + # matrix: + # java-version: ['23', '21', '17', '20', 'dev'] + # distribution: ['graalvm', 'graalvm-community'] + # os: [ + # ubuntu-latest, + # macos-latest, # macOS on Apple silicon + # macos-13, # macOS on Intel + # windows-latest + # ] + # set-gds-token: [false] + # components: [''] + # include: + # - java-version: 'latest-ea' + # distribution: 'graalvm' + # os: ubuntu-latest + # - java-version: '24-ea' + # distribution: 'graalvm' + # os: ubuntu-latest + # - java-version: '21' + # distribution: '' + # os: ubuntu-latest + # - java-version: 'dev' + # distribution: '' + # os: windows-latest + # - java-version: '21' + # distribution: 'graalvm-community' + # os: ubuntu-latest + # components: 'native-image' # should print a warning but not fail + # - java-version: '21.0.0' # test for GA version (see #63) + # distribution: 'graalvm' + # os: ubuntu-latest + # - java-version: '17' + # distribution: 'graalvm' + # os: ubuntu-latest + # set-gds-token: true + # - java-version: '17.0.13' + # distribution: 'graalvm' + # os: ubuntu-latest + # set-gds-token: true + # steps: + # - 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 }} + # gds-token: ${{ matrix.set-gds-token && secrets.GDS_TOKEN || '' }} + # - name: Check environment + # run: | + # echo "GRAALVM_HOME: $GRAALVM_HOME" + # if [[ "${{ matrix.java-version }}" == "dev" ]]; then + # [[ "$GRAALVM_HOME" == *"$RUNNER_TEMP"* ]] || exit 12 + # else + # [[ "$GRAALVM_HOME" == *"$RUNNER_TOOL_CACHE"* ]] || exit 23 + # fi + # echo "JAVA_HOME: $JAVA_HOME" + # java --version + # java --version | grep "GraalVM" || exit 34 + # native-image --version + # if: runner.os != 'Windows' + # - name: Check Windows environment + # run: | + # echo "GRAALVM_HOME: $env:GRAALVM_HOME" + # echo "JAVA_HOME: $env:JAVA_HOME" + # java --version + # native-image --version + # test-ce: # make sure the action works on a clean machine without building + # needs: test + # name: CE ${{ matrix.version }} + JDK${{ matrix.java-version }} on ${{ matrix.os }} + # runs-on: ${{ matrix.os }} + # strategy: + # matrix: + # version: ['latest', 'dev'] + # java-version: ['17', '20'] + # components: ['native-image'] + # os: [macos-latest, windows-latest, ubuntu-latest] + # exclude: + # - version: 'latest' + # java-version: '20' + # - version: 'dev' + # java-version: '19' + # include: + # - version: '22.2.0' # for update notifications + # java-version: '17' + # components: 'native-image' + # os: ubuntu-20.04 + # - version: '21.2.0' + # java-version: '8' # for JDK 8 notification + # components: 'native-image' + # os: ubuntu-latest + # - version: '22.3.1' + # java-version: '11' # for JDK 11 notification + # components: 'native-image' + # os: macos-13 + # - version: '22.3.1' + # java-version: '17' + # components: 'native-image' + # os: windows-2022 + # - version: 'dev' + # java-version: 'dev' + # components: 'native-image' + # os: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # - name: Run setup-graalvm action + # uses: ./ + # with: + # version: ${{ matrix.version }} + # java-version: ${{ matrix.java-version }} + # components: ${{ matrix.components }} + # github-token: ${{ secrets.GITHUB_TOKEN }} + # - name: Check environment + # run: | + # echo "GRAALVM_HOME: $GRAALVM_HOME" + # if [[ "${{ matrix.version }}" == "dev" ]] && [[ "${{ matrix.java-version }}" == "dev" ]]; then + # [[ "$GRAALVM_HOME" == *"$RUNNER_TEMP"* ]] || exit 12 + # else + # [[ "$GRAALVM_HOME" == *"$RUNNER_TOOL_CACHE"* ]] || exit 23 + # fi + # echo "JAVA_HOME: $JAVA_HOME" + # java -version + # java -version 2>&1 | grep "GraalVM" || exit 34 + # native-image --version + # if [[ "${{ matrix.java-version }}" != "dev" ]]; then + # gu list + # fi + # if: runner.os != 'Windows' + # - name: Check Windows environment + # run: | + # echo "GRAALVM_HOME: $env:GRAALVM_HOME" + # echo "JAVA_HOME: $env:JAVA_HOME" + # java -version + # native-image --version + # gu.cmd remove native-image + # if: runner.os == 'Windows' + # test-ee: + # needs: test + # name: EE ${{ matrix.version }} + JDK${{ matrix.java-version }} on ${{ matrix.os }} + # runs-on: ${{ matrix.os }} + # strategy: + # matrix: + # version: ['latest'] + # java-version: ['17'] + # components: ['native-image'] + # os: [macos-latest, windows-latest, ubuntu-latest] + # include: + # - version: '22.3.3' + # java-version: '11' + # components: 'native-image' + # os: ubuntu-latest + # - version: '22.3.3' + # java-version: '17' + # components: 'native-image' + # os: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # - name: Run setup-graalvm action + # uses: ./ + # with: + # version: ${{ matrix.version }} + # gds-token: ${{ secrets.GDS_TOKEN }} + # java-version: ${{ matrix.java-version }} + # components: ${{ matrix.components }} + # github-token: ${{ secrets.GITHUB_TOKEN }} + # - name: Check environment + # run: | + # echo "GRAALVM_HOME: $GRAALVM_HOME" + # [[ "$GRAALVM_HOME" == *"$RUNNER_TOOL_CACHE"* ]] || exit 12 + # echo "JAVA_HOME: $JAVA_HOME" + # java --version + # java --version | grep -e "GraalVM EE" -e "Oracle GraalVM" || exit 23 + # native-image --version + # gu list + # if: runner.os != 'Windows' + # - name: Check Windows environment + # run: | + # echo "GRAALVM_HOME: $env:GRAALVM_HOME" + # echo "JAVA_HOME: $env:JAVA_HOME" + # java --version + # native-image --version + # gu.cmd remove native-image + # if: runner.os == 'Windows' + # test-mandrel: + # needs: test + # name: ${{ matrix.version }} + JDK${{ matrix.java-version }} on ${{ matrix.os }} + # runs-on: ${{ matrix.os }} + # strategy: + # matrix: + # version: ['mandrel-22.2.0.0-Final', '23.0.1.2-Final', 'mandrel-latest'] + # java-version: ['17'] + # distribution: ['mandrel'] + # os: [windows-latest, ubuntu-latest] + # include: + # - version: 'mandrel-latest' + # java-version: '17' + # distribution: '' # test empty distribution for backward compatibility + # os: ubuntu-latest + # - version: '' # test with no version + # java-version: '21' + # distribution: 'mandrel' + # os: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # - name: Run setup-graalvm action + # uses: ./ + # with: + # version: ${{ matrix.version }} + # distribution: ${{ matrix.distribution }} + # java-version: ${{ matrix.java-version }} + # github-token: ${{ secrets.GITHUB_TOKEN }} + # - name: Check environment + # run: | + # echo "GRAALVM_HOME: $GRAALVM_HOME" + # [[ "$GRAALVM_HOME" == *"$RUNNER_TOOL_CACHE"* ]] || exit 12 + # echo "JAVA_HOME: $JAVA_HOME" + # java --version + # java --version | grep "Temurin" || exit 23 + # native-image --version + # if: runner.os != 'Windows' + # - name: Check Windows environment + # run: | + # echo "GRAALVM_HOME: $env:GRAALVM_HOME" + # echo "JAVA_HOME: $env:JAVA_HOME" + # java --version + # native-image --version + # if: runner.os == 'Windows' + # test-liberica: + # needs: test + # name: Liberica (${{ matrix.java-version }}, '${{ matrix.java-package }}', ${{ matrix.os }}) + # runs-on: ${{ matrix.os }} + # strategy: + # matrix: + # java-version: ['17', '21.0.2'] + # java-package: ['', 'jdk', 'jdk+fx'] + # os: [ubuntu-latest, macos-latest, windows-latest] + # steps: + # - uses: actions/checkout@v4 + # - name: Run setup-graalvm action + # uses: ./ + # with: + # distribution: liberica + # java-version: ${{ matrix.java-version }} + # java-package: ${{ matrix.java-package }} + # github-token: ${{ secrets.GITHUB_TOKEN }} + # - name: Check environment + # run: | + # echo "GRAALVM_HOME: $GRAALVM_HOME" + # [[ "$GRAALVM_HOME" == *"$RUNNER_TOOL_CACHE"* ]] || exit 12 + # echo "JAVA_HOME: $JAVA_HOME" + # java --version + # java --version | fgrep -qw ${{ matrix.java-version }} || exit 23 + # native-image --version + # native-image --version | fgrep -qw ${{ matrix.java-version }} || exit 24 + # if: runner.os != 'Windows' + # - name: Check Windows environment + # shell: pwsh + # run: | + # echo "GRAALVM_HOME: $env:GRAALVM_HOME" + # echo "JAVA_HOME: $env:JAVA_HOME" + # java --version + # if (!(java --version | findstr \<${{ matrix.java-version }}\>)) { + # exit 23 + # } + # native-image --version + # if (!(native-image --version | findstr \<${{ matrix.java-version }}\>)) { + # exit 24 + # } + # if: runner.os == 'Windows' + # test-native-image-windows: + # name: native-image on windows-latest + # runs-on: windows-latest + # permissions: + # contents: read + # pull-requests: write # for `native-image-pr-reports` option + # steps: + # - uses: actions/checkout@v4 + # - name: Run setup-graalvm action + # uses: ./ + # with: + # java-version: 'dev' + # distribution: 'graalvm-community' + # native-image-job-reports: 'true' + # native-image-pr-reports: 'true' + # github-token: ${{ secrets.GITHUB_TOKEN }} + # - name: Build HelloWorld executable with GraalVM Native Image on Windows + # run: | + # echo 'public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }' > HelloWorld.java + # javac HelloWorld.java + # native-image HelloWorld + # ./helloworld + # test-native-image-windows-msvc: + # name: native-image on windows-2022 + # runs-on: windows-2022 + # permissions: + # contents: read + # pull-requests: write # for `native-image-pr-reports` option + # steps: + # - uses: actions/checkout@v4 + # - name: Run setup-graalvm action + # uses: ./ + # with: + # java-version: '17' + # distribution: 'graalvm' + # native-image-job-reports: 'true' + # native-image-pr-reports: 'true' + # github-token: ${{ secrets.GITHUB_TOKEN }} + # - name: Build HelloWorld executable with GraalVM Native Image on Windows + # run: | + # echo 'public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }' > HelloWorld.java + # javac HelloWorld.java + # native-image HelloWorld + # ./helloworld + # test-native-image-musl: + # name: native-image-musl on ubuntu-latest + # runs-on: ubuntu-latest + # permissions: + # contents: read + # pull-requests: write # for `native-image-pr-reports` option + # steps: + # - uses: actions/checkout@v4 + # - name: Run setup-graalvm action + # uses: ./ + # with: + # java-version: 'dev' + # distribution: 'graalvm-community' + # native-image-musl: 'true' + # native-image-job-reports: 'true' + # native-image-pr-reports: 'true' + # github-token: ${{ secrets.GITHUB_TOKEN }} + # - name: Build static HelloWorld executable with GraalVM Native Image and musl + # run: | + # echo 'public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }' > HelloWorld.java + # javac HelloWorld.java + # native-image --static --libc=musl HelloWorld + # ./helloworld + # test-extensive: + # name: extensive tests on ubuntu-latest + # runs-on: ubuntu-latest + # permissions: + # contents: read + # pull-requests: write # for `native-image-pr-reports` option + # steps: + # - uses: actions/checkout@v4 + # - name: Run setup-graalvm action + # uses: ./ + # with: + # java-version: '17.0.8' + # distribution: 'graalvm' + # components: 'espresso,llvm-toolchain,native-image,nodejs,python,ruby,wasm' + # set-java-home: 'false' + # native-image-job-reports: 'true' + # native-image-pr-reports: 'true' + # github-token: ${{ secrets.GITHUB_TOKEN }} + # - name: Check environment + # run: | + # echo "GRAALVM_HOME: $GRAALVM_HOME" + # echo "JAVA_HOME: $JAVA_HOME" + # [[ "$GRAALVM_HOME" != "$JAVA_HOME" ]] || exit 12 + # [[ $(which java) == *"graalvm"* ]] || exit 23 + # java --version + # java -truffle --version + # gu --version + # gu list + # [[ $(which lli) == *"graalvm"* ]] || exit 34 + # lli --version + # native-image --version + # [[ $(which node) == *"graalvm"* ]] || exit 45 + # node --version + # graalpy --version + # truffleruby --version + # wasm --version + # - name: Build HelloWorld.java with GraalVM Native Image + # run: | + # echo 'public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }' > HelloWorld.java + # javac HelloWorld.java + # native-image -g HelloWorld + # ./helloworld + # # - name: Build Ruby-FFI with TruffleRuby + # # run: | + # # [[ $(which bundle) == *"graalvm"* ]] || exit 57 + # # git clone --depth 1 https://github.com/ffi/ffi.git + # # pushd ffi > /dev/null + # # # https://github.com/ffi/ffi/blob/447845cb3030194c79700c86fb388a12e6f81386/.github/workflows/ci.yml#L58-L62 + # # bundle install + # # bundle exec rake libffi + # # bundle exec rake compile + # # bundle exec rake test + # # popd > /dev/null + # - name: Remove components + # run: gu remove espresso llvm-toolchain nodejs python ruby wasm + test-sbom: + name: test 'native-image-enable-sbom' option + runs-on: macos-latest # TODO: use matrix vlaue permissions: contents: read - pull-requests: write # for `native-image-pr-reports` option + pull-requests: write + # TODO: use appropriate matrix steps: - uses: actions/checkout@v4 - - name: Run setup-graalvm action - uses: ./ - with: - java-version: 'dev' - distribution: 'graalvm-community' - native-image-musl: 'true' - native-image-job-reports: 'true' - native-image-pr-reports: 'true' - github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Build static HelloWorld executable with GraalVM Native Image and musl + - name: Build action run: | - echo 'public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }' > HelloWorld.java - javac HelloWorld.java - native-image --static --libc=musl HelloWorld - ./helloworld - test-extensive: - name: extensive tests on ubuntu-latest - runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: write # for `native-image-pr-reports` option - steps: - - uses: actions/checkout@v4 - - name: Run setup-graalvm action - uses: ./ + npm install + npm run build + npm run package + - uses: ./ with: - java-version: '17.0.8' + java-version: '23' distribution: 'graalvm' - components: 'espresso,llvm-toolchain,native-image,nodejs,python,ruby,wasm' - set-java-home: 'false' - native-image-job-reports: 'true' - native-image-pr-reports: 'true' - github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Check environment - run: | - echo "GRAALVM_HOME: $GRAALVM_HOME" - echo "JAVA_HOME: $JAVA_HOME" - [[ "$GRAALVM_HOME" != "$JAVA_HOME" ]] || exit 12 - [[ $(which java) == *"graalvm"* ]] || exit 23 - java --version - java -truffle --version - gu --version - gu list - [[ $(which lli) == *"graalvm"* ]] || exit 34 - lli --version - native-image --version - [[ $(which node) == *"graalvm"* ]] || exit 45 - node --version - graalpy --version - truffleruby --version - wasm --version - - name: Build HelloWorld.java with GraalVM Native Image + native-image-enable-sbom: 'true' + # set-java-home: 'false' + components: 'native-image' + - name: Verify SBOM was generated run: | - echo 'public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }' > HelloWorld.java - javac HelloWorld.java - native-image -g HelloWorld - ./helloworld - # - name: Build Ruby-FFI with TruffleRuby - # run: | - # [[ $(which bundle) == *"graalvm"* ]] || exit 57 - # git clone --depth 1 https://github.com/ffi/ffi.git - # pushd ffi > /dev/null - # # https://github.com/ffi/ffi/blob/447845cb3030194c79700c86fb388a12e6f81386/.github/workflows/ci.yml#L58-L62 - # bundle install - # bundle exec rake libffi - # bundle exec rake compile - # bundle exec rake test - # popd > /dev/null - - name: Remove components - run: gu remove espresso llvm-toolchain nodejs python ruby wasm + echo 'public class Hello { public static void main(String[] args) { System.out.println("Hello"); } }' > Hello.java + javac Hello.java + native-image Hello + find . -name "*.sbom.json" | grep . || exit 1 diff --git a/__tests__/sbom.test.ts b/__tests__/sbom.test.ts new file mode 100644 index 0000000..bb1cdaf --- /dev/null +++ b/__tests__/sbom.test.ts @@ -0,0 +1,136 @@ +import {setUpSBOMSupport, processSBOM, INPUT_NI_SBOM, NATIVE_IMAGE_OPTIONS_ENV} from '../src/features/sbom' +import * as core from '@actions/core' +import * as glob from '@actions/glob' +import {join} from 'path' +import {tmpdir} from 'os' +import {mkdtempSync, writeFileSync, rmSync} from 'fs' + +jest.mock('@actions/glob') + +// sbom.ts uses glob to find the SBOM file +// This helper function mocks the glob module to return 'files' +function mockGlobResult(files: string[]) { + const mockCreate = jest.fn().mockResolvedValue({ + glob: jest.fn().mockResolvedValue(files) + }) + ;(glob.create as jest.Mock).mockImplementation(mockCreate) +} + +describe('sbom feature', () => { + let spyInfo: jest.SpyInstance> + let spyWarning: jest.SpyInstance> + let spyExportVariable: jest.SpyInstance> + let workspace: string + + beforeEach(() => { + workspace = mkdtempSync(join(tmpdir(), 'setup-graalvm-sbom-')) + + 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 === INPUT_NI_SBOM) { + return 'true' + } + return '' + }) + }) + + afterEach(() => { + jest.clearAllMocks() + rmSync(workspace, {recursive: true, force: true}) + }) + + describe('setup', () => { + it('should set the SBOM option flag when activated', () => { + setUpSBOMSupport() + expect(spyExportVariable).toHaveBeenCalledWith( + NATIVE_IMAGE_OPTIONS_ENV, + expect.stringContaining('--enable-sbom=export') + ) + expect(spyInfo).toHaveBeenCalledWith('Enabled SBOM generation for Native Image builds') + }) + + it('should not set the SBOM option flag when not activated', () => { + jest.spyOn(core, 'getInput').mockReturnValue('false') + setUpSBOMSupport() + expect(spyExportVariable).not.toHaveBeenCalled() + expect(spyInfo).not.toHaveBeenCalled() + }) + }) + + describe('process', () => { + 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: "20211205", + purl: "pkg:maven/org.json/json@20211205", + "bom-ref": "pkg:maven/org.json/json@20211205", + properties: [ + { + name: "syft:cpe23", + value: "cpe:2.3:a:json:json:20211205:*:*:*:*:*:*:*" + } + ] + }, + { + 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@20211205"] + }, + { + ref: "pkg:maven/org.json/json@20211205", + dependsOn: [] + } + ] + } + + it('should process SBOM file and display components', async () => { + setUpSBOMSupport() + spyInfo.mockClear() + + // Mock 'native-image' invocation by creating the SBOM file + const sbomPath = join(workspace, 'test.sbom.json') + writeFileSync(sbomPath, JSON.stringify(sampleSBOM, null, 2)) + + mockGlobResult([sbomPath]) + + await processSBOM() + + expect(spyInfo).toHaveBeenCalledWith('Found SBOM file: ' + sbomPath) + expect(spyInfo).toHaveBeenCalledWith('=== SBOM Content ===') + expect(spyInfo).toHaveBeenCalledWith('Found 2 components:') + expect(spyInfo).toHaveBeenCalledWith('- json@20211205') + expect(spyInfo).toHaveBeenCalledWith('- main-test-app@1.0-SNAPSHOT') + expect(spyWarning).not.toHaveBeenCalled() + }) + + it('should handle missing SBOM file', async () => { + setUpSBOMSupport() + spyInfo.mockClear() + + mockGlobResult([]) + + await processSBOM() + expect(spyWarning).toHaveBeenCalledWith( + 'No SBOM file found. Make sure native-image build completed successfully.' + ) + }) + }) +}) \ No newline at end of file diff --git a/action.yml b/action.yml index ea52128..52dc54e 100644 --- a/action.yml +++ b/action.yml @@ -51,6 +51,10 @@ inputs: required: false 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: 'Enable SBOM generation for Native Image builds. The SBOM dependencies are shown in the dependency view in Github.' + default: 'false' version: required: false description: 'GraalVM version (release, latest, dev).' diff --git a/package-lock.json b/package-lock.json index 985ed71..c94a1bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,7 +40,7 @@ "prettier": "^3.2.5", "prettier-eslint": "^16.3.0", "ts-jest": "^29.1.2", - "typescript": "^5.3.3" + "typescript": "^5.7.2" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -7644,10 +7644,11 @@ } }, "node_modules/typescript": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", - "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index 72547e0..9961aa6 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,6 @@ "prettier": "^3.2.5", "prettier-eslint": "^16.3.0", "ts-jest": "^29.1.2", - "typescript": "^5.3.3" + "typescript": "^5.7.2" } } diff --git a/src/cleanup.ts b/src/cleanup.ts index 3ed1b0c..cc1e9eb 100644 --- a/src/cleanup.ts +++ b/src/cleanup.ts @@ -28,6 +28,7 @@ import * as core from '@actions/core' import * as constants from './constants' import {save} from './features/cache' import {generateReports} from './features/reports' +import { processSBOM } from './features/sbom' /** * Check given input and run a save process for the specified package manager @@ -58,6 +59,7 @@ async function ignoreErrors(promise: Promise): Promise { export async function run(): Promise { await ignoreErrors(generateReports()) + await ignoreErrors(processSBOM()) await ignoreErrors(saveCache()) } diff --git a/src/features/sbom.ts b/src/features/sbom.ts new file mode 100644 index 0000000..c96b9e5 --- /dev/null +++ b/src/features/sbom.ts @@ -0,0 +1,170 @@ +import * as core from '@actions/core' +import * as fs from 'fs' +import * as github from '@actions/github' +import * as glob from '@actions/glob' + +export const INPUT_NI_SBOM = 'native-image-enable-sbom' +export const NATIVE_IMAGE_OPTIONS_ENV = 'NATIVE_IMAGE_OPTIONS' + +export function setUpSBOMSupport(): void { + const isSbomEnabled = core.getInput(INPUT_NI_SBOM) === 'true' + if (!isSbomEnabled) { + return + } + + let options = process.env[NATIVE_IMAGE_OPTIONS_ENV] || '' + if (options.length > 0) { + options += ' ' + } + options += '--enable-sbom=export' + core.exportVariable(NATIVE_IMAGE_OPTIONS_ENV, options) + core.info('Enabled SBOM generation for Native Image builds') +} + +/** + * Finds a single SBOM file in the build directory + * @returns Path to the SBOM file or null if not found or multiple files exist + */ +async function findSBOMFile(): Promise { + const globber = await glob.create('**/*.sbom.json') + const sbomFiles = await globber.glob() + + if (sbomFiles.length === 0) { + core.warning('No SBOM file found. Make sure native-image build completed successfully.') + return null + } + + if (sbomFiles.length > 1) { + core.warning( + `Found multiple SBOM files: ${sbomFiles.join(', ')}. ` + + 'Expected exactly one SBOM file. Skipping SBOM processing.' + ) + return null + } + + core.info(`Found SBOM file: ${sbomFiles[0]}`) + return sbomFiles[0] +} + +function displaySBOMContent(sbomData: any): void { + core.info('=== SBOM Content ===') + + if (sbomData.components) { + core.info(`Found ${sbomData.components.length} components:`) + for (const component of sbomData.components) { + core.info(`- ${component.name}@${component.version || 'unknown'}`) + if (component.dependencies?.length > 0) { + core.info(` Dependencies: ${component.dependencies.join(', ')}`) + } + } + } else { + core.info('No components found in SBOM') + } + + core.info('==================') +} + +export async function processSBOM(): Promise { + const isSbomEnabled = core.getInput(INPUT_NI_SBOM) === 'true' + if (!isSbomEnabled) { + return + } + + const sbomFile = await findSBOMFile() + if (!sbomFile) { + return + } + + try { + const sbomContent = fs.readFileSync(sbomFile, 'utf8') + const sbomData = JSON.parse(sbomContent) + displaySBOMContent(sbomData) + } catch (error) { + core.warning(`Failed to process SBOM file: ${error instanceof Error ? error.message : String(error)}`) + } +} + +interface DependencySnapshot { + version: number + sha: string + ref: string + job: { + correlator: string + id: string + } + detector: { + name: string + version: string + url: string + } + scanned: string + manifests: Record + }> +} + +async function convertSBOMToSnapshot(sbomData: any): Promise { + const context = github.context + + return { + version: 0, + sha: context.sha, + ref: context.ref, + job: { + correlator: `${context.workflow}_${context.action}`, + id: context.runId.toString() + }, + detector: { + name: 'graalvm-setup-sbom', + version: '1.0.0', + url: 'https://github.com/graalvm/setup-graalvm' + }, + scanned: new Date().toISOString(), + manifests: { + 'native-image-sbom.json': { + name: 'native-image-sbom.json', + file: { + source_location: 'native-image-sbom.json' + }, + resolved: convertSBOMDependencies(sbomData) + } + } + } +} + +function convertSBOMDependencies(sbomData: any): Record { + const resolved: Record = {} + + if (sbomData.components) { + for (const component of sbomData.components) { + if (component.name && component.version) { + resolved[component.name] = { + package_url: `pkg:${component.type || 'maven'}/${component.name}@${component.version}` + } + + if (component.dependencies?.length > 0) { + resolved[component.name].dependencies = component.dependencies + } + } + } + } + + return resolved +} + +async function submitDependencySnapshot(snapshot: DependencySnapshot): Promise { + const token = core.getInput('github-token') + const octokit = github.getOctokit(token) +// await octokit.rest.dependencyGraph.createSnapshot({ +// owner: github.context.repo.owner, +// repo: github.context.repo.repo, +// ...snapshot +// }) +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 7f32b82..8fa13f8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -14,6 +14,7 @@ import {setUpNativeImageMusl} from './features/musl' import {setUpWindowsEnvironment} from './msvc' import {setUpNativeImageBuildReports} from './features/reports' import {exec} from '@actions/exec' +import {setUpSBOMSupport} from './features/sbom' async function run(): Promise { try { @@ -166,6 +167,8 @@ async function run(): Promise { graalVMVersion ) + setUpSBOMSupport() + core.startGroup(`Successfully set up '${basename(graalVMHome)}'`) await exec(join(graalVMHome, 'bin', `java${c.EXECUTABLE_SUFFIX}`), [ javaVersion.startsWith('8') ? '-version' : '--version'