Compare commits

...

83 Commits
v1.2.3 ... main

Author SHA1 Message Date
dependabot[bot]
7de2d094ec Bump eslint-plugin-jest from 28.12.0 to 29.0.1
---
updated-dependencies:
- dependency-name: eslint-plugin-jest
  dependency-version: 29.0.1
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-01 23:33:15 +02:00
dependabot[bot]
d7feb9d031 Bump the npm-development group with 10 updates
Bumps the npm-development group with 10 updates:

| Package | From | To |
| --- | --- | --- |
| [@eslint/compat](https://github.com/eslint/rewrite/tree/HEAD/packages/compat) | `1.2.9` | `1.3.1` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.17.57` | `20.19.4` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.33.0` | `8.35.1` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.33.0` | `8.35.1` |
| [eslint](https://github.com/eslint/eslint) | `9.28.0` | `9.30.1` |
| [eslint-import-resolver-typescript](https://github.com/import-js/eslint-import-resolver-typescript) | `4.4.2` | `4.4.4` |
| [eslint-plugin-import](https://github.com/import-js/eslint-plugin-import) | `2.31.0` | `2.32.0` |
| [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) | `5.4.1` | `5.5.1` |
| [prettier](https://github.com/prettier/prettier) | `3.5.3` | `3.6.2` |
| [ts-jest](https://github.com/kulshekhar/ts-jest) | `29.3.4` | `29.4.0` |


Updates `@eslint/compat` from 1.2.9 to 1.3.1
- [Release notes](https://github.com/eslint/rewrite/releases)
- [Changelog](https://github.com/eslint/rewrite/blob/main/packages/compat/CHANGELOG.md)
- [Commits](https://github.com/eslint/rewrite/commits/compat-v1.3.1/packages/compat)

Updates `@types/node` from 20.17.57 to 20.19.4
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@typescript-eslint/eslint-plugin` from 8.33.0 to 8.35.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.35.1/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.33.0 to 8.35.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.35.1/packages/parser)

Updates `eslint` from 9.28.0 to 9.30.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.28.0...v9.30.1)

Updates `eslint-import-resolver-typescript` from 4.4.2 to 4.4.4
- [Release notes](https://github.com/import-js/eslint-import-resolver-typescript/releases)
- [Changelog](https://github.com/import-js/eslint-import-resolver-typescript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-import-resolver-typescript/compare/v4.4.2...v4.4.4)

Updates `eslint-plugin-import` from 2.31.0 to 2.32.0
- [Release notes](https://github.com/import-js/eslint-plugin-import/releases)
- [Changelog](https://github.com/import-js/eslint-plugin-import/blob/main/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-plugin-import/compare/v2.31.0...v2.32.0)

Updates `eslint-plugin-prettier` from 5.4.1 to 5.5.1
- [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.4.1...v5.5.1)

Updates `prettier` from 3.5.3 to 3.6.2
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.5.3...3.6.2)

Updates `ts-jest` from 29.3.4 to 29.4.0
- [Release notes](https://github.com/kulshekhar/ts-jest/releases)
- [Changelog](https://github.com/kulshekhar/ts-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/kulshekhar/ts-jest/compare/v29.3.4...v29.4.0)

---
updated-dependencies:
- dependency-name: "@eslint/compat"
  dependency-version: 1.3.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: "@types/node"
  dependency-version: 20.19.4
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.35.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.35.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint
  dependency-version: 9.30.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint-import-resolver-typescript
  dependency-version: 4.4.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: eslint-plugin-import
  dependency-version: 2.32.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint-plugin-prettier
  dependency-version: 5.5.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: prettier
  dependency-version: 3.6.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: ts-jest
  dependency-version: 29.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-01 23:22:15 +02:00
Fabio Niephaus
63e0340562
Revise README.md. (#169)
Co-authored-by: Olga Gupalo <olga.gupalo@oracle.com>
2025-06-26 08:46:11 +02:00
Fabio Niephaus
8ea6c1f538 Update dependencies 2025-06-24 17:44:38 +02:00
Fabio Niephaus
01ed3ea8d4 Update dist files. 2025-06-24 16:58:58 +02:00
dependabot[bot]
e46a5025da Bump the npm-production group with 2 updates
Bumps the npm-production group with 2 updates: [@actions/github](https://github.com/actions/toolkit/tree/HEAD/packages/github) and [semver](https://github.com/npm/node-semver).


Updates `@actions/github` from 6.0.0 to 6.0.1
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/github/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/github)

Updates `semver` from 7.7.1 to 7.7.2
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v7.7.1...v7.7.2)

---
updated-dependencies:
- dependency-name: "@actions/github"
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-production
- dependency-name: semver
  dependency-version: 7.7.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-24 16:58:58 +02:00
dependabot[bot]
4daf9d25d0 Bump undici from 5.28.5 to 5.29.0
Bumps [undici](https://github.com/nodejs/undici) from 5.28.5 to 5.29.0.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v5.28.5...v5.29.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-24 16:58:58 +02:00
Fabio Niephaus
6249097607 Update java-version in README.md.
Fixes #166
2025-06-24 16:45:27 +02:00
Fabio Niephaus
99513f43da Update dist files. 2025-06-24 16:45:27 +02:00
dependabot[bot]
70cc29044a Bump the npm-development group with 11 updates
Bumps the npm-development group with 11 updates:

| Package | From | To |
| --- | --- | --- |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.17.32` | `20.17.57` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.31.1` | `8.33.0` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.31.1` | `8.33.0` |
| [eslint](https://github.com/eslint/eslint) | `9.25.1` | `9.28.0` |
| [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) | `10.1.2` | `10.1.5` |
| [eslint-import-resolver-typescript](https://github.com/import-js/eslint-import-resolver-typescript) | `4.3.4` | `4.4.2` |
| [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) | `28.11.0` | `28.12.0` |
| [eslint-plugin-jsonc](https://github.com/ota-meshi/eslint-plugin-jsonc) | `2.20.0` | `2.20.1` |
| [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) | `5.2.6` | `5.4.1` |
| [prettier-eslint](https://github.com/prettier/prettier-eslint) | `16.4.1` | `16.4.2` |
| [ts-jest](https://github.com/kulshekhar/ts-jest) | `29.3.2` | `29.3.4` |


Updates `@types/node` from 20.17.32 to 20.17.57
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@typescript-eslint/eslint-plugin` from 8.31.1 to 8.33.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.33.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.31.1 to 8.33.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.33.0/packages/parser)

Updates `eslint` from 9.25.1 to 9.28.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.25.1...v9.28.0)

Updates `eslint-config-prettier` from 10.1.2 to 10.1.5
- [Release notes](https://github.com/prettier/eslint-config-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v10.1.2...v10.1.5)

Updates `eslint-import-resolver-typescript` from 4.3.4 to 4.4.2
- [Release notes](https://github.com/import-js/eslint-import-resolver-typescript/releases)
- [Changelog](https://github.com/import-js/eslint-import-resolver-typescript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-import-resolver-typescript/compare/v4.3.4...v4.4.2)

Updates `eslint-plugin-jest` from 28.11.0 to 28.12.0
- [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases)
- [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v28.11.0...v28.12.0)

Updates `eslint-plugin-jsonc` from 2.20.0 to 2.20.1
- [Release notes](https://github.com/ota-meshi/eslint-plugin-jsonc/releases)
- [Changelog](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ota-meshi/eslint-plugin-jsonc/compare/v2.20.0...v2.20.1)

Updates `eslint-plugin-prettier` from 5.2.6 to 5.4.1
- [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.2.6...v5.4.1)

Updates `prettier-eslint` from 16.4.1 to 16.4.2
- [Release notes](https://github.com/prettier/prettier-eslint/releases)
- [Changelog](https://github.com/prettier/prettier-eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier-eslint/compare/v16.4.1...v16.4.2)

Updates `ts-jest` from 29.3.2 to 29.3.4
- [Release notes](https://github.com/kulshekhar/ts-jest/releases)
- [Changelog](https://github.com/kulshekhar/ts-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/kulshekhar/ts-jest/compare/v29.3.2...v29.3.4)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 20.17.57
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.33.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.33.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint
  dependency-version: 9.28.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint-config-prettier
  dependency-version: 10.1.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: eslint-import-resolver-typescript
  dependency-version: 4.4.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint-plugin-jest
  dependency-version: 28.12.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint-plugin-jsonc
  dependency-version: 2.20.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: eslint-plugin-prettier
  dependency-version: 5.4.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: prettier-eslint
  dependency-version: 16.4.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: ts-jest
  dependency-version: 29.3.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-24 16:45:27 +02:00
dependabot[bot]
547a84f872 Bump @octokit/types from 14.0.0 to 14.1.0
Bumps [@octokit/types](https://github.com/octokit/types.ts) from 14.0.0 to 14.1.0.
- [Release notes](https://github.com/octokit/types.ts/releases)
- [Commits](https://github.com/octokit/types.ts/compare/v14.0.0...v14.1.0)

---
updated-dependencies:
- dependency-name: "@octokit/types"
  dependency-version: 14.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-02 10:17:37 +02:00
dependabot[bot]
21af6a0ef7 Bump @octokit/types from 13.10.0 to 14.0.0
Bumps [@octokit/types](https://github.com/octokit/types.ts) from 13.10.0 to 14.0.0.
- [Release notes](https://github.com/octokit/types.ts/releases)
- [Commits](https://github.com/octokit/types.ts/compare/v13.10.0...v14.0.0)

---
updated-dependencies:
- dependency-name: "@octokit/types"
  dependency-version: 14.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-12 11:25:31 +02:00
dependabot[bot]
1086d2a1b4 Bump the npm-development group with 11 updates
Bumps the npm-development group with 11 updates:

| Package | From | To |
| --- | --- | --- |
| [@eslint/compat](https://github.com/eslint/rewrite) | `1.2.8` | `1.2.9` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.17.30` | `20.17.32` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.29.0` | `8.31.1` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.29.0` | `8.31.1` |
| [eslint](https://github.com/eslint/eslint) | `9.23.0` | `9.25.1` |
| [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) | `10.1.1` | `10.1.2` |
| [eslint-import-resolver-typescript](https://github.com/import-js/eslint-import-resolver-typescript) | `4.3.1` | `4.3.4` |
| [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) | `5.2.5` | `5.2.6` |
| [prettier-eslint](https://github.com/prettier/prettier-eslint) | `16.3.0` | `16.4.1` |
| [ts-jest](https://github.com/kulshekhar/ts-jest) | `29.3.1` | `29.3.2` |
| [typescript](https://github.com/microsoft/TypeScript) | `5.8.2` | `5.8.3` |


Updates `@eslint/compat` from 1.2.8 to 1.2.9
- [Release notes](https://github.com/eslint/rewrite/releases)
- [Changelog](https://github.com/eslint/rewrite/blob/main/release-please-config.json)
- [Commits](https://github.com/eslint/rewrite/compare/compat-v1.2.8...compat-v1.2.9)

Updates `@types/node` from 20.17.30 to 20.17.32
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@typescript-eslint/eslint-plugin` from 8.29.0 to 8.31.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.31.1/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.29.0 to 8.31.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.31.1/packages/parser)

Updates `eslint` from 9.23.0 to 9.25.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.23.0...v9.25.1)

Updates `eslint-config-prettier` from 10.1.1 to 10.1.2
- [Release notes](https://github.com/prettier/eslint-config-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v10.1.1...v10.1.2)

Updates `eslint-import-resolver-typescript` from 4.3.1 to 4.3.4
- [Release notes](https://github.com/import-js/eslint-import-resolver-typescript/releases)
- [Changelog](https://github.com/import-js/eslint-import-resolver-typescript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-import-resolver-typescript/compare/v4.3.1...v4.3.4)

Updates `eslint-plugin-prettier` from 5.2.5 to 5.2.6
- [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.2.5...v5.2.6)

Updates `prettier-eslint` from 16.3.0 to 16.4.1
- [Release notes](https://github.com/prettier/prettier-eslint/releases)
- [Changelog](https://github.com/prettier/prettier-eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier-eslint/compare/v16.3.0...v16.4.1)

Updates `ts-jest` from 29.3.1 to 29.3.2
- [Release notes](https://github.com/kulshekhar/ts-jest/releases)
- [Changelog](https://github.com/kulshekhar/ts-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/kulshekhar/ts-jest/compare/v29.3.1...v29.3.2)

Updates `typescript` from 5.8.2 to 5.8.3
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.8.2...v5.8.3)

---
updated-dependencies:
- dependency-name: "@eslint/compat"
  dependency-version: 1.2.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: "@types/node"
  dependency-version: 20.17.32
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.31.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.31.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint
  dependency-version: 9.25.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint-config-prettier
  dependency-version: 10.1.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: eslint-import-resolver-typescript
  dependency-version: 4.3.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: eslint-plugin-prettier
  dependency-version: 5.2.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: prettier-eslint
  dependency-version: 16.4.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: ts-jest
  dependency-version: 29.3.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: typescript
  dependency-version: 5.8.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-12 11:24:18 +02:00
dependabot[bot]
7f61f4917e Bump eslint-import-resolver-typescript from 3.8.3 to 4.3.1
Bumps [eslint-import-resolver-typescript](https://github.com/import-js/eslint-import-resolver-typescript) from 3.8.3 to 4.3.1.
- [Release notes](https://github.com/import-js/eslint-import-resolver-typescript/releases)
- [Changelog](https://github.com/import-js/eslint-import-resolver-typescript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-import-resolver-typescript/compare/v3.8.3...v4.3.1)

---
updated-dependencies:
- dependency-name: eslint-import-resolver-typescript
  dependency-version: 4.3.1
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-02 08:57:39 +02:00
dependabot[bot]
f3662e4b72 Bump @octokit/types from 13.8.0 to 13.10.0
Bumps [@octokit/types](https://github.com/octokit/types.ts) from 13.8.0 to 13.10.0.
- [Release notes](https://github.com/octokit/types.ts/releases)
- [Commits](https://github.com/octokit/types.ts/compare/v13.8.0...v13.10.0)

---
updated-dependencies:
- dependency-name: "@octokit/types"
  dependency-version: 13.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-02 08:57:39 +02:00
Fabio Niephaus
b19c2851fd Update dist files. 2025-04-02 08:57:39 +02:00
dependabot[bot]
0027121302 Bump the npm-production group with 2 updates
Bumps the npm-production group with 2 updates: [@actions/cache](https://github.com/actions/toolkit/tree/HEAD/packages/cache) and [@github/dependency-submission-toolkit](https://github.com/github/dependency-submission-toolkit).


Updates `@actions/cache` from 4.0.2 to 4.0.3
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/cache/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/cache)

Updates `@github/dependency-submission-toolkit` from 2.0.4 to 2.0.5
- [Release notes](https://github.com/github/dependency-submission-toolkit/releases)
- [Commits](https://github.com/github/dependency-submission-toolkit/compare/v2.0.4...v2.0.5)

---
updated-dependencies:
- dependency-name: "@actions/cache"
  dependency-version: 4.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-production
- dependency-name: "@github/dependency-submission-toolkit"
  dependency-version: 2.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-02 08:57:39 +02:00
Fabio Niephaus
0568ccefb6 Upgrade from ubuntu-20.04 to ubuntu-22.04.
Context: https://github.com/actions/runner-images/issues/11101
2025-04-02 08:50:21 +02:00
dependabot[bot]
a4c8415508 Bump the npm-development group with 11 updates
Bumps the npm-development group with 11 updates:

| Package | From | To |
| --- | --- | --- |
| [@eslint/compat](https://github.com/eslint/rewrite) | `1.2.7` | `1.2.8` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.17.22` | `20.17.30` |
| [@types/semver](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/semver) | `7.5.8` | `7.7.0` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.25.0` | `8.29.0` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.25.0` | `8.29.0` |
| [eslint](https://github.com/eslint/eslint) | `9.21.0` | `9.23.0` |
| [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) | `10.0.2` | `10.1.1` |
| [eslint-plugin-jsonc](https://github.com/ota-meshi/eslint-plugin-jsonc) | `2.19.1` | `2.20.0` |
| [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) | `5.2.3` | `5.2.5` |
| [ts-jest](https://github.com/kulshekhar/ts-jest) | `29.2.6` | `29.3.1` |
| [typescript](https://github.com/microsoft/TypeScript) | `5.7.3` | `5.8.2` |


Updates `@eslint/compat` from 1.2.7 to 1.2.8
- [Release notes](https://github.com/eslint/rewrite/releases)
- [Changelog](https://github.com/eslint/rewrite/blob/main/release-please-config.json)
- [Commits](https://github.com/eslint/rewrite/compare/compat-v1.2.7...compat-v1.2.8)

Updates `@types/node` from 20.17.22 to 20.17.30
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@types/semver` from 7.5.8 to 7.7.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/semver)

Updates `@typescript-eslint/eslint-plugin` from 8.25.0 to 8.29.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.29.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.25.0 to 8.29.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.29.0/packages/parser)

Updates `eslint` from 9.21.0 to 9.23.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.21.0...v9.23.0)

Updates `eslint-config-prettier` from 10.0.2 to 10.1.1
- [Release notes](https://github.com/prettier/eslint-config-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v10.0.2...v10.1.1)

Updates `eslint-plugin-jsonc` from 2.19.1 to 2.20.0
- [Release notes](https://github.com/ota-meshi/eslint-plugin-jsonc/releases)
- [Changelog](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ota-meshi/eslint-plugin-jsonc/compare/v2.19.1...v2.20.0)

Updates `eslint-plugin-prettier` from 5.2.3 to 5.2.5
- [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.2.3...v5.2.5)

Updates `ts-jest` from 29.2.6 to 29.3.1
- [Release notes](https://github.com/kulshekhar/ts-jest/releases)
- [Changelog](https://github.com/kulshekhar/ts-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/kulshekhar/ts-jest/compare/v29.2.6...v29.3.1)

Updates `typescript` from 5.7.3 to 5.8.2
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.7.3...v5.8.2)

---
updated-dependencies:
- dependency-name: "@eslint/compat"
  dependency-version: 1.2.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: "@types/node"
  dependency-version: 20.17.30
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: "@types/semver"
  dependency-version: 7.7.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.29.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.29.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint
  dependency-version: 9.23.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint-config-prettier
  dependency-version: 10.1.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint-plugin-jsonc
  dependency-version: 2.20.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint-plugin-prettier
  dependency-version: 5.2.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: ts-jest
  dependency-version: 29.3.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: typescript
  dependency-version: 5.8.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-02 08:50:21 +02:00
Fabio Niephaus
aef1f09405 Test against GraalVM for JDK 24 and 25 EA builds. 2025-03-18 17:03:35 +01:00
Alina Yurenko
26a86e7135 add about arm runners 2025-03-04 14:57:10 +01:00
Fabio Niephaus
01ed653ac8
Bump version to 1.3.3. 2025-03-03 14:23:11 +01:00
Joel Rudsberg
3ca6fc3a8a SBOM: Ensure 'java-version' is persisted to post-run phase 2025-03-03 12:56:54 +01:00
Fabio Niephaus
271a696e78 Bump version to 1.3.2. 2025-03-03 10:22:04 +01:00
Fabio Niephaus
2063b36b79 Update dist files. 2025-03-03 09:12:04 +01:00
Fabio Niephaus
44d0c2f19b Downgrade typescript back to 5.7.3.
eslint-plugin is not yet compatible with version `5.8.2` of typescript.
2025-03-03 09:12:04 +01:00
dependabot[bot]
26e3dc36fc Bump the npm-development group across 1 directory with 10 updates
Bumps the npm-development group with 10 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@eslint/compat](https://github.com/eslint/rewrite) | `1.2.6` | `1.2.7` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.17.17` | `20.17.22` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.24.0` | `8.25.0` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.24.0` | `8.25.0` |
| [eslint](https://github.com/eslint/eslint) | `9.20.1` | `9.21.0` |
| [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) | `10.0.1` | `10.0.2` |
| [eslint-import-resolver-typescript](https://github.com/import-js/eslint-import-resolver-typescript) | `3.7.0` | `3.8.3` |
| [prettier](https://github.com/prettier/prettier) | `3.5.0` | `3.5.3` |
| [ts-jest](https://github.com/kulshekhar/ts-jest) | `29.2.5` | `29.2.6` |
| [typescript](https://github.com/microsoft/TypeScript) | `5.7.3` | `5.8.2` |



Updates `@eslint/compat` from 1.2.6 to 1.2.7
- [Release notes](https://github.com/eslint/rewrite/releases)
- [Changelog](https://github.com/eslint/rewrite/blob/main/release-please-config.json)
- [Commits](https://github.com/eslint/rewrite/compare/compat-v1.2.6...compat-v1.2.7)

Updates `@types/node` from 20.17.17 to 20.17.22
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@typescript-eslint/eslint-plugin` from 8.24.0 to 8.25.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.25.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.24.0 to 8.25.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.25.0/packages/parser)

Updates `eslint` from 9.20.1 to 9.21.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.20.1...v9.21.0)

Updates `eslint-config-prettier` from 10.0.1 to 10.0.2
- [Release notes](https://github.com/prettier/eslint-config-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v10.0.1...v10.0.2)

Updates `eslint-import-resolver-typescript` from 3.7.0 to 3.8.3
- [Release notes](https://github.com/import-js/eslint-import-resolver-typescript/releases)
- [Changelog](https://github.com/import-js/eslint-import-resolver-typescript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-import-resolver-typescript/compare/v3.7.0...v3.8.3)

Updates `prettier` from 3.5.0 to 3.5.3
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.5.0...3.5.3)

Updates `ts-jest` from 29.2.5 to 29.2.6
- [Release notes](https://github.com/kulshekhar/ts-jest/releases)
- [Changelog](https://github.com/kulshekhar/ts-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/kulshekhar/ts-jest/compare/v29.2.5...v29.2.6)

Updates `typescript` from 5.7.3 to 5.8.2
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.7.3...v5.8.2)

---
updated-dependencies:
- dependency-name: "@eslint/compat"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint-config-prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: eslint-import-resolver-typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: ts-jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 09:12:04 +01:00
Fabio Niephaus
e6854f2a7c Update dist files. 2025-03-03 09:06:06 +01:00
dependabot[bot]
a1c06b5535 Bump @octokit/plugin-paginate-rest from 9.2.1 to 9.2.2
Bumps [@octokit/plugin-paginate-rest](https://github.com/octokit/plugin-paginate-rest.js) from 9.2.1 to 9.2.2.
- [Release notes](https://github.com/octokit/plugin-paginate-rest.js/releases)
- [Commits](https://github.com/octokit/plugin-paginate-rest.js/compare/v9.2.1...v9.2.2)

---
updated-dependencies:
- dependency-name: "@octokit/plugin-paginate-rest"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 09:06:06 +01:00
Fabio Niephaus
e4bdac3847 Update dist files. 2025-03-03 08:52:38 +01:00
dependabot[bot]
00f0f13934 Bump uuid from 11.0.5 to 11.1.0
Bumps [uuid](https://github.com/uuidjs/uuid) from 11.0.5 to 11.1.0.
- [Release notes](https://github.com/uuidjs/uuid/releases)
- [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v11.0.5...v11.1.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 08:52:38 +01:00
dependabot[bot]
63ca6fe724 Bump @actions/cache from 4.0.0 to 4.0.2 in the npm-production group
Bumps the npm-production group with 1 update: [@actions/cache](https://github.com/actions/toolkit/tree/HEAD/packages/cache).


Updates `@actions/cache` from 4.0.0 to 4.0.2
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/cache/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/cache)

---
updated-dependencies:
- dependency-name: "@actions/cache"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 08:52:38 +01:00
dependabot[bot]
5b85983c0a Bump @octokit/request from 8.4.0 to 8.4.1
Bumps [@octokit/request](https://github.com/octokit/request.js) from 8.4.0 to 8.4.1.
- [Release notes](https://github.com/octokit/request.js/releases)
- [Commits](https://github.com/octokit/request.js/compare/v8.4.0...v8.4.1)

---
updated-dependencies:
- dependency-name: "@octokit/request"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 08:52:38 +01:00
Fabio Niephaus
f4c22e2c3f Update dist files. 2025-02-17 10:50:53 +01:00
dependabot[bot]
2ea5788b37 Bump @octokit/endpoint from 9.0.5 to 9.0.6
Bumps [@octokit/endpoint](https://github.com/octokit/endpoint.js) from 9.0.5 to 9.0.6.
- [Release notes](https://github.com/octokit/endpoint.js/releases)
- [Commits](https://github.com/octokit/endpoint.js/compare/v9.0.5...v9.0.6)

---
updated-dependencies:
- dependency-name: "@octokit/endpoint"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 10:50:53 +01:00
Fabio Niephaus
b5709ab80d Run SBOM test on ubuntu-22.04-arm. 2025-02-17 10:43:44 +01:00
Fabio Niephaus
6e1c9cebb5 Update dist files. 2025-02-17 10:43:44 +01:00
dependabot[bot]
601e3a4caa Bump @octokit/request-error from 5.1.0 to 5.1.1
Bumps [@octokit/request-error](https://github.com/octokit/request-error.js) from 5.1.0 to 5.1.1.
- [Release notes](https://github.com/octokit/request-error.js/releases)
- [Commits](https://github.com/octokit/request-error.js/compare/v5.1.0...v5.1.1)

---
updated-dependencies:
- dependency-name: "@octokit/request-error"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 10:43:44 +01:00
Fabio Niephaus
b0cb26a8da Bump version to 1.3.1. 2025-02-12 21:31:35 +01:00
Fabio Niephaus
30b157ff45 Ensure cache: 'maven' is tested. 2025-02-12 21:31:35 +01:00
Fabio Niephaus
0f761465f7 Convert back to CJS and use ncc. 2025-02-12 21:31:35 +01:00
Fabio Niephaus
f07b5bfaef Update dist files. 2025-02-12 14:38:09 +01:00
dependabot[bot]
fcc01ed19b Bump semver from 7.6.3 to 7.7.1
Dependabot couldn't find the original pull request head commit, d99c250780f60ae25820f76a799d34572762727f.
2025-02-12 14:38:09 +01:00
dependabot[bot]
c65e623881 Bump @octokit/types from 12.6.0 to 13.8.0
Bumps [@octokit/types](https://github.com/octokit/types.ts) from 12.6.0 to 13.8.0.
- [Release notes](https://github.com/octokit/types.ts/releases)
- [Commits](https://github.com/octokit/types.ts/compare/v12.6.0...v13.8.0)

---
updated-dependencies:
- dependency-name: "@octokit/types"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-12 14:23:45 +01:00
dependabot[bot]
3040d71541 Bump eslint-config-prettier from 9.1.0 to 10.0.1
Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 9.1.0 to 10.0.1.
- [Release notes](https://github.com/prettier/eslint-config-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v9.1.0...v10.0.1)

---
updated-dependencies:
- dependency-name: eslint-config-prettier
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-12 14:19:07 +01:00
Fabio Niephaus
70a5974953 Fix PASSES_GDS_TOKEN_CHECK. 2025-02-12 12:55:33 +01:00
dependabot[bot]
aa331906a0 Bump the npm-development group with 5 updates
Bumps the npm-development group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.17.14` | `20.17.17` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.22.0` | `8.24.0` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.22.0` | `8.24.0` |
| [eslint](https://github.com/eslint/eslint) | `9.19.0` | `9.20.1` |
| [prettier](https://github.com/prettier/prettier) | `3.4.2` | `3.5.0` |


Updates `@types/node` from 20.17.14 to 20.17.17
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@typescript-eslint/eslint-plugin` from 8.22.0 to 8.24.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.24.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.22.0 to 8.24.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.24.0/packages/parser)

Updates `eslint` from 9.19.0 to 9.20.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.19.0...v9.20.1)

Updates `prettier` from 3.4.2 to 3.5.0
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.4.2...3.5.0)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-12 12:55:33 +01:00
Fabio Niephaus
dea0e3da95 Bump version to 1.3.0. 2025-02-12 10:54:00 +01:00
Fabio Niephaus
300d65ee39 Fix cleanup invocation. 2025-02-12 10:54:00 +01:00
Fabio Niephaus
9d4a7232c4 Add ignore rule for @types/node. 2025-02-12 10:54:00 +01:00
Fabio Niephaus
9b77b7e1c6 Adjust printWidth to 120. 2025-02-12 10:54:00 +01:00
Fabio Niephaus
93a3b57d30 Convert to ESM and use rollup. 2025-02-12 10:54:00 +01:00
Fabio Niephaus
ebd520e252 Update imports. 2025-02-12 10:54:00 +01:00
Fabio Niephaus
02f9160735 Fix GDS_TOKEN check. 2025-02-10 08:11:51 +01:00
dependabot[bot]
ef3ebf8051 Bump the npm-development group with 5 updates
Bumps the npm-development group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@eslint/compat](https://github.com/eslint/rewrite) | `1.2.5` | `1.2.6` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.21.0` | `8.22.0` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.21.0` | `8.22.0` |
| [eslint](https://github.com/eslint/eslint) | `9.18.0` | `9.19.0` |
| [eslint-plugin-jsonc](https://github.com/ota-meshi/eslint-plugin-jsonc) | `2.18.2` | `2.19.1` |


Updates `@eslint/compat` from 1.2.5 to 1.2.6
- [Release notes](https://github.com/eslint/rewrite/releases)
- [Changelog](https://github.com/eslint/rewrite/blob/main/release-please-config.json)
- [Commits](https://github.com/eslint/rewrite/compare/compat-v1.2.5...compat-v1.2.6)

Updates `@typescript-eslint/eslint-plugin` from 8.21.0 to 8.22.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.22.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.21.0 to 8.22.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.22.0/packages/parser)

Updates `eslint` from 9.18.0 to 9.19.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.18.0...v9.19.0)

Updates `eslint-plugin-jsonc` from 2.18.2 to 2.19.1
- [Release notes](https://github.com/ota-meshi/eslint-plugin-jsonc/releases)
- [Changelog](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ota-meshi/eslint-plugin-jsonc/compare/v2.18.2...v2.19.1)

---
updated-dependencies:
- dependency-name: "@eslint/compat"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint-plugin-jsonc
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 08:11:51 +01:00
Fabio Niephaus
ae07e6cc51 Start testing on ubuntu-22.04-arm. 2025-01-22 16:22:52 +01:00
Fabio Niephaus
49622345c8 Fix badge. 2025-01-21 13:35:31 +01:00
Fabio Niephaus
a0ea0f7a0a Bump version to 1.2.8. 2025-01-21 13:25:39 +01:00
Fabio Niephaus
d0b11c9136 Update ci.yml workflow with template. 2025-01-21 13:25:39 +01:00
Fabio Niephaus
eb58450822 Update check-dist.yml workflow with template. 2025-01-21 13:25:39 +01:00
Fabio Niephaus
af56e29ad9 Address eslint errors and warnings. 2025-01-21 13:25:39 +01:00
Fabio Niephaus
bc541ab008 Upgrade to eslint 9. 2025-01-21 13:25:39 +01:00
dependabot[bot]
d028da6ae3 Bump the npm-development group with 5 updates
Bumps the npm-development group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@vercel/ncc](https://github.com/vercel/ncc) | `0.38.1` | `0.38.3` |
| [eslint-plugin-jsonc](https://github.com/ota-meshi/eslint-plugin-jsonc) | `2.14.0` | `2.18.2` |
| [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) | `5.1.3` | `5.2.3` |
| [prettier](https://github.com/prettier/prettier) | `3.2.5` | `3.4.2` |
| [typescript](https://github.com/microsoft/TypeScript) | `5.7.2` | `5.7.3` |


Updates `@vercel/ncc` from 0.38.1 to 0.38.3
- [Release notes](https://github.com/vercel/ncc/releases)
- [Commits](https://github.com/vercel/ncc/compare/0.38.1...0.38.3)

Updates `eslint-plugin-jsonc` from 2.14.0 to 2.18.2
- [Release notes](https://github.com/ota-meshi/eslint-plugin-jsonc/releases)
- [Changelog](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ota-meshi/eslint-plugin-jsonc/compare/v2.14.0...v2.18.2)

Updates `eslint-plugin-prettier` from 5.1.3 to 5.2.3
- [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.1.3...v5.2.3)

Updates `prettier` from 3.2.5 to 3.4.2
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.2.5...3.4.2)

Updates `typescript` from 5.7.2 to 5.7.3
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.7.2...v5.7.3)

---
updated-dependencies:
- dependency-name: "@vercel/ncc"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
- dependency-name: eslint-plugin-jsonc
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: eslint-plugin-prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-development
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-21 10:12:36 +01:00
dependabot[bot]
613c01f0e8 Bump actions/upload-artifact from 3 to 4
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-21 10:11:47 +01:00
Fabio Niephaus
71b1e905e2 Add dependabot.yml.
Inspired by template at 2e5a157793/.github/dependabot.yml
2025-01-21 10:08:05 +01:00
Joel Rudsberg
7b74bd8bd8
Integrate Native Image SBOM with GitHub's Dependency Submission API (#119)
Co-authored-by: Fabio Niephaus <fabio.niephaus@oracle.com>
2025-01-21 09:00:42 +01:00
Fabio Niephaus
c09e29bb11 Bump version to 1.2.7. 2025-01-16 15:54:52 +01:00
Fabio Niephaus
04d7e4f4bb Skip steps that require a GDS token in PR builds. 2025-01-16 15:54:52 +01:00
Fabio Niephaus
64b43dc209 Update @actions/cache and other dependencies.
Context: https://github.com/actions/toolkit/discussions/1890
2025-01-16 15:54:52 +01:00
Fabio Niephaus
4a200f28cd Bump version to 1.2.6. 2024-11-13 21:01:33 +01:00
Fabio Niephaus
a8c0509ec2 Revert "Upgrade musl and follow recommendation."
This reverts commit 9dd2b41757680f1bd6a44bcd6ad9f68574bc4f0c.
2024-11-13 21:01:33 +01:00
Fabio Niephaus
557ffcf459 Bump version to 1.2.5. 2024-10-29 15:50:32 +01:00
Fabio Niephaus
f7c3ab9a9a Upgrade to macos-13.
Context: https://github.com/actions/runner-images/issues/10721
2024-10-29 15:50:32 +01:00
Fabio Niephaus
dee12811d5 Update tests to use GraalVM for JDK 22 and 23-ea. 2024-10-29 15:50:32 +01:00
Fabio Niephaus
9dd2b41757 Upgrade musl and follow recommendation.
Closes #113
2024-10-29 15:50:32 +01:00
Fabio Niephaus
3aaf71e276 Fix and improve README.md.
Thanks to @Marcono1234 for the suggestions.
2024-10-17 22:19:35 +02:00
Fabio Niephaus
17d757cc41 Add 'Supported distributions' section.
Related to #107.
2024-10-17 22:19:35 +02:00
Fabio Niephaus
24013ae277 Upgrade job to 17.0.13. 2024-10-17 22:19:35 +02:00
Fabio Niephaus
caa712a441 Recommend actions/upload-artifact@v4. [ci skip]
Fixes #111.

https://github.blog/changelog/2024-02-13-deprecation-notice-v1-and-v2-of-the-artifact-actions/
2024-10-17 22:19:35 +02:00
Fabio Niephaus
6f327093bb
Bump version to 1.2.4. 2024-10-15 15:02:57 +02:00
Fabio Niephaus
4873ae0b28 Add support for Oracle GraalVM via GDS. 2024-10-14 17:35:04 +02:00
Fabio Niephaus
c3163945bd Update dependency. 2024-10-14 17:35:04 +02:00
Fabio Niephaus
c60701d448 Upgrade to macos-12.
`macos-11` was removed in June 2024:
https://github.blog/changelog/2024-05-20-actions-upcoming-changes-to-github-hosted-macos-runners/
2024-08-12 11:44:53 +02:00
50 changed files with 77432 additions and 85504 deletions

View File

@ -1,4 +0,0 @@
dist/
lib/
node_modules/
jest.config.js

View File

@ -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
View 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

View File

@ -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/

View File

@ -1,4 +1,4 @@
name: 'build-test' name: Continuous Integration
on: on:
push: push:
@ -8,37 +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-14, # macOS on Apple silicon ubuntu-22.04-arm, # Linux on arm64
macos-12, # macOS on Intel macos-latest, # macOS on Apple silicon
macos-13, # macOS on Intel
windows-latest windows-latest
] ]
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'
@ -54,6 +72,14 @@ jobs:
- java-version: '21.0.0' # test for GA version (see #63) - java-version: '21.0.0' # test for GA version (see #63)
distribution: 'graalvm' distribution: 'graalvm'
os: ubuntu-latest os: ubuntu-latest
- java-version: '17'
distribution: 'graalvm'
os: ubuntu-latest
set-gds-token: true
- java-version: '17.0.13'
distribution: 'graalvm'
os: ubuntu-latest
set-gds-token: true
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Run setup-graalvm action - name: Run setup-graalvm action
@ -63,6 +89,8 @@ jobs:
distribution: ${{ matrix.distribution }} distribution: ${{ matrix.distribution }}
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
components: ${{ matrix.components }} components: ${{ matrix.components }}
gds-token: ${{ matrix.set-gds-token && secrets.GDS_TOKEN || '' }}
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"
@ -75,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:
@ -101,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'
@ -109,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-11 os: macos-13
- version: '22.3.1' - version: '22.3.1'
java-version: '17' java-version: '17'
components: 'native-image' components: 'native-image'
@ -142,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"
@ -150,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']
@ -181,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"
@ -190,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"
@ -198,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:
@ -235,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:
@ -270,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: |
@ -284,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:
@ -307,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:
@ -329,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:
@ -352,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:
@ -407,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' }}

3
.gitignore vendored
View File

@ -97,3 +97,6 @@ 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
View File

@ -0,0 +1 @@
20.9.0

View File

@ -1,3 +1,3 @@
dist/ dist/
lib/
node_modules/ node_modules/
README.md

View File

@ -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
View 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

140
README.md
View File

@ -1,5 +1,7 @@
# GitHub Action for GraalVM [![build-test](https://github.com/graalvm/setup-graalvm/actions/workflows/test.yml/badge.svg)](https://github.com/graalvm/setup-graalvm/actions/workflows/test.yml) # GitHub Action for GraalVM [![CI](https://github.com/graalvm/setup-graalvm/actions/workflows/ci.yml/badge.svg)](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,14 +74,13 @@ jobs:
./helloworld ./helloworld
- name: Upload binary - name: Upload binary
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v4
with: with:
name: helloworld-${{ matrix.os }} name: helloworld-${{ matrix.os }}
path: helloworld* path: helloworld*
``` ```
<details> ### Template for Oracle GraalVM Early Access (EA) builds
<summary><h4>Template for Oracle GraalVM Early Access (EA) builds</h4></summary>
```yml ```yml
name: Oracle GraalVM Early Access build name: Oracle GraalVM Early Access build
@ -93,18 +92,36 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: graalvm/setup-graalvm@v1 - uses: graalvm/setup-graalvm@v1
with: with:
java-version: '23-ea' # or 'latest-ea' for the latest Java version available java-version: '24-ea' # or 'latest-ea' for the latest Java version available
distribution: 'graalvm' distribution: 'graalvm'
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
``` ```
</details>
<details> <details>
<summary><h4>Template for older GraalVM releases</h4></summary> <summary><h4>Template for Oracle GraalVM via GraalVM Download Service</h4></summary>
#### Prerequisites
1. Obtain a token for the GraalVM Download Service. For this, replace `your@email.com` with your email address and run the following `curl` command:
```bash
curl -sS -X POST "https://gds.oracle.com/api/20220101/licenseAcceptance" \
-H "Content-Type: application/json" \
-d "{ \"email\": \"your@email.com\", \"licenseId\": \"D53FA58D12817B3CE0530F15000A74CA\", \"type\": \"GENERATE_TOKEN_AND_ACCEPT_LICENSE\"}"
```
The response should look like this:
```json
{"token":"<your-token>","status":"UNVERIFIED"}
```
2. Store the value of `<your-token>` as a [GitHub Action secret][gha-secrets]. For the following template, we use the name `GDS_TOKEN`.
3. Check your emails and accept the license to activate the token.
4. Use `java-version: '17'` (or a specific version such as `17.0.13`) and provide the `GDS_TOKEN` as shown in the following template:
```yml ```yml
name: GraalVM build name: Build with Oracle GraalVM for JDK 17 via GDS
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
build: build:
@ -113,10 +130,14 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: graalvm/setup-graalvm@v1 - uses: graalvm/setup-graalvm@v1
with: with:
version: '22.3.2' # GraalVM version distribution: 'graalvm'
java-version: '17' java-version: '17'
components: 'native-image' gds-token: ${{ secrets.GDS_TOKEN }}
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Example step
run: |
java --version
native-image --version
``` ```
</details> </details>
@ -129,7 +150,7 @@ jobs:
1. Download the version of [GraalVM Enterprise Edition (EE)][graalvm-ee] you want to run on GitHub Actions. 1. Download the version of [GraalVM Enterprise Edition (EE)][graalvm-ee] you want to run on GitHub Actions.
2. Use the [GraalVM Updater][gu] to install the GraalVM components you need on GitHub Actions and accept the corresponding licenses. 2. Use the [GraalVM Updater][gu] to install the GraalVM components you need on GitHub Actions and accept the corresponding licenses.
3. Run `$GRAALVM_HOME/bin/gu --show-ee-token` to display your token for the GraalVM Download Service. 3. Run `$GRAALVM_HOME/bin/gu --show-ee-token` to display your token for the GraalVM Download Service.
4. Store this token as a [GitHub Action secret][gha-secrets]. For this template, we use the name `GDS_TOKEN`. 4. Store this token as a [GitHub Action secret][gha-secrets]. In the following template, we use the name `GDS_TOKEN`:
```yml ```yml
name: GraalVM Enterprise Edition build name: GraalVM Enterprise Edition build
@ -155,6 +176,55 @@ jobs:
</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
This actions can be configured with the following options:
| Name | Default | Description |
|-----------------|:--------:|-------------|
| `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 (see [supported distributions](#supported-distributions)) |
| `java-package` | `'jdk'` | The package type (`'jdk'` or `'jdk+fx'`). Currently applies to Liberica only. |
| `github-token` | `'${{ github.token }}'` | Token for communication with the GitHub API. Please set this to `${{ secrets.GITHUB_TOKEN }}` (see [templates](#templates)) to allow the action to authenticate with the GitHub API, which helps reduce rate-limiting issues. |
| `set-java-home` | `'true'` | If set to `'true'`, instructs the action to set `$JAVA_HOME` to the path of the GraalVM installation. Overrides any previous action or command that sets `$JAVA_HOME`. |
| `cache` | `''` | Name of the build platform to cache dependencies. Turned off by default (`''`). It can also be `'maven'`, `'gradle'`, or `'sbt'` and works the same way as described in [actions/setup-java][setup-java-caching]. |
| `check-for-updates` | `'true'` | [Annotate jobs][gha-annotations] with update notifications, for example when a new GraalVM release is available. |
| `native-image-musl` | `'false'` | If set to `'true'`, sets up [musl] to build [static binaries][native-image-static] with GraalVM Native Image *(Linux only)*. [Example usage][native-image-musl-build] (be sure to replace `uses: ./` with `uses: graalvm/setup-graalvm@v1`). |
| `native-image-job-reports` *) | `'false'` | If set to `'true'`, post a job summary containing a Native Image build report. |
| `native-image-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-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]. |
| `version` | `''` | `X.Y.Z` (e.g., `22.3.0`) for a specific [GraalVM release][releases] up to `22.3.2`<br>`mandrel-X.Y.Z.W` or `X.Y.Z.W-Final` (e.g., `mandrel-21.3.0.0-Final` or `21.3.0.0-Final`) for a specific [Mandrel release][mandrel-releases],<br>`mandrel-latest` or `latest` for the latest Mandrel stable release. |
| `gds-token` | `''` Download token for the GraalVM Download Service. If a non-empty token is provided, the action will set up 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.*
## Notes on Oracle GraalVM for JDK 17
GraalVM for JDK 17.0.12 is the [last release of Oracle GraalVM for JDK 17 under the GFTC](https://blogs.oracle.com/java/post/jdk-17-approaches-endofpermissive-license).
Updates after September 2024 will be licensed under the [GraalVM OTN License Including License for Early Adopter Versions](https://www.oracle.com/downloads/licenses/graalvm-otn-license.html) (GOTN) and production use beyond the limited free grants of the GraalVM OTN license will require a fee.
As a user of `setup-graalvm`, you have the following options:
- *Recommended*: Upgrade to Oracle GraalVM for JDK 21 or later to receive new updates.
- *Not recommended*: Instead of `java-version: '17'`, use `java-version: '17.0.12'` in your workflow to keep using the last release under GFTC. This will also disable the warning. Note that switching to GraalVM Community Edition or other GraalVM distributions might provide you with even older releases of GraalVM.
- Provide a `gds-token` to access Oracle GraalVM for JDK 17 under GOTN (see [Oracle GraalVM via GDS template](#template-for-oracle-graalvm-via-graalvm-download-service)).
## Migrating from GraalVM 22.3 or Earlier to the New GraalVM for JDK 17 and Later ## Migrating from GraalVM 22.3 or Earlier to the New GraalVM for JDK 17 and Later
The [GraalVM for JDK 17 and JDK 20 release](https://medium.com/graalvm/a-new-graalvm-release-and-new-free-license-4aab483692f5) aligns the GraalVM version scheme with OpenJDK. The [GraalVM for JDK 17 and JDK 20 release](https://medium.com/graalvm/a-new-graalvm-release-and-new-free-license-4aab483692f5) aligns the GraalVM version scheme with OpenJDK.
@ -177,34 +247,12 @@ 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
# ... # ...
``` ```
## Options
| 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> |
| `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> |
| `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. |
| `set-java-home` | `'true'` | If set to `'true'`, instructs the action to set `$JAVA_HOME` to the path of the GraalVM installation. Overrides any previous action or command that sets `$JAVA_HOME`. |
| `cache` | `''` | Name of the build platform to cache dependencies. Turned off by default (`''`). It can also be `'maven'`, `'gradle'`, or `'sbt'` and works the same way as described in [actions/setup-java][setup-java-caching]. |
| `check-for-updates` | `'true'` | [Annotate jobs][gha-annotations] with update notifications, for example when a new GraalVM release is available. |
| `native-image-musl` | `'false'` | If set to `'true'`, sets up [musl] to build [static binaries][native-image-static] with GraalVM Native Image *(Linux only)*. [Example usage][native-image-musl-build] (be sure to replace `uses: ./` with `uses: graalvm/setup-graalvm@v1`). |
| `native-image-job-reports` *) | `'false'` | If set to `'true'`, post a job summary containing a Native Image build report. |
| `native-image-pr-reports` *) | `'false'` | If set to `'true'`, post a comment containing a Native Image build report on pull requests. Requires `write` permissions for the [`pull-requests` scope][gha-permissions]. |
| `native-image-pr-reports-update-existing` *) | `'false'` | Instead of posting another comment, update an existing PR comment with the latest Native Image build report. Requires `native-image-pr-reports` to be `true`. |
| `components` | `''` | Comma-separated list of GraalVM components (e.g., `native-image` or `ruby,nodejs`) that will be installed by the [GraalVM Updater][gu]. |
| `version` | `''` | `X.Y.Z` (e.g., `22.3.0`) for a specific [GraalVM release][releases] up to `22.3.2`<br>`mandrel-X.Y.Z.W` or `X.Y.Z.W-Final` (e.g., `mandrel-21.3.0.0-Final` or `21.3.0.0-Final`) for a specific [Mandrel release][mandrel-releases],<br>`mandrel-latest` or `latest` for the latest Mandrel stable release. |
| `gds-token` | `''` | Download token for the GraalVM Download Service. If a non-empty token is provided, the action will set up GraalVM Enterprise Edition (see [GraalVM EE template](#template-for-graalvm-enterprise-edition)). |
**) Make sure that Native Image is used only once per build job. Otherwise, the report is only generated for the last Native Image build.*
## Contributing ## Contributing
We welcome code contributions. To get started, you will need to sign the [Oracle Contributor Agreement][oca] (OCA). We welcome code contributions. To get started, you will need to sign the [Oracle Contributor Agreement][oca] (OCA).
@ -215,27 +263,23 @@ Only pull requests from committers that can be verified as having signed the OCA
[dev-build]: https://github.com/graalvm/graalvm-ce-dev-builds/releases/latest [dev-build]: https://github.com/graalvm/graalvm-ce-dev-builds/releases/latest
[dev-builds]: https://github.com/graalvm/graalvm-ce-dev-builds [dev-builds]: https://github.com/graalvm/graalvm-ce-dev-builds
[ea-builds]: https://github.com/graalvm/oracle-graalvm-ea-builds [ea-builds]: https://github.com/graalvm/oracle-graalvm-ea-builds
[gftc]: https://www.oracle.com/downloads/licenses/graal-free-license.html
[gha-annotations]: https://github.com/actions/toolkit/tree/main/packages/core#annotations [gha-annotations]: https://github.com/actions/toolkit/tree/main/packages/core#annotations
[gha-permissions]: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions [gha-permissions]: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
[gha-secrets]: https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository [gha-secrets]: https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository
[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

View File

@ -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'

View File

@ -31,11 +31,7 @@ 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'

View File

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

View File

@ -2,18 +2,14 @@ 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,
findHighestJavaVersion,
findLatestEABuildDownloadUrl
} from '../src/graalvm'
import { GRAALVM_GH_USER, GRAALVM_RELEASES_REPO } from '../src/constants' 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)
@ -68,7 +60,7 @@ test('find version/javaVersion', async () => {
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
} }

View File

@ -7,6 +7,8 @@ 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('/')

View File

@ -7,7 +7,7 @@ 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}`)
} }

View File

@ -7,30 +7,19 @@ 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
View 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)
})
})
})

View 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>

View File

@ -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);
}
}

View 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

View 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"

View File

@ -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
} }

View File

@ -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'

74886
dist/cleanup/index.js generated vendored

File diff suppressed because one or more lines are too long

76891
dist/main/index.js generated vendored

File diff suppressed because one or more lines are too long

82
eslint.config.mjs Normal file
View 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'
}
}
]

View File

@ -1,5 +1,10 @@
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: {

5789
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,63 +1,75 @@
{ {
"name": "setup-graalvm", "name": "setup-graalvm",
"version": "1.2.3", "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"
} }
} }

View File

@ -28,6 +28,7 @@ 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')
}

View File

@ -1,5 +1,7 @@
import * as otypes from '@octokit/types' import * as otypes from '@octokit/types'
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'
export const INPUT_JAVA_VERSION = 'java-version' export const INPUT_JAVA_VERSION = 'java-version'
@ -12,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'
@ -44,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

View File

@ -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']])]

View File

@ -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 || ''

View File

@ -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`

View File

@ -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,11 +34,7 @@ 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 })

View File

@ -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
View 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)}`
)
}
}

View File

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

View File

@ -1,4 +1,5 @@
import * as c from './constants' import * as c from './constants'
import * as core from '@actions/core'
import * as semver from 'semver' import * as semver from 'semver'
import { import {
downloadAndExtractJDK, downloadAndExtractJDK,
@ -8,7 +9,7 @@ import {
getMatchingTags, getMatchingTags,
getTaggedRelease getTaggedRelease
} from './utils' } from './utils'
import {downloadGraalVMEELegacy} from './gds' import { downloadGraalVM, downloadGraalVMEELegacy } from './gds'
import { downloadTool } from '@actions/tool-cache' import { downloadTool } from '@actions/tool-cache'
import { basename } from 'path' import { basename } from 'path'
@ -22,14 +23,25 @@ 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
): Promise<string> {
if (javaVersionOrDev === c.VERSION_DEV) { if (javaVersionOrDev === c.VERSION_DEV) {
return setUpGraalVMJDKDevBuild() return setUpGraalVMJDKDevBuild()
} }
const isTokenProvided = gdsToken.length > 0
let javaVersion = javaVersionOrDev let javaVersion = javaVersionOrDev
const toolName = determineToolName(javaVersion, false) const toolName = determineToolName(javaVersion, false)
if (javaVersionOrDev === '17' && !isTokenProvided) {
core.warning(
'This build uses the last update of Oracle GraalVM for JDK 17 under the GFTC. More details: https://github.com/marketplace/actions/github-action-for-graalvm#notes-on-oracle-graalvm-for-jdk-17'
)
return setUpGraalVMJDK('17.0.12', gdsToken)
}
if (isTokenProvided) {
// Download from GDS
const downloader = async () => downloadGraalVM(gdsToken, javaVersion)
return downloadExtractAndCacheJDK(downloader, toolName, javaVersion)
}
// Download from oracle.com
let downloadName = toolName let downloadName = toolName
let downloadUrl: string let downloadUrl: string
if (javaVersion.endsWith('-ea')) { if (javaVersion.endsWith('-ea')) {
@ -37,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('.')) {
@ -65,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()
} }
@ -134,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,
@ -147,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
} }
} }
@ -163,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}).`
)
} }
} }
@ -193,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) {
@ -237,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)
@ -262,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) {
@ -299,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)
@ -337,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}).`
)
} }
} }

View File

@ -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,

View File

@ -1,10 +1,6 @@
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,
getTaggedRelease,
getMatchingTags
} from './utils'
import { downloadTool } from '@actions/tool-cache' import { downloadTool } from '@actions/tool-cache'
import { spawnSync } from 'child_process' import { spawnSync } from 'child_process'
@ -13,23 +9,14 @@ 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
} }
} }

View File

@ -14,6 +14,7 @@ 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 {
@ -23,24 +24,15 @@ async function run(): Promise<void> {
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,14 +44,13 @@ 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)
} }
switch (distribution) { switch (distribution) {
case c.DISTRIBUTION_GRAALVM: case c.DISTRIBUTION_GRAALVM:
graalVMHome = await graalvm.setUpGraalVMJDK(javaVersion) graalVMHome = await graalvm.setUpGraalVMJDK(javaVersion, gdsToken)
break break
case c.DISTRIBUTION_GRAALVM_COMMUNITY: case c.DISTRIBUTION_GRAALVM_COMMUNITY:
graalVMHome = await graalvm.setUpGraalVMJDKCE(javaVersion) graalVMHome = await graalvm.setUpGraalVMJDKCE(javaVersion)
@ -80,7 +71,7 @@ async function run(): Promise<void> {
core.info( core.info(
`This build is using the new Oracle GraalVM. To select a specific distribution, use the 'distribution' option (see https://github.com/graalvm/setup-graalvm/tree/main#options).` `This build is using the new Oracle GraalVM. To select a specific distribution, use the 'distribution' option (see https://github.com/graalvm/setup-graalvm/tree/main#options).`
) )
graalVMHome = await graalvm.setUpGraalVMJDK(javaVersion) graalVMHome = await graalvm.setUpGraalVMJDK(javaVersion, gdsToken)
} }
break break
default: default:
@ -92,34 +83,25 @@ 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) 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}.`
) )
graalVMHome = await graalvm.setUpGraalVMJDK(javaVersion) graalVMHome = await graalvm.setUpGraalVMJDK(javaVersion, gdsToken)
} else { } else {
graalVMHome = await graalvm.setUpGraalVMJDKDevBuild() graalVMHome = await graalvm.setUpGraalVMJDKDevBuild()
} }
@ -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}`), [

View File

@ -1,6 +1,6 @@
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'
@ -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
} }

View File

@ -1,5 +1,4 @@
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'
@ -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)

View File

@ -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 * as fs from 'fs'
import { ExecOptions, exec as e } from '@actions/exec' import { ExecOptions, exec as e } from '@actions/exec'
import { readFileSync, readdirSync } from 'fs' import { readFileSync, readdirSync } from 'fs'
import { Octokit } from '@octokit/core' import { Octokit } from '@octokit/core'
import { createHash } from 'crypto' import { createHash } from 'crypto'
import { join } from 'path' 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,24 +21,14 @@ 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)
@ -48,10 +40,7 @@ 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)
@ -90,23 +79,16 @@ export async function getMatchingTags(
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, owner,
repo, repo,
tagPrefix 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
View 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
View 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"]
}

View File

@ -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"]
} }