mirror of
https://github.com/actions/setup-java.git
synced 2026-07-30 17:19:27 +08:00
Compare commits
70 Commits
support-kona-jdk
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 3cc3643700 | |||
| 6937f5eb31 | |||
| 0b56831a10 | |||
| 9f43141311 | |||
| ec4dbbe20d | |||
| 62f345fa33 | |||
| bcd3ba3d32 | |||
| 27f2c62824 | |||
| 19c23b379e | |||
| 6e26972896 | |||
| 5894ef6b27 | |||
| e1ce3a3428 | |||
| ce75feb3d3 | |||
| 382d4b753d | |||
| 24d1ce4c2b | |||
| 1c3b3d28f0 | |||
| 0b0bd25927 | |||
| 089b010dc8 | |||
| e07d36bbdd | |||
| 69304e5bab | |||
| f75542ba2b | |||
| c59dceb0cd | |||
| 8f48118d89 | |||
| c79143eaae | |||
| 77c695c0d0 | |||
| 7b26641a55 | |||
| e08df439e0 | |||
| cd3b6000e4 | |||
| c3d7ccbf81 | |||
| 46f6294045 | |||
| e40a8e0642 | |||
| 6e2e32e729 | |||
| 38fa86f9e4 | |||
| ecd5f809c2 | |||
| 4a24efdcc9 | |||
| cc8cdedf67 | |||
| 4b0728bd0d | |||
| 7d485884af | |||
| c3568cc9d9 | |||
| 81c13a41f9 | |||
| 3c85b14378 | |||
| 80c368b720 | |||
| cd57b95697 | |||
| 7a475d86d1 | |||
| 92f9362dd0 | |||
| 71cfe8e0ed | |||
| eb6157cd13 | |||
| 2adeb10550 | |||
| 23f8c419c6 | |||
| 6f7d7a6eb1 | |||
| 2301a55b6d | |||
| 2789aa9170 | |||
| 28fb8cb06b | |||
| 174d4b5609 | |||
| 86ce8e6cc8 | |||
| 90be2728bc | |||
| 3157986b3f | |||
| 548a822bee | |||
| f848fd1976 | |||
| fe9b749bcb | |||
| 4db08ef6bf | |||
| 7dbccc66ee | |||
| 8a3e8157a1 | |||
| f7121373a9 | |||
| 2a07c83aea | |||
| d3530c1eb4 | |||
| 0f481fcb61 | |||
| c4922bf809 | |||
| 6657b99340 | |||
| a50fdccef1 |
@@ -1,6 +0,0 @@
|
||||
# Ignore list
|
||||
/*
|
||||
|
||||
# Do not ignore these folders:
|
||||
!__tests__/
|
||||
!src/
|
||||
@@ -1,51 +0,0 @@
|
||||
// This is a reusable configuration file copied from https://github.com/actions/reusable-workflows/tree/main/reusable-configurations. Please don't make changes to this file as it's the subject of an automatic update.
|
||||
module.exports = {
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:eslint-plugin-jest/recommended',
|
||||
'eslint-config-prettier'
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint', 'eslint-plugin-node', 'eslint-plugin-jest'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-require-imports': 'error',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/ban-ts-comment': [
|
||||
'error',
|
||||
{
|
||||
'ts-ignore': 'allow-with-description'
|
||||
}
|
||||
],
|
||||
'no-console': 'error',
|
||||
'yoda': 'error',
|
||||
'prefer-const': [
|
||||
'error',
|
||||
{
|
||||
destructuring: 'all'
|
||||
}
|
||||
],
|
||||
'no-control-regex': 'off',
|
||||
'no-constant-condition': ['error', {checkLoops: false}],
|
||||
'node/no-extraneous-import': 'error'
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['**/*{test,spec}.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'jest/no-standalone-expect': 'off',
|
||||
'jest/no-conditional-expect': 'off',
|
||||
'no-console': 'off',
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
env: {
|
||||
node: true,
|
||||
es6: true,
|
||||
'jest/globals': true
|
||||
}
|
||||
};
|
||||
@@ -21,6 +21,19 @@
|
||||
"message": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "maven-javac",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^\\[(WARNING|ERROR)\\]\\s+(.+?\\.java):\\[(\\d+),(\\d+)\\]\\s+(.+)$",
|
||||
"severity": 1,
|
||||
"file": 2,
|
||||
"line": 3,
|
||||
"column": 4,
|
||||
"message": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
name: Benchmark cache restore
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
baseline-ref:
|
||||
description: Git ref containing the sequential restore implementation
|
||||
required: true
|
||||
default: main
|
||||
type: string
|
||||
candidate-ref:
|
||||
description: Git ref containing the concurrent restore implementation (defaults to the dispatched ref)
|
||||
required: false
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
warm-caches:
|
||||
name: Warm ${{ matrix.tool }} ${{ matrix.profile }} caches (${{ matrix.os }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-15-intel, windows-latest, ubuntu-latest]
|
||||
tool: [maven, gradle]
|
||||
profile: [small, large]
|
||||
steps:
|
||||
- name: Checkout benchmark workflow
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Checkout baseline
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
path: baseline
|
||||
persist-credentials: false
|
||||
ref: ${{ inputs.baseline-ref }}
|
||||
- name: Checkout candidate
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
path: candidate
|
||||
persist-credentials: false
|
||||
ref: ${{ inputs.candidate-ref || github.ref }}
|
||||
- name: Prepare benchmark inputs
|
||||
run: bash __tests__/benchmark-cache-restore.sh prepare "${{ matrix.tool }}" "${{ matrix.profile }}"
|
||||
- name: Prepare cache save
|
||||
uses: ./candidate
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '17'
|
||||
cache: ${{ matrix.tool }}
|
||||
cache-dependency-path: benchmark/${{ matrix.tool == 'maven' && 'pom.xml' || 'build.gradle' }}
|
||||
- name: Populate benchmark caches
|
||||
run: |
|
||||
bash __tests__/benchmark-cache-restore.sh reset "${{ matrix.tool }}"
|
||||
bash __tests__/benchmark-cache-restore.sh populate "${{ matrix.tool }}" "${{ matrix.profile }}"
|
||||
|
||||
benchmark:
|
||||
name: Benchmark ${{ matrix.tool }} ${{ matrix.profile }} (${{ matrix.os }})
|
||||
needs: warm-caches
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-15-intel, windows-latest, ubuntu-latest]
|
||||
tool: [maven, gradle]
|
||||
profile: [small, large]
|
||||
steps:
|
||||
- name: Checkout benchmark workflow
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Checkout baseline
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
path: baseline
|
||||
persist-credentials: false
|
||||
ref: ${{ inputs.baseline-ref }}
|
||||
- name: Checkout candidate
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
path: candidate
|
||||
persist-credentials: false
|
||||
ref: ${{ inputs.candidate-ref || github.ref }}
|
||||
- name: Prepare benchmark inputs
|
||||
run: bash __tests__/benchmark-cache-restore.sh prepare "${{ matrix.tool }}" "${{ matrix.profile }}"
|
||||
|
||||
- name: Reset caches for baseline iteration 1
|
||||
run: bash __tests__/benchmark-cache-restore.sh reset "${{ matrix.tool }}"
|
||||
- name: Start baseline iteration 1 timer
|
||||
run: bash __tests__/benchmark-cache-restore.sh start "${{ matrix.tool }}"
|
||||
- name: Restore with baseline iteration 1
|
||||
id: baseline-1
|
||||
uses: ./baseline
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '17'
|
||||
cache: ${{ matrix.tool }}
|
||||
cache-dependency-path: benchmark/${{ matrix.tool == 'maven' && 'pom.xml' || 'build.gradle' }}
|
||||
cache-read-only: true
|
||||
- name: Record baseline iteration 1
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.baseline-1.outputs.cache-hit }}
|
||||
run: bash __tests__/benchmark-cache-restore.sh record "${{ matrix.tool }}" "${{ matrix.os }}" "${{ matrix.profile }}" baseline 1 "$CACHE_HIT"
|
||||
|
||||
- name: Reset caches for candidate iteration 1
|
||||
run: bash __tests__/benchmark-cache-restore.sh reset "${{ matrix.tool }}"
|
||||
- name: Start candidate iteration 1 timer
|
||||
run: bash __tests__/benchmark-cache-restore.sh start "${{ matrix.tool }}"
|
||||
- name: Restore with candidate iteration 1
|
||||
id: candidate-1
|
||||
uses: ./candidate
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '17'
|
||||
cache: ${{ matrix.tool }}
|
||||
cache-dependency-path: benchmark/${{ matrix.tool == 'maven' && 'pom.xml' || 'build.gradle' }}
|
||||
cache-read-only: true
|
||||
- name: Record candidate iteration 1
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.candidate-1.outputs.cache-hit }}
|
||||
run: bash __tests__/benchmark-cache-restore.sh record "${{ matrix.tool }}" "${{ matrix.os }}" "${{ matrix.profile }}" candidate 1 "$CACHE_HIT"
|
||||
|
||||
- name: Reset caches for candidate iteration 2
|
||||
run: bash __tests__/benchmark-cache-restore.sh reset "${{ matrix.tool }}"
|
||||
- name: Start candidate iteration 2 timer
|
||||
run: bash __tests__/benchmark-cache-restore.sh start "${{ matrix.tool }}"
|
||||
- name: Restore with candidate iteration 2
|
||||
id: candidate-2
|
||||
uses: ./candidate
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '17'
|
||||
cache: ${{ matrix.tool }}
|
||||
cache-dependency-path: benchmark/${{ matrix.tool == 'maven' && 'pom.xml' || 'build.gradle' }}
|
||||
cache-read-only: true
|
||||
- name: Record candidate iteration 2
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.candidate-2.outputs.cache-hit }}
|
||||
run: bash __tests__/benchmark-cache-restore.sh record "${{ matrix.tool }}" "${{ matrix.os }}" "${{ matrix.profile }}" candidate 2 "$CACHE_HIT"
|
||||
|
||||
- name: Reset caches for baseline iteration 2
|
||||
run: bash __tests__/benchmark-cache-restore.sh reset "${{ matrix.tool }}"
|
||||
- name: Start baseline iteration 2 timer
|
||||
run: bash __tests__/benchmark-cache-restore.sh start "${{ matrix.tool }}"
|
||||
- name: Restore with baseline iteration 2
|
||||
id: baseline-2
|
||||
uses: ./baseline
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '17'
|
||||
cache: ${{ matrix.tool }}
|
||||
cache-dependency-path: benchmark/${{ matrix.tool == 'maven' && 'pom.xml' || 'build.gradle' }}
|
||||
cache-read-only: true
|
||||
- name: Record baseline iteration 2
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.baseline-2.outputs.cache-hit }}
|
||||
run: bash __tests__/benchmark-cache-restore.sh record "${{ matrix.tool }}" "${{ matrix.os }}" "${{ matrix.profile }}" baseline 2 "$CACHE_HIT"
|
||||
|
||||
- name: Reset caches for baseline iteration 3
|
||||
run: bash __tests__/benchmark-cache-restore.sh reset "${{ matrix.tool }}"
|
||||
- name: Start baseline iteration 3 timer
|
||||
run: bash __tests__/benchmark-cache-restore.sh start "${{ matrix.tool }}"
|
||||
- name: Restore with baseline iteration 3
|
||||
id: baseline-3
|
||||
uses: ./baseline
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '17'
|
||||
cache: ${{ matrix.tool }}
|
||||
cache-dependency-path: benchmark/${{ matrix.tool == 'maven' && 'pom.xml' || 'build.gradle' }}
|
||||
cache-read-only: true
|
||||
- name: Record baseline iteration 3
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.baseline-3.outputs.cache-hit }}
|
||||
run: bash __tests__/benchmark-cache-restore.sh record "${{ matrix.tool }}" "${{ matrix.os }}" "${{ matrix.profile }}" baseline 3 "$CACHE_HIT"
|
||||
|
||||
- name: Reset caches for candidate iteration 3
|
||||
run: bash __tests__/benchmark-cache-restore.sh reset "${{ matrix.tool }}"
|
||||
- name: Start candidate iteration 3 timer
|
||||
run: bash __tests__/benchmark-cache-restore.sh start "${{ matrix.tool }}"
|
||||
- name: Restore with candidate iteration 3
|
||||
id: candidate-3
|
||||
uses: ./candidate
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '17'
|
||||
cache: ${{ matrix.tool }}
|
||||
cache-dependency-path: benchmark/${{ matrix.tool == 'maven' && 'pom.xml' || 'build.gradle' }}
|
||||
cache-read-only: true
|
||||
- name: Record candidate iteration 3
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.candidate-3.outputs.cache-hit }}
|
||||
run: bash __tests__/benchmark-cache-restore.sh record "${{ matrix.tool }}" "${{ matrix.os }}" "${{ matrix.profile }}" candidate 3 "$CACHE_HIT"
|
||||
|
||||
- name: Summarize benchmark
|
||||
run: bash __tests__/benchmark-cache-restore.sh summarize "${{ matrix.tool }}" "$GITHUB_STEP_SUMMARY"
|
||||
- name: Upload raw timings
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: cache-restore-${{ matrix.os }}-${{ matrix.tool }}-${{ matrix.profile }}
|
||||
path: .benchmark-results/timings.csv
|
||||
if-no-files-found: error
|
||||
@@ -1,102 +0,0 @@
|
||||
name: Validate cache with cache-dependency-path option
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- releases/*
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
gradle1-save:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run setup-java with the cache for gradle
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '17'
|
||||
cache: gradle
|
||||
cache-dependency-path: __tests__/cache/gradle1/*.gradle*
|
||||
- name: Create files to cache
|
||||
# Need to avoid using Gradle daemon to stabilize the save process on Windows
|
||||
# https://github.com/actions/cache/issues/454#issuecomment-840493935
|
||||
run: |
|
||||
gradle downloadDependencies --no-daemon -p __tests__/cache/gradle1
|
||||
if [ ! -d ~/.gradle/caches ]; then
|
||||
echo "::error::The ~/.gradle/caches directory does not exist unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
gradle1-restore:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
needs: gradle1-save
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run setup-java with the cache for gradle
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
cache: gradle
|
||||
cache-dependency-path: __tests__/cache/gradle1/*.gradle*
|
||||
- name: Confirm that ~/.gradle/caches directory has been made
|
||||
run: |
|
||||
if [ ! -d ~/.gradle/caches ]; then
|
||||
echo "::error::The ~/.gradle/caches directory does not exist unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
ls ~/.gradle/caches/
|
||||
gradle2-restore:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
needs: gradle1-save
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run setup-java with the cache for gradle
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
cache: gradle
|
||||
cache-dependency-path: __tests__/cache/gradle2/*.gradle*
|
||||
- name: Confirm that ~/.gradle/caches directory has not been made
|
||||
run: |
|
||||
if [ -d ~/.gradle/caches ]; then
|
||||
echo "::error::The ~/.gradle/caches directory exists unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
+327
-54
@@ -42,10 +42,10 @@ jobs:
|
||||
# https://github.com/actions/cache/issues/454#issuecomment-840493935
|
||||
run: |
|
||||
gradle downloadDependencies --no-daemon -p __tests__/cache/gradle1
|
||||
if [ ! -d ~/.gradle/caches ]; then
|
||||
echo "::error::The ~/.gradle/caches directory does not exist unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
mkdir -p "$HOME/.gradle/wrapper/dists/setup-java-e2e"
|
||||
echo "gradle wrapper cache" > "$HOME/.gradle/wrapper/dists/setup-java-e2e/payload"
|
||||
bash __tests__/check-dir.sh "$HOME/.gradle/caches"
|
||||
bash __tests__/check-dir.sh "$HOME/.gradle/wrapper/dists"
|
||||
gradle-restore:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
@@ -65,13 +65,11 @@ jobs:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
cache: gradle
|
||||
cache-read-only: true
|
||||
- name: Confirm that ~/.gradle/caches directory has been made
|
||||
run: |
|
||||
if [ ! -d ~/.gradle/caches ]; then
|
||||
echo "::error::The ~/.gradle/caches directory does not exist unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
ls ~/.gradle/caches/
|
||||
run: bash __tests__/check-dir.sh "$HOME/.gradle/caches"
|
||||
- name: Confirm that the Gradle Wrapper cache has been restored
|
||||
run: bash __tests__/check-dir.sh "$HOME/.gradle/wrapper/dists"
|
||||
maven-save:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
@@ -93,10 +91,10 @@ jobs:
|
||||
- name: Create files to cache
|
||||
run: |
|
||||
mvn verify -f __tests__/cache/maven/pom.xml
|
||||
if [ ! -d ~/.m2/repository ]; then
|
||||
echo "::error::The ~/.m2/repository directory does not exist unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
mkdir -p "$HOME/.m2/wrapper/dists/setup-java-e2e"
|
||||
echo "maven wrapper cache" > "$HOME/.m2/wrapper/dists/setup-java-e2e/payload"
|
||||
bash __tests__/check-dir.sh "$HOME/.m2/repository"
|
||||
bash __tests__/check-dir.sh "$HOME/.m2/wrapper/dists"
|
||||
maven-restore:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
@@ -116,13 +114,11 @@ jobs:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
cache: maven
|
||||
cache-read-only: true
|
||||
- name: Confirm that ~/.m2/repository directory has been made
|
||||
run: |
|
||||
if [ ! -d ~/.m2/repository ]; then
|
||||
echo "::error::The ~/.m2/repository directory does not exist unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
ls ~/.m2/repository
|
||||
run: bash __tests__/check-dir.sh "$HOME/.m2/repository"
|
||||
- name: Confirm that the Maven Wrapper cache has been restored
|
||||
run: bash __tests__/check-dir.sh "$HOME/.m2/wrapper/dists"
|
||||
sbt-save:
|
||||
runs-on: ${{ matrix.os }}
|
||||
defaults:
|
||||
@@ -155,25 +151,13 @@ jobs:
|
||||
|
||||
- name: Check files to cache on macos-latest
|
||||
if: matrix.os == 'macos-15-intel'
|
||||
run: |
|
||||
if [ ! -d ~/Library/Caches/Coursier ]; then
|
||||
echo "::error::The ~/Library/Caches/Coursier directory does not exist unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
run: bash "$GITHUB_WORKSPACE/__tests__/check-dir.sh" "$HOME/Library/Caches/Coursier"
|
||||
- name: Check files to cache on windows-latest
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: |
|
||||
if [ ! -d ~/AppData/Local/Coursier/Cache ]; then
|
||||
echo "::error::The ~/AppData/Local/Coursier/Cache directory does not exist unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
run: bash "$GITHUB_WORKSPACE/__tests__/check-dir.sh" "$HOME/AppData/Local/Coursier/Cache"
|
||||
- name: Check files to cache on ubuntu-latest
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
if [ ! -d ~/.cache/coursier ]; then
|
||||
echo "::error::The ~/.cache/coursier directory does not exist unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: bash "$GITHUB_WORKSPACE/__tests__/check-dir.sh" "$HOME/.cache/coursier"
|
||||
sbt-restore:
|
||||
runs-on: ${{ matrix.os }}
|
||||
defaults:
|
||||
@@ -197,28 +181,317 @@ jobs:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
cache: sbt
|
||||
cache-read-only: true
|
||||
|
||||
- name: Confirm that ~/Library/Caches/Coursier directory has been made
|
||||
if: matrix.os == 'macos-15-intel'
|
||||
run: |
|
||||
if [ ! -d ~/Library/Caches/Coursier ]; then
|
||||
echo "::error::The ~/Library/Caches/Coursier directory does not exist unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
ls ~/Library/Caches/Coursier
|
||||
run: bash "$GITHUB_WORKSPACE/__tests__/check-dir.sh" "$HOME/Library/Caches/Coursier"
|
||||
- name: Confirm that ~/AppData/Local/Coursier/Cache directory has been made
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: |
|
||||
if [ ! -d ~/AppData/Local/Coursier/Cache ]; then
|
||||
echo "::error::The ~/AppData/Local/Coursier/Cache directory does not exist unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
ls ~/AppData/Local/Coursier/Cache
|
||||
run: bash "$GITHUB_WORKSPACE/__tests__/check-dir.sh" "$HOME/AppData/Local/Coursier/Cache"
|
||||
- name: Confirm that ~/.cache/coursier directory has been made
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: bash "$GITHUB_WORKSPACE/__tests__/check-dir.sh" "$HOME/.cache/coursier"
|
||||
gradle1-save:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run setup-java with the cache for gradle
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '17'
|
||||
cache: gradle
|
||||
cache-dependency-path: __tests__/cache/gradle1/*.gradle*
|
||||
- name: Create files to cache
|
||||
# Need to avoid using Gradle daemon to stabilize the save process on Windows
|
||||
# https://github.com/actions/cache/issues/454#issuecomment-840493935
|
||||
run: |
|
||||
if [ ! -d ~/.cache/coursier ]; then
|
||||
echo "::error::The ~/.cache/coursier directory does not exist unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
ls ~/.cache/coursier
|
||||
gradle downloadDependencies --no-daemon -p __tests__/cache/gradle1
|
||||
mkdir -p "$HOME/.gradle/wrapper/dists/setup-java-e2e-gradle1"
|
||||
echo "gradle wrapper cache gradle1" > "$HOME/.gradle/wrapper/dists/setup-java-e2e-gradle1/payload"
|
||||
bash __tests__/check-dir.sh "$HOME/.gradle/caches"
|
||||
bash __tests__/check-dir.sh "$HOME/.gradle/wrapper/dists"
|
||||
gradle1-restore:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
needs: gradle1-save
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run setup-java with the cache for gradle
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
cache: gradle
|
||||
cache-dependency-path: __tests__/cache/gradle1/*.gradle*
|
||||
- name: Confirm that ~/.gradle/caches directory has been made
|
||||
run: bash __tests__/check-dir.sh "$HOME/.gradle/caches"
|
||||
- name: Confirm that the Gradle Wrapper cache has been restored
|
||||
run: bash __tests__/check-dir.sh "$HOME/.gradle/wrapper/dists"
|
||||
gradle2-restore:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
needs: gradle1-save
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run setup-java with the cache for gradle
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
cache: gradle
|
||||
cache-dependency-path: __tests__/cache/gradle2/*.gradle*
|
||||
- name: Confirm that ~/.gradle/caches directory has not been made
|
||||
run: bash __tests__/check-dir.sh "$HOME/.gradle/caches" absent
|
||||
maven1-save:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-15-intel, windows-latest, ubuntu-latest]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run setup-java with the cache for maven
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
cache: maven
|
||||
cache-dependency-path: __tests__/cache/maven/pom.xml
|
||||
- name: Create files to cache
|
||||
run: |
|
||||
mvn verify -f __tests__/cache/maven/pom.xml
|
||||
mkdir -p "$HOME/.m2/wrapper/dists/setup-java-e2e-maven1"
|
||||
echo "maven wrapper cache maven1" > "$HOME/.m2/wrapper/dists/setup-java-e2e-maven1/payload"
|
||||
bash __tests__/check-dir.sh "$HOME/.m2/repository"
|
||||
bash __tests__/check-dir.sh "$HOME/.m2/wrapper/dists"
|
||||
maven1-restore:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-15-intel, windows-latest, ubuntu-latest]
|
||||
needs: maven1-save
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run setup-java with the cache for maven
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
cache: maven
|
||||
cache-dependency-path: __tests__/cache/maven/pom.xml
|
||||
- name: Confirm that ~/.m2/repository directory has been made
|
||||
run: bash __tests__/check-dir.sh "$HOME/.m2/repository"
|
||||
- name: Confirm that the Maven Wrapper cache has been restored
|
||||
run: bash __tests__/check-dir.sh "$HOME/.m2/wrapper/dists"
|
||||
maven2-restore:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-15-intel, windows-latest, ubuntu-latest]
|
||||
needs: maven1-save
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run setup-java with the cache for maven
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
cache: maven
|
||||
cache-dependency-path: |
|
||||
__tests__/cache/maven2/pom.xml
|
||||
README.md
|
||||
- name: Confirm that ~/.m2/repository directory has not been made
|
||||
run: bash __tests__/check-dir.sh "$HOME/.m2/repository" absent
|
||||
sbt1-save:
|
||||
runs-on: ${{ matrix.os }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: __tests__/cache/sbt
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-15-intel, windows-latest, ubuntu-22.04]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run setup-java with the cache for sbt
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
cache: sbt
|
||||
cache-dependency-path: __tests__/cache/sbt/*.sbt
|
||||
- name: Setup SBT
|
||||
if: matrix.os == 'macos-15-intel'
|
||||
run: |
|
||||
echo ""Installing SBT...""
|
||||
brew install sbt
|
||||
- name: Create files to cache
|
||||
run: sbt update
|
||||
|
||||
- name: Check files to cache on macos-latest
|
||||
if: matrix.os == 'macos-15-intel'
|
||||
run: bash "$GITHUB_WORKSPACE/__tests__/check-dir.sh" "$HOME/Library/Caches/Coursier"
|
||||
- name: Check files to cache on windows-latest
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: bash "$GITHUB_WORKSPACE/__tests__/check-dir.sh" "$HOME/AppData/Local/Coursier/Cache"
|
||||
- name: Check files to cache on ubuntu-latest
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: bash "$GITHUB_WORKSPACE/__tests__/check-dir.sh" "$HOME/.cache/coursier"
|
||||
sbt1-restore:
|
||||
runs-on: ${{ matrix.os }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: __tests__/cache/sbt
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-15-intel, windows-latest, ubuntu-22.04]
|
||||
needs: sbt1-save
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run setup-java with the cache for sbt
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
cache: sbt
|
||||
cache-dependency-path: __tests__/cache/sbt/*.sbt
|
||||
|
||||
- name: Confirm that ~/Library/Caches/Coursier directory has been made
|
||||
if: matrix.os == 'macos-15-intel'
|
||||
run: bash "$GITHUB_WORKSPACE/__tests__/check-dir.sh" "$HOME/Library/Caches/Coursier"
|
||||
- name: Confirm that ~/AppData/Local/Coursier/Cache directory has been made
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: bash "$GITHUB_WORKSPACE/__tests__/check-dir.sh" "$HOME/AppData/Local/Coursier/Cache"
|
||||
- name: Confirm that ~/.cache/coursier directory has been made
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: bash "$GITHUB_WORKSPACE/__tests__/check-dir.sh" "$HOME/.cache/coursier"
|
||||
sbt2-restore:
|
||||
runs-on: ${{ matrix.os }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: __tests__/cache/sbt2
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-15-intel, windows-latest, ubuntu-22.04]
|
||||
needs: sbt1-save
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run setup-java with the cache for sbt
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
cache: sbt
|
||||
cache-dependency-path: __tests__/cache/sbt2/*.sbt
|
||||
|
||||
- name: Confirm that ~/Library/Caches/Coursier directory has not been made
|
||||
if: matrix.os == 'macos-15-intel'
|
||||
run: bash "$GITHUB_WORKSPACE/__tests__/check-dir.sh" "$HOME/Library/Caches/Coursier" absent
|
||||
- name: Confirm that ~/AppData/Local/Coursier/Cache directory has not been made
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: bash "$GITHUB_WORKSPACE/__tests__/check-dir.sh" "$HOME/AppData/Local/Coursier/Cache" absent
|
||||
- name: Confirm that ~/.cache/coursier directory has not been made
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: bash "$GITHUB_WORKSPACE/__tests__/check-dir.sh" "$HOME/.cache/coursier" absent
|
||||
custom-maven-path-save:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run setup-java with a custom Maven cache path
|
||||
uses: ./
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
cache: maven
|
||||
cache-dependency-path: |
|
||||
__tests__/cache/maven2/pom.xml
|
||||
.github/workflows/e2e-cache.yml
|
||||
cache-path: |
|
||||
${{ runner.temp }}/setup-java-custom-maven-repository
|
||||
!${{ runner.temp }}/setup-java-custom-maven-repository/**/*.lastUpdated
|
||||
- name: Populate the custom Maven repository
|
||||
run: |
|
||||
mvn -Dmaven.repo.local="$RUNNER_TEMP/setup-java-custom-maven-repository" verify -f __tests__/cache/maven2/pom.xml
|
||||
touch "$RUNNER_TEMP/setup-java-custom-maven-repository/setup-java-cache-path-marker"
|
||||
bash __tests__/check-dir.sh "$RUNNER_TEMP/setup-java-custom-maven-repository"
|
||||
custom-maven-path-restore:
|
||||
runs-on: ubuntu-latest
|
||||
needs: custom-maven-path-save
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run setup-java with a custom Maven cache path
|
||||
uses: ./
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
cache: maven
|
||||
cache-dependency-path: |
|
||||
__tests__/cache/maven2/pom.xml
|
||||
.github/workflows/e2e-cache.yml
|
||||
cache-path: |
|
||||
${{ runner.temp }}/setup-java-custom-maven-repository
|
||||
!${{ runner.temp }}/setup-java-custom-maven-repository/**/*.lastUpdated
|
||||
cache-read-only: true
|
||||
- name: Confirm that the custom Maven repository has been restored
|
||||
run: test -f "$RUNNER_TEMP/setup-java-custom-maven-repository/setup-java-cache-path-marker"
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'jdkfile'
|
||||
jdkFile: ${{ runner.temp }}/${{ env.LocalFilename }}
|
||||
jdk-file: ${{ runner.temp }}/${{ env.LocalFilename }}
|
||||
java-version: '11.0.0-ea'
|
||||
architecture: x64
|
||||
- name: Verify Java version
|
||||
@@ -88,7 +88,7 @@ jobs:
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'jdkfile'
|
||||
jdkFile: ${{ runner.temp }}/${{ env.LocalFilename }}
|
||||
jdk-file: ${{ runner.temp }}/${{ env.LocalFilename }}
|
||||
java-version: '11.0.0-ea'
|
||||
architecture: x64
|
||||
- name: Verify Java version
|
||||
@@ -129,6 +129,7 @@ jobs:
|
||||
id: setup-java
|
||||
with:
|
||||
distribution: 'jdkfile'
|
||||
# Intentionally uses the deprecated `jdkFile` alias to keep it covered.
|
||||
jdkFile: ${{ runner.temp }}/${{ env.LocalFilename }}
|
||||
java-version: '11.0.0-ea'
|
||||
architecture: x64
|
||||
|
||||
@@ -38,21 +38,33 @@ jobs:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
server-id: maven
|
||||
server-username: MAVEN_USERNAME
|
||||
server-password: MAVEN_CENTRAL_TOKEN
|
||||
gpg-passphrase: MAVEN_GPG_PASSPHRASE
|
||||
server-username-env-var: MAVEN_USERNAME
|
||||
server-password-env-var: MAVEN_CENTRAL_TOKEN
|
||||
gpg-passphrase-env-var: MAVEN_GPG_PASSPHRASE
|
||||
- name: Validate settings.xml
|
||||
run: |
|
||||
$xmlPath = Join-Path $HOME ".m2" "settings.xml"
|
||||
Get-Content $xmlPath | ForEach-Object { Write-Host $_ }
|
||||
|
||||
[xml]$xml = Get-Content $xmlPath
|
||||
$servers = $xml.settings.servers.server
|
||||
if (($servers[0].id -ne 'maven') -or ($servers[0].username -ne '${env.MAVEN_USERNAME}') -or ($servers[0].password -ne '${env.MAVEN_CENTRAL_TOKEN}')) {
|
||||
throw "Generated XML file is incorrect"
|
||||
}
|
||||
$content = [System.IO.File]::ReadAllText($xmlPath)
|
||||
$expected = @(
|
||||
'<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"'
|
||||
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
|
||||
' xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">'
|
||||
' <interactiveMode>false</interactiveMode>'
|
||||
' <servers>'
|
||||
' <server>'
|
||||
' <id>maven</id>'
|
||||
' <username>${env.MAVEN_USERNAME}</username>'
|
||||
' <password>${env.MAVEN_CENTRAL_TOKEN}</password>'
|
||||
' </server>'
|
||||
' </servers>'
|
||||
'</settings>'
|
||||
) -join "`n"
|
||||
|
||||
if (($servers[1].id -ne 'gpg.passphrase') -or ($servers[1].passphrase -ne '${env.MAVEN_GPG_PASSPHRASE}')) {
|
||||
if ($content -ne $expected) {
|
||||
Write-Host "Expected settings.xml:"
|
||||
$expected -split "`n" | ForEach-Object { Write-Host $_ }
|
||||
throw "Generated XML file is incorrect"
|
||||
}
|
||||
|
||||
@@ -81,9 +93,9 @@ jobs:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
server-id: maven
|
||||
server-username: MAVEN_USERNAME
|
||||
server-password: MAVEN_CENTRAL_TOKEN
|
||||
gpg-passphrase: MAVEN_GPG_PASSPHRASE
|
||||
server-username-env-var: MAVEN_USERNAME
|
||||
server-password-env-var: MAVEN_CENTRAL_TOKEN
|
||||
gpg-passphrase-env-var: MAVEN_GPG_PASSPHRASE
|
||||
- name: Validate settings.xml is overwritten
|
||||
run: |
|
||||
$xmlPath = Join-Path $HOME ".m2" "settings.xml"
|
||||
@@ -119,10 +131,10 @@ jobs:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
server-id: maven
|
||||
server-username: MAVEN_USERNAME
|
||||
server-password: MAVEN_CENTRAL_TOKEN
|
||||
server-username-env-var: MAVEN_USERNAME
|
||||
server-password-env-var: MAVEN_CENTRAL_TOKEN
|
||||
overwrite-settings: false
|
||||
gpg-passphrase: MAVEN_GPG_PASSPHRASE
|
||||
gpg-passphrase-env-var: MAVEN_GPG_PASSPHRASE
|
||||
- name: Validate that settings.xml is not overwritten
|
||||
run: |
|
||||
$xmlPath = Join-Path $HOME ".m2" "settings.xml"
|
||||
@@ -152,9 +164,9 @@ jobs:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
server-id: maven
|
||||
server-username: MAVEN_USERNAME
|
||||
server-password: MAVEN_CENTRAL_TOKEN
|
||||
gpg-passphrase: MAVEN_GPG_PASSPHRASE
|
||||
server-username-env-var: MAVEN_USERNAME
|
||||
server-password-env-var: MAVEN_CENTRAL_TOKEN
|
||||
gpg-passphrase-env-var: MAVEN_GPG_PASSPHRASE
|
||||
settings-path: ${{ runner.temp }}
|
||||
- name: Validate settings.xml location
|
||||
run: |
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
name: Validate Java e2e smoke
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
setup-java:
|
||||
name: ${{ matrix.distribution }} ${{ matrix.version }} (${{ matrix.java-package }}) - ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: macos-latest
|
||||
distribution: temurin
|
||||
version: '11'
|
||||
java-package: jdk
|
||||
- os: windows-latest
|
||||
distribution: temurin
|
||||
version: '17'
|
||||
java-package: jdk
|
||||
- os: ubuntu-latest
|
||||
distribution: temurin
|
||||
version: '21'
|
||||
java-package: jdk
|
||||
- os: macos-latest
|
||||
distribution: temurin
|
||||
version: '25'
|
||||
java-package: jdk
|
||||
- os: windows-latest
|
||||
distribution: temurin
|
||||
version: '25'
|
||||
java-package: jdk
|
||||
- os: ubuntu-latest
|
||||
distribution: temurin
|
||||
version: '25'
|
||||
java-package: jdk
|
||||
- os: macos-latest
|
||||
distribution: microsoft
|
||||
version: '25'
|
||||
java-package: jdk
|
||||
- os: windows-latest
|
||||
distribution: microsoft
|
||||
version: '25'
|
||||
java-package: jdk
|
||||
- os: ubuntu-latest
|
||||
distribution: microsoft
|
||||
version: '25'
|
||||
java-package: jdk
|
||||
- os: ubuntu-latest
|
||||
distribution: zulu
|
||||
version: '17'
|
||||
java-package: jre
|
||||
- os: ubuntu-latest
|
||||
distribution: liberica
|
||||
version: '21'
|
||||
java-package: jdk+fx
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: setup-java
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
java-version: ${{ matrix.version }}
|
||||
java-package: ${{ matrix.java-package }}
|
||||
distribution: ${{ matrix.distribution }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Verify Java
|
||||
env:
|
||||
JAVA_VERSION: ${{ matrix.version }}
|
||||
JAVA_PATH: ${{ steps.setup-java.outputs.path }}
|
||||
run: bash __tests__/verify-java.sh "$JAVA_VERSION" "$JAVA_PATH"
|
||||
shell: bash
|
||||
+195
-152
@@ -3,13 +3,9 @@ name: Validate Java e2e
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- releases/*
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
schedule:
|
||||
- cron: '0 */12 * * *'
|
||||
workflow_dispatch:
|
||||
@@ -36,7 +32,9 @@ jobs:
|
||||
'corretto',
|
||||
'dragonwell',
|
||||
'sapmachine',
|
||||
'jetbrains'
|
||||
'jetbrains',
|
||||
'kona',
|
||||
'liberica-nik'
|
||||
] # internally 'adopt-hotspot' is the same as 'adopt'
|
||||
version: ['21', '11', '17']
|
||||
exclude:
|
||||
@@ -54,6 +52,24 @@ jobs:
|
||||
- distribution: microsoft
|
||||
os: macos-latest
|
||||
version: 25
|
||||
- distribution: kona
|
||||
os: windows-latest
|
||||
version: 25
|
||||
- distribution: kona
|
||||
os: ubuntu-latest
|
||||
version: 25
|
||||
- distribution: kona
|
||||
os: macos-latest
|
||||
version: 25
|
||||
- distribution: liberica-nik
|
||||
os: windows-latest
|
||||
version: 25
|
||||
- distribution: liberica-nik
|
||||
os: ubuntu-latest
|
||||
version: 25
|
||||
- distribution: liberica-nik
|
||||
os: macos-latest
|
||||
version: 25
|
||||
- distribution: oracle
|
||||
os: macos-15-intel
|
||||
version: 17
|
||||
@@ -63,6 +79,15 @@ jobs:
|
||||
- distribution: oracle
|
||||
os: ubuntu-latest
|
||||
version: 21
|
||||
- distribution: oracle-openjdk
|
||||
os: macos-15-intel
|
||||
version: 21
|
||||
- distribution: oracle-openjdk
|
||||
os: windows-latest
|
||||
version: 21
|
||||
- distribution: oracle-openjdk
|
||||
os: ubuntu-latest
|
||||
version: 21
|
||||
- distribution: graalvm
|
||||
os: macos-latest
|
||||
version: 17.0.12
|
||||
@@ -76,7 +101,8 @@ jobs:
|
||||
os: ubuntu-latest
|
||||
version: '24-ea'
|
||||
steps:
|
||||
- name: Checkout
|
||||
- &checkout_step
|
||||
name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
@@ -95,6 +121,25 @@ jobs:
|
||||
run: bash __tests__/verify-java.sh "$JAVA_VERSION" "$JAVA_PATH"
|
||||
shell: bash
|
||||
|
||||
setup-java-checksum-verification:
|
||||
name: Corretto checksum verification - ubuntu-latest
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- *checkout_step
|
||||
- name: setup-java with forced download
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: corretto
|
||||
force-download: true
|
||||
- name: Verify Java
|
||||
env:
|
||||
JAVA_VERSION: '21'
|
||||
JAVA_PATH: ${{ steps.setup-java.outputs.path }}
|
||||
run: bash __tests__/verify-java.sh "$JAVA_VERSION" "$JAVA_PATH"
|
||||
shell: bash
|
||||
|
||||
setup-java-alpine-linux:
|
||||
name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-${{ contains(matrix.os, 'macos') && !contains(matrix.os, 'intel') && 'arm64' || 'x64' }}) - alpine-linux - ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -107,10 +152,7 @@ jobs:
|
||||
distribution: ['temurin', 'sapmachine']
|
||||
version: ['21', '17']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- *checkout_step
|
||||
- name: Install bash
|
||||
run: apk add --no-cache bash
|
||||
- name: setup-java
|
||||
@@ -133,7 +175,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
os: &default_os [macos-latest, windows-latest, ubuntu-latest]
|
||||
distribution: ['temurin', 'zulu', 'liberica']
|
||||
version:
|
||||
- '11.0'
|
||||
@@ -162,10 +204,7 @@ jobs:
|
||||
os: ubuntu-latest
|
||||
version: '17.0.7'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- *checkout_step
|
||||
- name: setup-java
|
||||
uses: ./
|
||||
id: setup-java
|
||||
@@ -187,7 +226,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
os: *default_os
|
||||
distribution:
|
||||
[
|
||||
'temurin',
|
||||
@@ -201,10 +240,7 @@ jobs:
|
||||
- distribution: dragonwell
|
||||
os: macos-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- *checkout_step
|
||||
- name: setup-java
|
||||
uses: ./
|
||||
id: setup-java
|
||||
@@ -227,7 +263,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
os: *default_os
|
||||
distribution:
|
||||
[
|
||||
'temurin',
|
||||
@@ -241,10 +277,7 @@ jobs:
|
||||
- distribution: dragonwell
|
||||
os: macos-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- *checkout_step
|
||||
- name: setup-java
|
||||
uses: ./
|
||||
id: setup-java
|
||||
@@ -274,26 +307,37 @@ jobs:
|
||||
run: bash __tests__/verify-java.sh "17" "$JAVA_PATH"
|
||||
shell: bash
|
||||
|
||||
setup-java-ea-versions-zulu:
|
||||
name: zulu ${{ matrix.version }} (jdk-${{ contains(matrix.os, 'macos') && !contains(matrix.os, 'intel') && 'arm64' || 'x64' }}) - ${{ matrix.os }}
|
||||
setup-java-ea-versions:
|
||||
name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-${{ contains(matrix.os, 'macos') && !contains(matrix.os, 'intel') && 'arm64' || 'x64' }}) - ${{ matrix.os }}
|
||||
needs: setup-java-major-minor-versions
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-15-intel, windows-latest, ubuntu-latest]
|
||||
version: ['17-ea', '15.0.0-ea.14']
|
||||
include:
|
||||
- {os: macos-15-intel, version: '17-ea', distribution: zulu}
|
||||
- {os: windows-latest, version: '17-ea', distribution: zulu}
|
||||
- {os: ubuntu-latest, version: '17-ea', distribution: zulu}
|
||||
- {os: macos-15-intel, version: '15.0.0-ea.14', distribution: zulu}
|
||||
- {os: windows-latest, version: '15.0.0-ea.14', distribution: zulu}
|
||||
- {os: ubuntu-latest, version: '15.0.0-ea.14', distribution: zulu}
|
||||
- {os: macos-latest, version: '17-ea', distribution: temurin}
|
||||
- {os: windows-latest, version: '17-ea', distribution: temurin}
|
||||
- {os: ubuntu-latest, version: '17-ea', distribution: temurin}
|
||||
- {os: macos-latest, version: '17-ea', distribution: sapmachine}
|
||||
- {os: windows-latest, version: '17-ea', distribution: sapmachine}
|
||||
- {os: ubuntu-latest, version: '17-ea', distribution: sapmachine}
|
||||
- {os: macos-latest, version: '21-ea', distribution: sapmachine}
|
||||
- {os: windows-latest, version: '21-ea', distribution: sapmachine}
|
||||
- {os: ubuntu-latest, version: '21-ea', distribution: sapmachine}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- *checkout_step
|
||||
- name: setup-java
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
java-version: ${{ matrix.version }}
|
||||
distribution: zulu
|
||||
distribution: ${{ matrix.distribution }}
|
||||
- name: Verify Java
|
||||
env:
|
||||
JAVA_VERSION: ${{ matrix.version }}
|
||||
@@ -301,53 +345,24 @@ jobs:
|
||||
run: bash __tests__/verify-java.sh "$JAVA_VERSION" "$JAVA_PATH"
|
||||
shell: bash
|
||||
|
||||
setup-java-ea-versions-temurin:
|
||||
name: temurin ${{ matrix.version }} (jdk-${{ contains(matrix.os, 'macos') && !contains(matrix.os, 'intel') && 'arm64' || 'x64' }}) - ${{ matrix.os }}
|
||||
setup-java-signature-verification:
|
||||
name: ${{ matrix.distribution }} ${{ matrix.version }} signature verification - ${{ matrix.os }}
|
||||
needs: setup-java-major-minor-versions
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
version: ['17-ea']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: setup-java
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
java-version: ${{ matrix.version }}
|
||||
distribution: temurin
|
||||
- name: Verify Java
|
||||
env:
|
||||
JAVA_VERSION: ${{ matrix.version }}
|
||||
JAVA_PATH: ${{ steps.setup-java.outputs.path }}
|
||||
run: bash __tests__/verify-java.sh "$JAVA_VERSION" "$JAVA_PATH"
|
||||
shell: bash
|
||||
|
||||
setup-java-temurin-signature-verification:
|
||||
name: temurin ${{ matrix.version }} signature verification - ${{ matrix.os }}
|
||||
needs: setup-java-major-minor-versions
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
os: *default_os
|
||||
version: ['21', '17']
|
||||
distribution: [temurin, microsoft]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- *checkout_step
|
||||
- name: setup-java with signature verification
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
java-version: ${{ matrix.version }}
|
||||
distribution: temurin
|
||||
distribution: ${{ matrix.distribution }}
|
||||
verify-signature: true
|
||||
- name: Verify Java
|
||||
env:
|
||||
@@ -356,61 +371,6 @@ jobs:
|
||||
run: bash __tests__/verify-java.sh "$JAVA_VERSION" "$JAVA_PATH"
|
||||
shell: bash
|
||||
|
||||
setup-java-microsoft-signature-verification:
|
||||
name: microsoft ${{ matrix.version }} signature verification - ${{ matrix.os }}
|
||||
needs: setup-java-major-minor-versions
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
version: ['21', '17']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: setup-java with signature verification
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
java-version: ${{ matrix.version }}
|
||||
distribution: microsoft
|
||||
verify-signature: true
|
||||
- name: Verify Java
|
||||
env:
|
||||
JAVA_VERSION: ${{ matrix.version }}
|
||||
JAVA_PATH: ${{ steps.setup-java.outputs.path }}
|
||||
run: bash __tests__/verify-java.sh "$JAVA_VERSION" "$JAVA_PATH"
|
||||
shell: bash
|
||||
|
||||
setup-java-ea-versions-sapmachine:
|
||||
name: sapmachine ${{ matrix.version }} (jdk-${{ contains(matrix.os, 'macos') && !contains(matrix.os, 'intel') && 'arm64' || 'x64' }}) - ${{ matrix.os }}
|
||||
needs: setup-java-major-minor-versions
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
version: ['17-ea', '21-ea']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: setup-java
|
||||
uses: ./
|
||||
id: setup-java
|
||||
with:
|
||||
java-version: ${{ matrix.version }}
|
||||
distribution: sapmachine
|
||||
- name: Verify Java
|
||||
env:
|
||||
JAVA_VERSION: ${{ matrix.version }}
|
||||
JAVA_PATH: ${{ steps.setup-java.outputs.path }}
|
||||
run: bash __tests__/verify-java.sh "$JAVA_VERSION" "$JAVA_PATH"
|
||||
shell: bash
|
||||
|
||||
setup-java-custom-package-type:
|
||||
name: ${{ matrix.distribution }} ${{ matrix.version }} (${{ matrix.java-package }}-x64) - ${{ matrix.os }}
|
||||
needs: setup-java-major-minor-versions
|
||||
@@ -440,6 +400,10 @@ jobs:
|
||||
java-package: jre+fx
|
||||
version: '11'
|
||||
os: ubuntu-latest
|
||||
- distribution: 'liberica-nik'
|
||||
java-package: jdk+fx
|
||||
version: '21'
|
||||
os: ubuntu-latest
|
||||
- distribution: 'corretto'
|
||||
java-package: jre
|
||||
version: '8'
|
||||
@@ -486,10 +450,7 @@ jobs:
|
||||
os: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- *checkout_step
|
||||
- name: setup-java
|
||||
uses: ./
|
||||
id: setup-java
|
||||
@@ -519,10 +480,7 @@ jobs:
|
||||
distribution: ['liberica', 'zulu', 'corretto']
|
||||
version: ['11']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- *checkout_step
|
||||
- name: setup-java
|
||||
uses: ./
|
||||
id: setup-java
|
||||
@@ -537,20 +495,36 @@ jobs:
|
||||
run: bash __tests__/verify-java.sh "$JAVA_VERSION" "$JAVA_PATH"
|
||||
shell: bash
|
||||
|
||||
setup-java-unsupported-platform:
|
||||
name: Reject unsupported Oracle x86 on Linux
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- *checkout_step
|
||||
- name: Attempt unsupported setup
|
||||
id: unsupported-setup
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
distribution: oracle
|
||||
java-version: '21'
|
||||
architecture: x86
|
||||
- name: Verify setup was rejected
|
||||
if: always()
|
||||
env:
|
||||
SETUP_OUTCOME: ${{ steps.unsupported-setup.outcome }}
|
||||
run: test "$SETUP_OUTCOME" = failure
|
||||
|
||||
setup-java-version-both-version-inputs-presents:
|
||||
name: ${{ matrix.distribution }} version (should be from input) - ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
os: *default_os
|
||||
distribution: ['temurin', 'microsoft', 'corretto']
|
||||
java-version-file: ['.java-version', '.tool-versions']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- *checkout_step
|
||||
- name: Create .java-version file
|
||||
shell: bash
|
||||
run: echo "17" > .java-version
|
||||
@@ -576,14 +550,11 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
os: *default_os
|
||||
distribution: ['temurin', 'zulu', 'liberica', 'microsoft', 'corretto']
|
||||
java-version-file: ['.java-version', '.tool-versions']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- *checkout_step
|
||||
- name: Create .java-version file
|
||||
shell: bash
|
||||
run: echo "11" > .java-version
|
||||
@@ -608,14 +579,11 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
os: *default_os
|
||||
distribution: ['adopt', 'adopt-openj9', 'zulu']
|
||||
java-version-file: ['.java-version', '.tool-versions']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- *checkout_step
|
||||
- name: Create .java-version file
|
||||
shell: bash
|
||||
run: echo "17.0.10" > .java-version
|
||||
@@ -640,14 +608,11 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
os: *default_os
|
||||
distribution: ['adopt', 'zulu', 'liberica']
|
||||
java-version-file: ['.java-version', '.tool-versions', '.sdkmanrc']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- *checkout_step
|
||||
- name: Create .java-version file
|
||||
shell: bash
|
||||
run: echo "openjdk64-17.0.10" > .java-version
|
||||
@@ -668,3 +633,81 @@ jobs:
|
||||
JAVA_PATH: ${{ steps.setup-java.outputs.path }}
|
||||
run: bash __tests__/verify-java.sh "17.0.10" "$JAVA_PATH"
|
||||
shell: bash
|
||||
|
||||
setup-java-set-default:
|
||||
name: set-default option - ${{ matrix.os }}
|
||||
needs: setup-java-major-versions
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: *default_os
|
||||
steps:
|
||||
- *checkout_step
|
||||
- name: Setup Java 17 as default
|
||||
uses: ./
|
||||
id: setup-java-17
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Setup Java 21 without setting as default
|
||||
uses: ./
|
||||
id: setup-java-21
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '21'
|
||||
set-default: false
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Verify JAVA_HOME still points to Java 17
|
||||
env:
|
||||
JAVA_17_PATH: ${{ steps.setup-java-17.outputs.path }}
|
||||
run: |
|
||||
echo "JAVA_HOME=$JAVA_HOME"
|
||||
echo "Java 17 path=$JAVA_17_PATH"
|
||||
if [ "$JAVA_HOME" != "$JAVA_17_PATH" ]; then
|
||||
echo "JAVA_HOME should still point to Java 17"
|
||||
exit 1
|
||||
fi
|
||||
shell: bash
|
||||
- name: Verify java -version reports Java 17
|
||||
run: |
|
||||
JAVA_VERSION=$(java -version 2>&1 | head -1)
|
||||
echo "java -version: $JAVA_VERSION"
|
||||
if ! echo "$JAVA_VERSION" | grep -q "17"; then
|
||||
echo "Default java should still be version 17"
|
||||
exit 1
|
||||
fi
|
||||
shell: bash
|
||||
- name: Verify JAVA_HOME_21 env var is set
|
||||
run: |
|
||||
$envName = "JAVA_HOME_21_${env:RUNNER_ARCH}"
|
||||
$JavaVersionPath = [Environment]::GetEnvironmentVariable($envName)
|
||||
if (-not $JavaVersionPath) {
|
||||
Write-Host "$envName is not set"
|
||||
exit 1
|
||||
}
|
||||
if (-not (Test-Path "$JavaVersionPath")) {
|
||||
Write-Host "$envName path does not exist: $JavaVersionPath"
|
||||
exit 1
|
||||
}
|
||||
Write-Host "$envName=$JavaVersionPath"
|
||||
shell: pwsh
|
||||
- name: Verify Java 21 outputs are set
|
||||
env:
|
||||
JAVA_21_PATH: ${{ steps.setup-java-21.outputs.path }}
|
||||
JAVA_21_VERSION: ${{ steps.setup-java-21.outputs.version }}
|
||||
run: |
|
||||
echo "Java 21 path=$JAVA_21_PATH"
|
||||
echo "Java 21 version=$JAVA_21_VERSION"
|
||||
if [ -z "$JAVA_21_PATH" ]; then
|
||||
echo "Java 21 path output should be set"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$JAVA_21_VERSION" ]; then
|
||||
echo "Java 21 version output should be set"
|
||||
exit 1
|
||||
fi
|
||||
shell: bash
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
uses: actions/setup-python@v7
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
|
||||
+4
-1
@@ -10,8 +10,11 @@ allowed:
|
||||
- mit
|
||||
- cc0-1.0
|
||||
- unlicense
|
||||
- blueoak-1.0.0
|
||||
|
||||
reviewed:
|
||||
npm:
|
||||
- "@actions/http-client" # MIT (license text present), but detected as "other"
|
||||
- "argparse" # Python Software Foundation License (PSF), but detected as "other"
|
||||
- "argparse" # Python Software Foundation License (PSF), but detected as "other"
|
||||
- "balanced-match"
|
||||
- "brace-expansion"
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@actions/cache"
|
||||
version: 5.1.0
|
||||
version: 6.2.0
|
||||
type: npm
|
||||
summary: Actions cache lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/cache
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@actions/core"
|
||||
version: 2.0.3
|
||||
version: 3.0.1
|
||||
type: npm
|
||||
summary: Actions core lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/core
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@actions/exec"
|
||||
version: 2.0.0
|
||||
version: 3.0.0
|
||||
type: npm
|
||||
summary: Actions exec lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/exec
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@actions/glob"
|
||||
version: 0.5.1
|
||||
version: 0.7.0
|
||||
type: npm
|
||||
summary: Actions glob lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/glob
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@actions/http-client"
|
||||
version: 3.0.2
|
||||
version: 4.0.1
|
||||
type: npm
|
||||
summary: Actions Http Client
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/http-client
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@actions/io"
|
||||
version: 2.0.0
|
||||
version: 3.0.2
|
||||
type: npm
|
||||
summary: Actions io lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/io
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@actions/tool-cache"
|
||||
version: 3.0.1
|
||||
version: 4.0.0
|
||||
type: npm
|
||||
summary: Actions tool-cache lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/tool-cache
|
||||
|
||||
Generated
+4
-4
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@azure/abort-controller"
|
||||
version: 2.1.2
|
||||
version: 2.2.0
|
||||
type: npm
|
||||
summary: Microsoft Azure SDK for JavaScript - Aborter
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/abort-controller/README.md
|
||||
@@ -8,9 +8,9 @@ license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Copyright (c) 2020 Microsoft
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,7 +22,7 @@ licenses:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
Generated
+2
-2
@@ -1,10 +1,10 @@
|
||||
---
|
||||
name: "@azure/core-auth"
|
||||
version: 1.10.1
|
||||
version: 1.11.0
|
||||
type: npm
|
||||
summary: Provides low-level interfaces and helper methods for authentication in Azure
|
||||
SDK
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-auth/README.md
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-auth/README.md
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@azure/core-client"
|
||||
version: 1.10.1
|
||||
version: 1.11.0
|
||||
type: npm
|
||||
summary: Core library for interfacing with AutoRest generated code
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-client/
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: "@azure/core-http-compat"
|
||||
version: 2.3.1
|
||||
version: 2.5.0
|
||||
type: npm
|
||||
summary: Core HTTP Compatibility Library to bridge the gap between Core V1 & V2 packages.
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-compat/
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-http-compat/
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
|
||||
Generated
+4
-4
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@azure/core-paging"
|
||||
version: 1.6.2
|
||||
version: 1.7.0
|
||||
type: npm
|
||||
summary: Core types for paging async iterable iterators
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-paging/README.md
|
||||
@@ -8,9 +8,9 @@ license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Copyright (c) 2020 Microsoft
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,7 +22,7 @@ licenses:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: "@azure/core-rest-pipeline"
|
||||
version: 1.22.2
|
||||
version: 1.25.0
|
||||
type: npm
|
||||
summary: Isomorphic client library for making HTTP requests in node.js and browser.
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-rest-pipeline/
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-rest-pipeline/README.md
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@azure/core-tracing"
|
||||
version: 1.3.1
|
||||
version: 1.4.0
|
||||
type: npm
|
||||
summary: Provides low-level interfaces and helper methods for tracing in Azure SDK
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-tracing/README.md
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@azure/core-util"
|
||||
version: 1.13.1
|
||||
version: 1.14.0
|
||||
type: npm
|
||||
summary: Core library for shared utility methods
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-util/
|
||||
|
||||
Generated
+2
-2
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: "@azure/core-xml"
|
||||
version: 1.5.0
|
||||
version: 1.6.0
|
||||
type: npm
|
||||
summary: Core library for interacting with XML payloads
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-xml/
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-xml/README.md
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@azure/logger"
|
||||
version: 1.3.0
|
||||
version: 1.4.0
|
||||
type: npm
|
||||
summary: Microsoft Azure SDK for JavaScript - Logger
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger/README.md
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: "@azure/storage-blob"
|
||||
version: 12.29.1
|
||||
version: 12.33.0
|
||||
type: npm
|
||||
summary: Microsoft Azure Storage SDK for JavaScript - Blob
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/storage/storage-blob/
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/storage-blob/README.md
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: "@azure/storage-common"
|
||||
version: 12.1.1
|
||||
version: 12.4.1
|
||||
type: npm
|
||||
summary: Azure Storage Common Client Library for JavaScript
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/storage/storage-internal-avro/
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/storage-common/README.md
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@nodable/entities"
|
||||
version: 2.2.0
|
||||
version: 3.0.0
|
||||
type: npm
|
||||
summary: Entity parser for XML, HTML, External entites with security and NCR control
|
||||
homepage:
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: "@typespec/ts-http-runtime"
|
||||
version: 0.3.2
|
||||
version: 0.3.7
|
||||
type: npm
|
||||
summary: Isomorphic client library for making HTTP requests in node.js and browser.
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/ts-http-runtime/
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/ts-http-runtime/README.md
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
|
||||
Generated
+3
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: anynum
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
type: npm
|
||||
summary: Normalize all Unicode decimal digits (Devanagari, Arabic, Thai, etc.) to
|
||||
ASCII numerals. Zero dependencies, performance-first.
|
||||
@@ -30,4 +30,6 @@ licenses:
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
- sources: README.md
|
||||
text: MIT
|
||||
notices: []
|
||||
|
||||
Generated
+4
-25
@@ -1,39 +1,18 @@
|
||||
---
|
||||
name: balanced-match
|
||||
version: 1.0.2
|
||||
version: 4.0.4
|
||||
type: npm
|
||||
summary: Match balanced character pairs, like "{" and "}"
|
||||
homepage: https://github.com/juliangruber/balanced-match
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE.md
|
||||
text: |
|
||||
(MIT)
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||
Original code Copyright Julian Gruber <julian@juliangruber.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
- sources: README.md
|
||||
text: |-
|
||||
(MIT)
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||
Port to TypeScript Copyright Isaac Z. Schlueter <i@izs.me>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
||||
Generated
+5
-26
@@ -1,16 +1,18 @@
|
||||
---
|
||||
name: brace-expansion
|
||||
version: 1.1.13
|
||||
version: 5.0.8
|
||||
type: npm
|
||||
summary: Brace expansion as known from sh/bash
|
||||
homepage: https://github.com/juliangruber/brace-expansion
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||
Copyright Julian Gruber <julian@juliangruber.com>
|
||||
|
||||
TypeScript port Copyright Isaac Z. Schlueter <i@izs.me>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,29 +24,6 @@ licenses:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
- sources: README.md
|
||||
text: |-
|
||||
(MIT)
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
|
||||
Generated
-31
@@ -1,31 +0,0 @@
|
||||
---
|
||||
name: concat-map
|
||||
version: 0.0.1
|
||||
type: npm
|
||||
summary: concatenative mapdashery
|
||||
homepage: https://github.com/substack/node-concat-map#readme
|
||||
license: other
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
This software is released under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
- sources: README.markdown
|
||||
text: MIT
|
||||
notices: []
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: fast-xml-builder
|
||||
version: 1.2.0
|
||||
version: 1.3.0
|
||||
type: npm
|
||||
summary: Build XML from JSON without C/C++ based libraries
|
||||
homepage:
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: fast-xml-parser
|
||||
version: 5.8.0
|
||||
version: 5.10.1
|
||||
type: npm
|
||||
summary: Validate XML, Parse XML, Build XML without C/C++ based libraries
|
||||
homepage:
|
||||
|
||||
+9
-6
@@ -1,16 +1,17 @@
|
||||
---
|
||||
name: "@azure/abort-controller"
|
||||
version: 1.1.0
|
||||
name: is-unsafe
|
||||
version: 2.0.0
|
||||
type: npm
|
||||
summary: Microsoft Azure SDK for JavaScript - Aborter
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/abort-controller/README.md
|
||||
summary: Zero-dependency, DOM-free, pure predicate for detecting unsafe strings across
|
||||
HTML, XML, SVG, SQL, SHELL, and REGEX contexts
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Microsoft
|
||||
Copyright (c) 2026 Natural Intelligence
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -29,4 +30,6 @@ licenses:
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
- sources: README.md
|
||||
text: MIT
|
||||
notices: []
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: js-yaml
|
||||
version: 4.1.1
|
||||
version: 4.3.0
|
||||
type: npm
|
||||
summary: YAML 1.2 parser and serializer
|
||||
homepage:
|
||||
|
||||
Generated
+55
-15
@@ -1,26 +1,66 @@
|
||||
---
|
||||
name: minimatch
|
||||
version: 3.1.5
|
||||
version: 10.2.6
|
||||
type: npm
|
||||
summary: a glob matcher in javascript
|
||||
homepage:
|
||||
license: isc
|
||||
license: blueoak-1.0.0
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
- sources: LICENSE.md
|
||||
text: |
|
||||
The ISC License
|
||||
# Blue Oak Model License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
Version 1.0.0
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
## Purpose
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
This license gives everyone as much permission to work with
|
||||
this software as possible, while protecting contributors
|
||||
from liability.
|
||||
|
||||
## Acceptance
|
||||
|
||||
In order to receive this license, you must agree to its
|
||||
rules. The rules of this license are both obligations
|
||||
under that agreement and conditions to your license.
|
||||
You must not do anything with this software that triggers
|
||||
a rule that you cannot or will not follow.
|
||||
|
||||
## Copyright
|
||||
|
||||
Each contributor licenses you to do everything with this
|
||||
software that would otherwise infringe that contributor's
|
||||
copyright in it.
|
||||
|
||||
## Notices
|
||||
|
||||
You must ensure that everyone who gets a copy of
|
||||
any part of this software from you, with or without
|
||||
changes, also gets the text of this license or a link to
|
||||
<https://blueoakcouncil.org/license/1.0.0>.
|
||||
|
||||
## Excuse
|
||||
|
||||
If anyone notifies you in writing that you have not
|
||||
complied with [Notices](#notices), you can keep your
|
||||
license by taking all practical steps to comply within 30
|
||||
days after the notice. If you do not do so, your license
|
||||
ends immediately.
|
||||
|
||||
## Patent
|
||||
|
||||
Each contributor licenses you to do everything with this
|
||||
software that would otherwise infringe any patent claims
|
||||
they can license or become able to license.
|
||||
|
||||
## Reliability
|
||||
|
||||
No contributor can revoke this license.
|
||||
|
||||
## No Liability
|
||||
|
||||
**_As far as the law allows, this software comes as is,
|
||||
without any warranty or condition, and no contributor
|
||||
will be liable to anyone for any damages related to this
|
||||
software or this license, under any kind of legal claim._**
|
||||
notices: []
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: path-expression-matcher
|
||||
version: 1.5.0
|
||||
version: 1.6.2
|
||||
type: npm
|
||||
summary: Efficient path tracking and pattern matching for XML/JSON parsers
|
||||
homepage: https://github.com/NaturalIntelligence/path-expression-matcher#readme
|
||||
|
||||
Generated
-26
@@ -1,26 +0,0 @@
|
||||
---
|
||||
name: semver
|
||||
version: 6.3.1
|
||||
type: npm
|
||||
summary: The semantic version parser used by npm.
|
||||
homepage:
|
||||
license: isc
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
notices: []
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: semver
|
||||
version: 7.8.4
|
||||
version: 7.8.5
|
||||
type: npm
|
||||
summary: The semantic version parser used by npm.
|
||||
homepage:
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: strnum
|
||||
version: 2.4.0
|
||||
version: 2.4.1
|
||||
type: npm
|
||||
summary: Parse String to Number based on configuration
|
||||
homepage:
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: undici
|
||||
version: 6.27.0
|
||||
version: 6.28.0
|
||||
type: npm
|
||||
summary: An HTTP/1.1 client, written from scratch for Node.js
|
||||
homepage: https://undici.nodejs.org
|
||||
|
||||
Generated
+24
-1
@@ -1,12 +1,35 @@
|
||||
---
|
||||
name: xml-naming
|
||||
version: 0.1.0
|
||||
version: 0.3.0
|
||||
type: npm
|
||||
summary: Validates XML name productions — Name, NCName, QName, NMToken, NMTokens —
|
||||
for XML 1.0 and 1.1
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Natural Intelligence
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
- sources: README.md
|
||||
text: MIT
|
||||
notices: []
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
// This is a reusable configuration file copied from https://github.com/actions/reusable-workflows/tree/main/reusable-configurations. Please don't make changes to this file as it's the subject of an automatic update.
|
||||
module.exports = {
|
||||
printWidth: 80,
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
semi: true,
|
||||
singleQuote: true,
|
||||
trailingComma: 'none',
|
||||
bracketSpacing: false,
|
||||
arrowParens: 'avoid'
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": false,
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
@@ -18,6 +18,21 @@ The `setup-java` action provides the following functionality for GitHub Actions
|
||||
|
||||
This action allows you to work with Java and Scala projects.
|
||||
|
||||
## What's new in V6
|
||||
|
||||
> [!NOTE]
|
||||
> V6 is still in development (`main` branch) and is not yet recommended for production workflows.
|
||||
|
||||
- **Migrated to ESM** to enable support for the latest `@actions/*` package versions. This is an internal implementation change.
|
||||
|
||||
## Breaking changes in V6
|
||||
|
||||
- **Renamed inputs that accept environment-variable names** to make it clear that their values are not credentials. Replace `server-username`, `server-password`, and `gpg-passphrase` with `server-username-env-var`, `server-password-env-var`, and `gpg-passphrase-env-var`, respectively. The old names remain as deprecated aliases and emit a warning when used.
|
||||
|
||||
- **The GPG passphrase is now passed to the Maven GPG Plugin through an environment variable (`gpg.passphraseEnvName`) instead of the deprecated `gpg.passphrase` server in `settings.xml`.** Set the environment variable name with `gpg-passphrase-env-var`, which defaults to `GPG_PASSPHRASE`. This requires `maven-gpg-plugin` **3.2.0 or newer**; older versions do not honor `gpg.passphraseEnvName` and, because the `gpg.passphrase` server is no longer written, will not pick up the passphrase. Upgrade the plugin to 3.2.0+.
|
||||
|
||||
See [GPG](docs/advanced-usage.md#gpg) for details.
|
||||
|
||||
## Breaking changes in V5
|
||||
|
||||
- Upgraded action from node20 to node24
|
||||
@@ -29,26 +44,38 @@ For more details, see the full release notes on the [releases page](https://git
|
||||
|
||||
- `java-version`: The Java version that is going to be set up. Takes a whole or [semver](#supported-version-syntax) Java version. If not specified, the action will expect `java-version-file` input to be specified.
|
||||
|
||||
- `java-version-file`: The path to a file containing java version. Supported file types are `.java-version` and `.tool-versions`. See more details in [about .java-version-file](docs/advanced-usage.md#Java-version-file).
|
||||
- `java-version-file`: The path to a file containing java version. Supported file types are `.java-version`, `.tool-versions`, and `.sdkmanrc`. See more details in [about .java-version-file](docs/advanced-usage.md#Java-version-file).
|
||||
|
||||
- `distribution`: _(required)_ Java [distribution](#supported-distributions).
|
||||
- `distribution`: Java [distribution](#supported-distributions). Required unless `java-version-file` points to `.sdkmanrc` with a recognized distribution suffix (for example `java=21.0.5-tem`).
|
||||
|
||||
- `java-package`: The packaging variant of the chosen distribution. Possible values: `jdk`, `jre`, `jdk+fx`, `jre+fx`. Default value: `jdk`.
|
||||
- `java-package`: The packaging variant of the chosen distribution. Possible values across all distributions are `jdk`, `jre`, `jdk+fx`, `jre+fx`, `jdk+crac`, `jre+crac`, `jdk+jmods`, `jdk+jcef`, `jre+jcef`, `jdk+ft`, and `jre+ft`. Supported values vary by distribution; see the [package compatibility table](docs/advanced-usage.md#package-compatibility). Default value: `jdk`.
|
||||
|
||||
- `architecture`: The target architecture of the package. Possible values: `x86`, `x64`, `armv7`, `aarch64`, `ppc64le`. Default value: Derived from the runner machine.
|
||||
- `architecture`: The target architecture of the package. Canonical values are `x86`, `x64`, `armv7`, `aarch64`, `ppc64le`, `ppc64`, and `s390x`; the aliases `ia32`, `amd64`, `arm`, and `arm64` normalize to `x86`, `x64`, `armv7`, and `aarch64`. Supported values vary by distribution and operating system. Default value: Derived from the runner machine.
|
||||
|
||||
- `jdkFile`: If a use-case requires a custom distribution setup-java uses the compressed JDK from the location pointed by this input and will take care of the installation and caching on the VM. Note: `distribution` must be set to 'jdkfile' (case-sensitive; all lowercase) when using this option.
|
||||
- `jdk-file`: If a use-case requires a custom distribution setup-java uses the compressed JDK from the location pointed by this input and will take care of the installation and caching on the VM. Note: `distribution` must be set to 'jdkfile' (case-sensitive; all lowercase) when using this option. (The camelCase `jdkFile` input is still accepted as a deprecated alias and may be removed in a future release.)
|
||||
|
||||
- `check-latest`: Setting this option makes the action to check for the latest available version for the version spec.
|
||||
|
||||
- `force-download`: Set to `true` to always download Java and replace any matching version in the tool cache. This can help make builds reproducible when a runner image has modified a pre-installed JDK, such as its `cacerts` file. Default value: `false`.
|
||||
|
||||
- `set-default`: Set to `false` to install a JDK without making it the default. When `false`, `JAVA_HOME` and `PATH` are not updated, but `JAVA_HOME_<major>_<arch>` is still set so the JDK remains discoverable. Default value: `true`. See [Installing JDK without setting as default](docs/advanced-usage.md#Installing-JDK-without-setting-as-default) for more details.
|
||||
|
||||
- `problem-matcher`: Set to `false` to disable Java problem matcher annotations (compiler diagnostics and uncaught exceptions). Default value: `true`. See [Java problem matcher](docs/advanced-usage.md#java-problem-matcher-compiler-annotations) for details and annotation limits.
|
||||
|
||||
- `verify-signature`: Verifies downloaded Java package signatures when supported by the selected distribution. Currently supported for `temurin` and `microsoft`. If set to `true` for unsupported distributions, the action fails.
|
||||
|
||||
- `verify-signature-public-key`: ASCII-armored GPG public key used to verify the downloaded package signature. Overrides the default bundled key for the selected distribution.
|
||||
|
||||
- `token`: The token used to authenticate when fetching version manifests hosted on GitHub.com. Defaults to `${{ github.token }}` when running on GitHub.com; defaults to an empty string on GitHub Enterprise Server. On GHES, provide a GitHub.com personal access token if manifest requests are rate-limited. See [Using Microsoft distribution on GHES](docs/advanced-usage.md#using-microsoft-distribution-on-ghes) for more details.
|
||||
|
||||
- `cache`: Quick [setup caching](#caching-packages-dependencies) for the dependencies managed through one of the predefined package managers. It can be one of "maven", "gradle" or "sbt".
|
||||
|
||||
- `cache-dependency-path`: The path to a dependency file: pom.xml, build.gradle, build.sbt, etc. This option can be used with the `cache` option. If this option is omitted, the action searches for the dependency file in the entire repository. This option supports wildcards and a list of file names for caching multiple dependencies.
|
||||
|
||||
- `cache-path`: The dependency cache path to use instead of the default path for the package manager selected by `cache`. This option supports a list of paths and exclusion patterns. The build tool must be configured to use the same location.
|
||||
|
||||
- `cache-read-only`: Restore dependency caches without saving changes in the post action. Defaults to `false`. Use this for pull requests, merge queues, short-lived branches, and fan-out jobs that should consume caches populated by a default-branch or seed job.
|
||||
|
||||
#### Maven options
|
||||
The action has a bunch of inputs to generate maven's [settings.xml](https://maven.apache.org/settings.html) on the fly and pass the values to Apache Maven GPG Plugin as well as Apache Maven Toolchains. See [advanced usage](docs/advanced-usage.md) for more.
|
||||
|
||||
@@ -56,49 +83,68 @@ For more details, see the full release notes on the [releases page](https://git
|
||||
|
||||
- `server-id`: ID of the distributionManagement repository in the pom.xml file. Default is `github`.
|
||||
|
||||
- `server-username`: Environment variable name for the username for authentication to the Apache Maven repository. Default is GITHUB_ACTOR.
|
||||
- `server-username-env-var`: Environment variable name for the username for authentication to the Apache Maven repository. Default is GITHUB\_ACTOR.
|
||||
|
||||
- `server-password`: Environment variable name for password or token for authentication to the Apache Maven repository. Default is GITHUB_TOKEN.
|
||||
- `server-password-env-var`: Environment variable name for password or token for authentication to the Apache Maven repository. Default is GITHUB\_TOKEN.
|
||||
|
||||
- `settings-path`: Maven related setting to point to the directory where the settings.xml file will be written. Default is ~/.m2.
|
||||
- `settings-path`: Maven related setting to point to the directory where the settings.xml file will be written. Default is \~/.m2.
|
||||
|
||||
- `gpg-private-key`: GPG private key to import. Default is empty string.
|
||||
|
||||
- `gpg-passphrase`: Environment variable name for the GPG private key passphrase. Default is GPG_PASSPHRASE.
|
||||
- `gpg-passphrase-env-var`: Environment variable name for the GPG private key passphrase. Default is GPG\_PASSPHRASE.
|
||||
|
||||
- `mvn-toolchain-id`: Name of Maven Toolchain ID if the default name of `${distribution}_${java-version}` is not wanted.
|
||||
- `mvn-toolchain-id`: Name of Maven Toolchain ID if the default name of `${distribution}_${java-version}` is not wanted. When supplied, the number of IDs must match the number of Java versions.
|
||||
|
||||
- `mvn-toolchain-vendor`: Name of Maven Toolchain Vendor if the default name of `${distribution}` is not wanted.
|
||||
|
||||
- `show-download-progress`: Set to `true` to keep Maven artifact download and transfer progress in build logs. Default value: `false`. By default, the action adds `-ntp` (`--no-transfer-progress`) to `MAVEN_ARGS`. This input has no effect on non-Maven builds. See [Maven transfer progress](docs/advanced-usage.md#maven-transfer-progress-download-logs) for more details.
|
||||
|
||||
### Download integrity verification
|
||||
|
||||
When a selected distribution publishes an authoritative checksum for an archive, `setup-java` automatically verifies each downloaded JDK, JRE, or JMOD archive before extraction and caching. No input is required. Automatic checksum verification is currently available for `temurin`, `semeru`, `adopt`, `corretto`, `dragonwell`, `kona`, `sapmachine`, `graalvm`, `graalvm-community`, `zulu`, `oracle`, `oracle-openjdk`, `microsoft`, and `jetbrains`.
|
||||
|
||||
Distributions or individual releases without an authoritative checksum continue to install normally, with the omission reported only in debug logs. Archives resolved directly from the runner tool cache are not downloaded again and therefore are not reverified.
|
||||
|
||||
Checksums detect corrupted or unexpectedly modified downloads before they are persisted in the runner tool cache.
|
||||
|
||||
### Basic Configuration
|
||||
|
||||
#### Eclipse Temurin
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||
java-version: '25'
|
||||
- run: java --version
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||
java-version: '25'
|
||||
- run: java --version
|
||||
```
|
||||
|
||||
#### Azul Zulu OpenJDK
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'zulu' # See 'Supported distributions' for available options
|
||||
java-version: '25'
|
||||
- run: java --version
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'zulu' # See 'Supported distributions' for available options
|
||||
java-version: '25'
|
||||
- run: java --version
|
||||
```
|
||||
|
||||
#### Supported version syntax
|
||||
The `java-version` input supports an exact version or a version range using [SemVer](https://semver.org/) notation. The values below are examples, not an exhaustive list:
|
||||
- major versions, such as: `8`, `11`, `16`, `17`, `21`, `25`
|
||||
- more specific versions: `8.0.282+8`, `8.0.232`, `11.0`, `11.0.4`, `17.0`
|
||||
- multi-field Java versions (JEP 322), such as: `11.0.9.1`, `18.0.1.1`
|
||||
- early access (EA) versions: `15-ea`, `15.0.0-ea`
|
||||
- the `latest` alias, which floats to the newest available stable (GA) release
|
||||
|
||||
> [!NOTE]
|
||||
> - `latest` always resolves the newest version from the distribution's remote metadata (it behaves like `check-latest: true`), so it ignores any older version already present in the runner tool cache. This has the same performance trade-off described in [Check latest](#check-latest).
|
||||
> - `latest` is only supported through the `java-version` input, not through `java-version-file`, and it resolves stable (GA) releases only — it cannot be combined with `-ea`.
|
||||
> - The `jdkfile` distribution does not support `latest`, as it installs from a local file.
|
||||
> - For `oracle` and `graalvm` (Oracle GraalVM), `latest` uses the Adoptium API only to determine the newest GA **major version number** — the JDK binary itself is still downloaded from the Oracle / GraalVM servers for that major. Because these distributions have no endpoint to list their own releases, if their servers haven't published the resolved major yet, the action fails and asks you to specify a concrete version. Note the Oracle JDK license caveat below still applies to a floating `latest`.
|
||||
> - For `graalvm-community`, `latest` floats to the newest GA release published on GitHub, so it never depends on the Adoptium API and always resolves to the newest major that GraalVM Community actually ships.
|
||||
|
||||
#### Supported distributions
|
||||
Currently, the following distributions are supported:
|
||||
@@ -109,21 +155,25 @@ Currently, the following distributions are supported:
|
||||
| `adopt` or `adopt-hotspot` | [AdoptOpenJDK Hotspot](https://adoptopenjdk.net/) | [`adopt-hotspot` license](https://adoptopenjdk.net/about.html) |
|
||||
| `adopt-openj9` | [AdoptOpenJDK OpenJ9](https://adoptopenjdk.net/) | [`adopt-openj9` license](https://adoptopenjdk.net/about.html) |
|
||||
| `liberica` | [Liberica JDK](https://bell-sw.com/) | [`liberica` license](https://bell-sw.com/liberica_eula/) |
|
||||
| `liberica-nik` | [Liberica Native Image Kit](https://bell-sw.com/pages/downloads/native-image-kit/) | [`liberica-nik` license](https://bell-sw.com/liberica_nik_eula/) |
|
||||
| `microsoft` | [Microsoft Build of OpenJDK](https://www.microsoft.com/openjdk) | [`microsoft` license](https://docs.microsoft.com/java/openjdk/faq)
|
||||
| `corretto` | [Amazon Corretto Build of OpenJDK](https://aws.amazon.com/corretto/) | [`corretto` license](https://aws.amazon.com/corretto/faqs/)
|
||||
| `semeru` | [IBM Semeru Runtime Open Edition](https://developer.ibm.com/languages/java/semeru-runtimes/downloads/) | [`semeru` license](https://openjdk.java.net/legal/gplv2+ce.html) |
|
||||
| `oracle` | [Oracle JDK](https://www.oracle.com/java/technologies/downloads/) | [`oracle` license](https://java.com/freeuselicense)
|
||||
| `oracle-openjdk` | [Oracle OpenJDK](https://jdk.java.net/) | [`oracle-openjdk` license](https://openjdk.org/legal/gplv2+ce.html)
|
||||
| `dragonwell` | [Alibaba Dragonwell JDK](https://dragonwell-jdk.io/) | [`dragonwell` license](https://www.aliyun.com/product/dragonwell/)
|
||||
| `sapmachine` | [SAP SapMachine JDK/JRE](https://sapmachine.io/) | [`sapmachine` license](https://github.com/SAP/SapMachine/blob/sapmachine/LICENSE)
|
||||
| `graalvm` | [Oracle GraalVM](https://www.graalvm.org/) | [`graalvm` license](https://www.oracle.com/downloads/licenses/graal-free-license.html)
|
||||
| `graalvm-community` | [GraalVM Community](https://github.com/graalvm/graalvm-ce-builds/releases) | [`graalvm-community` license](https://github.com/oracle/graal/blob/master/LICENSE)
|
||||
| `jetbrains` | [JetBrains Runtime](https://github.com/JetBrains/JetBrainsRuntime/) | [`jetbrains` license](https://github.com/JetBrains/JetBrainsRuntime/blob/main/LICENSE)
|
||||
| `kona` | [Tencent Kona JDK](https://tencent.github.io/konajdk/) | [`kona` license](https://tencent.github.io/konajdk/LICENSE.txt)
|
||||
| `jdkfile` | Custom JDK Installation | |
|
||||
|
||||
> [!NOTE]
|
||||
> - The different distributors can provide discrepant list of available versions / supported configurations. Please refer to the official documentation to see the list of supported versions.
|
||||
> - AdoptOpenJDK got moved to Eclipse Temurin and won't be updated anymore. It is highly recommended to migrate workflows from `adopt` and `adopt-openj9`, to `temurin` and `semeru` respectively, to keep receiving software and security updates. See more details in the [Good-bye AdoptOpenJDK post](https://blog.adoptopenjdk.net/2021/08/goodbye-adoptopenjdk-hello-adoptium/).
|
||||
> - For Azul Zulu OpenJDK architectures x64 and arm64 are mapped to x86 / arm with proper hw_bitness.
|
||||
> - Oracle OpenJDK builds are created and hosted by Oracle. After a limited number of releases, Oracle archives these builds and no longer provides security updates. To continue receiving security patches, users must move to Oracle JDK or choose a different vendor.
|
||||
> - For Azul Zulu OpenJDK, architecture `arm64` is mapped to `aarch64` when querying the Azul Metadata API.
|
||||
> - To comply with the GraalVM Free Terms and Conditions (GFTC) license, it is recommended to use GraalVM JDK 17 version 17.0.12, as this is the only version of GraalVM JDK 17 available under the GFTC license. Additionally, it is encouraged to consider upgrading to GraalVM JDK 21, which offers the latest features and improvements.
|
||||
> - GraalVM Community is available as `distribution: 'graalvm-community'` for stable JDK 17 and later releases published on GitHub.
|
||||
|
||||
@@ -135,31 +185,113 @@ Currently, the following distributions are supported:
|
||||
The action has a built-in functionality for caching and restoring dependencies. It uses [toolkit/cache](https://github.com/actions/toolkit/tree/main/packages/cache) under hood for caching dependencies but requires less configuration settings. Supported package managers are gradle, maven and sbt. The format of the used cache key is `setup-java-${{ platform }}-${{ packageManager }}-${{ fileHash }}`, where the hash is based on the following files:
|
||||
|
||||
- gradle: `**/*.gradle*`, `**/gradle-wrapper.properties`, `buildSrc/**/Versions.kt`, `buildSrc/**/Dependencies.kt`, `gradle/*.versions.toml`, and `**/versions.properties`
|
||||
- maven: `**/pom.xml` and `**/.mvn/wrapper/maven-wrapper.properties`
|
||||
- maven: `**/pom.xml`, `**/.mvn/wrapper/maven-wrapper.properties`, and `**/.mvn/extensions.xml`
|
||||
- sbt: all sbt build definition files `**/*.sbt`, `**/project/build.properties`, `**/project/**.scala`, `**/project/**.sbt`
|
||||
|
||||
When the option `cache-dependency-path` is specified, the hash is based on the matching file. This option supports wildcards and a list of file names, and is especially useful for monorepos.
|
||||
|
||||
Use `cache-path` to replace the selected package manager's default dependency
|
||||
cache paths. Each non-empty line is passed to `actions/cache`, including
|
||||
supported exclusion patterns. `setup-java` does not configure the build tool,
|
||||
so the build must use the same paths:
|
||||
|
||||
```yaml
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'maven'
|
||||
cache-path: |
|
||||
/custom/maven/repository
|
||||
!/custom/maven/repository/**/*.lastUpdated
|
||||
- run: mvn -Dmaven.repo.local=/custom/maven/repository verify
|
||||
```
|
||||
|
||||
`cache-path` does not change the cache key. The key continues to use the runner
|
||||
OS, architecture, selected package manager, and dependency-file hash described
|
||||
above. Jobs intended to share a cache key must therefore use the same
|
||||
`cache-path` values so that they restore and save the same filesystem
|
||||
locations.
|
||||
|
||||
The Maven and Gradle wrapper caches remain at their documented default paths
|
||||
and are managed independently of `cache-path`. For advanced keying, fallback
|
||||
keys, or cache topologies that do not map to one package manager's dependency
|
||||
paths, use [`actions/cache`](https://github.com/actions/cache) directly.
|
||||
|
||||
The workflow output `cache-hit` is set to indicate if an exact match was found for the key [as actions/cache does](https://github.com/actions/cache/tree/main#outputs).
|
||||
|
||||
The workflow output `cache-primary-key` exposes the primary cache key computed by the action for the configured build tool. It is useful for composing with [`actions/cache`](https://github.com/actions/cache) or [`actions/cache/restore`](https://github.com/actions/cache/tree/main/restore) in later steps or dependent jobs that need to reuse the exact same key. It is empty when caching is not enabled or when caching is skipped (for example, when the cache service is unavailable).
|
||||
|
||||
The cache input is optional, and caching is turned off by default.
|
||||
|
||||
Set `cache-read-only: true` to restore the main dependency cache and any Maven
|
||||
or Gradle wrapper cache without archiving or uploading changes after the job.
|
||||
For example, a workflow can allow only the default branch to write caches while
|
||||
pull requests, merge queues, and short-lived branches remain read-only:
|
||||
|
||||
```yaml
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'maven'
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
||||
```
|
||||
|
||||
For a fan-out matrix, use one seed job to populate a complete cache and make
|
||||
every matrix job a read-only consumer. The seed and consumers must use the same
|
||||
runner OS and cache dependency inputs so they compute the same key:
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
seed-cache:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'maven'
|
||||
- run: mvn dependency:go-offline dependency:resolve-plugins
|
||||
|
||||
build:
|
||||
needs: seed-cache
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
goal: [test, verify, package]
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'maven'
|
||||
cache-read-only: true
|
||||
- run: mvn ${{ matrix.goal }}
|
||||
```
|
||||
|
||||
**Maven Wrapper:** when `cache: 'maven'` is enabled, the action also caches and restores the Maven Wrapper distribution downloaded to `~/.m2/wrapper/dists` (in addition to the local repository), so wrapper-based (`./mvnw`) builds don't re-download the Maven distribution. The wrapper distribution is stored in a **separate** cache entry keyed only on `**/.mvn/wrapper/maven-wrapper.properties`, so it stays cached across the frequent `pom.xml` changes that rotate the main dependency cache key.
|
||||
|
||||
#### Caching gradle dependencies
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'gradle'
|
||||
cache-dependency-path: | # optional
|
||||
sub-project/*.gradle*
|
||||
sub-project/**/gradle-wrapper.properties
|
||||
- run: ./gradlew build --no-daemon
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'gradle'
|
||||
cache-dependency-path: | # optional
|
||||
sub-project/*.gradle*
|
||||
sub-project/**/gradle-wrapper.properties
|
||||
- run: ./gradlew build --no-daemon
|
||||
```
|
||||
Using the `cache: gradle` provides a simple and effective way to cache Gradle dependencies with minimal configuration.
|
||||
|
||||
**Gradle Wrapper:** when `cache: 'gradle'` is enabled, the action also caches and restores the Gradle Wrapper distribution downloaded to `~/.gradle/wrapper` (in addition to the Gradle caches), so wrapper-based (`./gradlew`) builds don't re-download the Gradle distribution. The wrapper distribution is stored in a **separate** cache entry keyed only on `**/gradle-wrapper.properties`, so it stays cached across the frequent `*.gradle*` changes that rotate the main dependency cache key.
|
||||
|
||||
For projects that require more advanced `Gradle` caching features, such as caching build outputs, support for Gradle configuration cache, encrypted cache storage, fine-grained cache control (including options to enable or disable the cache, set it to read-only or write-only, perform automated cleanup, and define custom cache rules), or optimized performance for complex CI workflows, consider using [`gradle/actions/setup-gradle`](https://github.com/gradle/actions/tree/main/setup-gradle).
|
||||
|
||||
For setup details and a comprehensive overview of all available features, visit the [setup-gradle documentation](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md).
|
||||
@@ -167,31 +299,38 @@ For setup details and a comprehensive overview of all available features, visit
|
||||
#### Caching maven dependencies
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'maven'
|
||||
cache-dependency-path: 'sub-project/pom.xml' # optional
|
||||
- name: Build with Maven
|
||||
run: mvn -B package --file pom.xml
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'maven'
|
||||
cache-dependency-path: 'sub-project/pom.xml' # optional
|
||||
- name: Build with Maven
|
||||
run: mvn package --file pom.xml
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Maven resolves plugin dependencies lazily, so a cache created by a "thin" goal
|
||||
> (e.g. `mvn compile`) can be missing plugin dependencies that later
|
||||
> `test`/`verify`/`package` jobs then re-download on every run. See
|
||||
> [Ensuring the Maven cache is complete](docs/advanced-usage.md#ensuring-the-maven-cache-is-complete-plugin-dependencies)
|
||||
> for how to seed a complete cache.
|
||||
|
||||
#### Caching sbt dependencies
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'sbt'
|
||||
cache-dependency-path: | # optional
|
||||
sub-project/build.sbt
|
||||
sub-project/project/build.properties
|
||||
- name: Build with SBT
|
||||
run: sbt package
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'sbt'
|
||||
cache-dependency-path: | # optional
|
||||
sub-project/build.sbt
|
||||
sub-project/project/build.properties
|
||||
- name: Build with SBT
|
||||
run: sbt package
|
||||
```
|
||||
|
||||
#### Cache segment restore timeout
|
||||
@@ -201,13 +340,13 @@ Usually, cache gets downloaded in multiple segments of fixed sizes. Sometimes, a
|
||||
env:
|
||||
SEGMENT_DOWNLOAD_TIMEOUT_MINS: '5'
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'gradle'
|
||||
- run: ./gradlew build --no-daemon
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'gradle'
|
||||
- run: ./gradlew build --no-daemon
|
||||
```
|
||||
|
||||
### Check latest
|
||||
@@ -216,18 +355,20 @@ In the basic examples above, the `check-latest` flag defaults to `false`. When s
|
||||
|
||||
If `check-latest` is set to `true`, the action first checks if the cached version is the latest one. If the locally cached version is not the most up-to-date, the latest version of Java will be downloaded. Set `check-latest` to `true` if you want the most up-to-date version of Java to always be used. Setting `check-latest` to `true` has performance implications as downloading versions of Java is slower than using cached versions.
|
||||
|
||||
[GitHub-hosted runners](https://github.com/actions/runner-images) include Eclipse Temurin JDKs in their tool cache. Selecting Eclipse Temurin (`distribution: 'temurin'`) can save setup time by using a pre-installed JDK instead of downloading one. See the installed Java versions for [Ubuntu](https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md#java), [Windows](https://github.com/actions/runner-images/blob/main/images/windows/Windows2025-Readme.md#java), and [macOS](https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md#java).
|
||||
|
||||
For Java distributions that are not cached on Hosted images, `check-latest` always behaves as `true` and downloads Java on the fly. Check out [Hosted Tool Cache](docs/advanced-usage.md#Hosted-Tool-Cache) for more details about pre-cached Java versions.
|
||||
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
check-latest: true
|
||||
- run: java --version
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
check-latest: true
|
||||
- run: java --version
|
||||
```
|
||||
|
||||
### Testing against different Java versions
|
||||
@@ -240,9 +381,9 @@ jobs:
|
||||
java: [ '8', '11', '17', '21', '25' ]
|
||||
name: Java ${{ matrix.Java }} sample
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
- name: Setup java
|
||||
uses: actions/setup-java@v5
|
||||
uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: '<distribution>'
|
||||
java-version: ${{ matrix.java }}
|
||||
@@ -251,11 +392,11 @@ jobs:
|
||||
|
||||
### Install multiple JDKs
|
||||
|
||||
All configured Java versions are added to the PATH. The last one added to the PATH (i.e., the last JDK set up by this action) will be used as the default and available globally. Other Java versions can be accessed through environment variables such as 'JAVA_HOME_{{ MAJOR_VERSION }}_{{ ARCHITECTURE }}'. To use a specific Java version, set the JAVA_HOME environment variable accordingly and prepend its bin directory to the PATH to ensure it takes priority during execution.
|
||||
All configured Java versions are added to the PATH. The last one added to the PATH (i.e., the last JDK set up by this action) will be used as the default and available globally. Other Java versions can be accessed through environment variables such as 'JAVA\_HOME\_{{ MAJOR\_VERSION }}\_{{ ARCHITECTURE }}'. To use a specific Java version, set the JAVA\_HOME environment variable accordingly and prepend its bin directory to the PATH to ensure it takes priority during execution.
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/setup-java@v5
|
||||
steps:
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: '<distribution>'
|
||||
java-version: |
|
||||
@@ -270,37 +411,31 @@ In the example above multiple JDKs are installed for the same job. The result af
|
||||
### Advanced Configuration
|
||||
|
||||
- [Selecting a Java distribution](docs/advanced-usage.md#Selecting-a-Java-distribution)
|
||||
- [Eclipse Temurin](docs/advanced-usage.md#Eclipse-Temurin)
|
||||
- [Adopt](docs/advanced-usage.md#Adopt)
|
||||
- [Zulu](docs/advanced-usage.md#Zulu)
|
||||
- [Liberica](docs/advanced-usage.md#Liberica)
|
||||
- [Microsoft](docs/advanced-usage.md#Microsoft)
|
||||
- [Amazon Corretto](docs/advanced-usage.md#Amazon-Corretto)
|
||||
- [Oracle](docs/advanced-usage.md#Oracle)
|
||||
- [Alibaba Dragonwell](docs/advanced-usage.md#Alibaba-Dragonwell)
|
||||
- [SapMachine](docs/advanced-usage.md#SapMachine)
|
||||
- [GraalVM](docs/advanced-usage.md#GraalVM)
|
||||
- [JetBrains](docs/advanced-usage.md#JetBrains)
|
||||
- [Eclipse Temurin](docs/advanced-usage.md#Eclipse-Temurin)
|
||||
- [Adopt](docs/advanced-usage.md#Adopt)
|
||||
- [Zulu](docs/advanced-usage.md#Zulu)
|
||||
- [Liberica](docs/advanced-usage.md#Liberica)
|
||||
- [Liberica Native Image Kit](docs/advanced-usage.md#Liberica-Native-Image-Kit)
|
||||
- [Microsoft](docs/advanced-usage.md#Microsoft)
|
||||
- [Amazon Corretto](docs/advanced-usage.md#Amazon-Corretto)
|
||||
- [Oracle](docs/advanced-usage.md#Oracle)
|
||||
- [Alibaba Dragonwell](docs/advanced-usage.md#Alibaba-Dragonwell)
|
||||
- [SapMachine](docs/advanced-usage.md#SapMachine)
|
||||
- [GraalVM](docs/advanced-usage.md#GraalVM)
|
||||
- [JetBrains](docs/advanced-usage.md#JetBrains)
|
||||
- [Tencent Kona](docs/advanced-usage.md#Tencent-Kona)
|
||||
- [Installing custom Java package type](docs/advanced-usage.md#Installing-custom-Java-package-type)
|
||||
- [Installing custom Java architecture](docs/advanced-usage.md#Installing-custom-Java-architecture)
|
||||
- [Installing custom Java distribution from local file](docs/advanced-usage.md#Installing-Java-from-local-file)
|
||||
- [Testing against different Java distributions](docs/advanced-usage.md#Testing-against-different-Java-distributions)
|
||||
- [Testing against different platforms](docs/advanced-usage.md#Testing-against-different-platforms)
|
||||
- [Publishing using Apache Maven](docs/advanced-usage.md#Publishing-using-Apache-Maven)
|
||||
- [Maven transfer progress (download logs)](docs/advanced-usage.md#maven-transfer-progress-download-logs)
|
||||
- [Publishing using Gradle](docs/advanced-usage.md#Publishing-using-Gradle)
|
||||
- [Hosted Tool Cache](docs/advanced-usage.md#Hosted-Tool-Cache)
|
||||
- [Modifying Maven Toolchains](docs/advanced-usage.md#Modifying-Maven-Toolchains)
|
||||
- [Java Version File](docs/advanced-usage.md#Java-version-file)
|
||||
|
||||
## V2 vs V1
|
||||
|
||||
Examples in this README use `actions/setup-java@v5`, but the main migration note from V1 still applies to all later major versions (`v2`, `v3`, `v4`, and `v5`):
|
||||
|
||||
- Starting with V2, the action supports custom distributions. V1 supports only Azul Zulu OpenJDK.
|
||||
- Starting with V2, you must specify distribution along with the version. V1 defaults to Azul Zulu OpenJDK, so only version input is required. Follow [the migration guide](docs/switching-to-v2.md) to switch from V1 to V2.
|
||||
|
||||
For information about the latest releases, recent updates, and newly supported distributions, please refer to the `setup-java` [Releases](https://github.com/actions/setup-java/releases).
|
||||
|
||||
## Recommended permissions
|
||||
|
||||
When using the `setup-java` action in your GitHub Actions workflow, it is recommended to set the following permissions to ensure proper functionality:
|
||||
|
||||
+129
-8
@@ -1,24 +1,63 @@
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import {fileURLToPath} from 'url';
|
||||
import * as io from '@actions/io';
|
||||
import * as core from '@actions/core';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import os from 'os';
|
||||
|
||||
import * as auth from '../src/auth';
|
||||
import {M2_DIR, MVN_SETTINGS_FILE} from '../src/constants';
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const auth = await import('../src/auth.js');
|
||||
const {M2_DIR, MVN_SETTINGS_FILE} = await import('../src/constants.js');
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const m2Dir = path.join(__dirname, M2_DIR);
|
||||
const settingsFile = path.join(m2Dir, MVN_SETTINGS_FILE);
|
||||
|
||||
describe('auth tests', () => {
|
||||
let spyOSHomedir: jest.SpyInstance;
|
||||
let spyInfo: jest.SpyInstance;
|
||||
let spyOSHomedir: any;
|
||||
let spyInfo: any;
|
||||
|
||||
beforeEach(async () => {
|
||||
await io.rmRF(m2Dir);
|
||||
spyOSHomedir = jest.spyOn(os, 'homedir');
|
||||
spyOSHomedir.mockReturnValue(__dirname);
|
||||
spyInfo = jest.spyOn(core, 'info');
|
||||
spyInfo = core.info as jest.Mock;
|
||||
spyInfo.mockImplementation(() => null);
|
||||
}, 300000);
|
||||
|
||||
@@ -189,9 +228,40 @@ describe('auth tests', () => {
|
||||
<username>\${env.${username}}</username>
|
||||
<password>\${env.&<>"''"><&}</password>
|
||||
</server>
|
||||
</servers>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>setup-java-gpg</id>
|
||||
<properties>
|
||||
<gpg.passphraseEnvName>${gpgPassphrase}</gpg.passphraseEnvName>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
<activeProfiles>
|
||||
<activeProfile>setup-java-gpg</activeProfile>
|
||||
</activeProfiles>
|
||||
</settings>`;
|
||||
|
||||
expect(auth.generate(id, username, password, gpgPassphrase)).toEqual(
|
||||
expectedSettings
|
||||
);
|
||||
});
|
||||
|
||||
it('does not add a gpg profile when the passphrase env var is the maven-gpg-plugin default', () => {
|
||||
const id = 'packages';
|
||||
const username = 'USER';
|
||||
const password = '&<>"\'\'"><&';
|
||||
const gpgPassphrase = 'MAVEN_GPG_PASSPHRASE';
|
||||
|
||||
const expectedSettings = `<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
|
||||
<interactiveMode>false</interactiveMode>
|
||||
<servers>
|
||||
<server>
|
||||
<id>gpg.passphrase</id>
|
||||
<passphrase>\${env.${gpgPassphrase}}</passphrase>
|
||||
<id>${id}</id>
|
||||
<username>\${env.${username}}</username>
|
||||
<password>\${env.&<>"''"><&}</password>
|
||||
</server>
|
||||
</servers>
|
||||
</settings>`;
|
||||
@@ -200,4 +270,55 @@ describe('auth tests', () => {
|
||||
expectedSettings
|
||||
);
|
||||
});
|
||||
|
||||
it('uses deprecated input aliases and warns', () => {
|
||||
const mockGetInput = core.getInput as jest.MockedFunction<
|
||||
typeof core.getInput
|
||||
>;
|
||||
const mockWarning = core.warning as jest.MockedFunction<
|
||||
typeof core.warning
|
||||
>;
|
||||
mockGetInput.mockImplementation(name =>
|
||||
name === 'server-username' ? 'LEGACY_USERNAME' : ''
|
||||
);
|
||||
|
||||
expect(
|
||||
auth.getInputWithDeprecatedAlias(
|
||||
'server-username-env-var',
|
||||
'server-username',
|
||||
'GITHUB_ACTOR'
|
||||
)
|
||||
).toBe('LEGACY_USERNAME');
|
||||
expect(mockWarning).toHaveBeenCalledWith(
|
||||
"The 'server-username' input is deprecated and may be removed in a future release. Please use 'server-username-env-var' instead."
|
||||
);
|
||||
|
||||
mockGetInput.mockReset();
|
||||
mockWarning.mockReset();
|
||||
});
|
||||
|
||||
it('prefers the replacement input over its deprecated alias', () => {
|
||||
const mockGetInput = core.getInput as jest.MockedFunction<
|
||||
typeof core.getInput
|
||||
>;
|
||||
mockGetInput.mockImplementation(name => {
|
||||
const inputs: Record<string, string> = {
|
||||
'server-password-env-var': 'NEW_PASSWORD',
|
||||
'server-password': 'LEGACY_PASSWORD'
|
||||
};
|
||||
return inputs[name] || '';
|
||||
});
|
||||
|
||||
expect(
|
||||
auth.getInputWithDeprecatedAlias(
|
||||
'server-password-env-var',
|
||||
'server-password',
|
||||
'GITHUB_TOKEN'
|
||||
)
|
||||
).toBe('NEW_PASSWORD');
|
||||
expect(core.warning).toHaveBeenCalled();
|
||||
|
||||
mockGetInput.mockReset();
|
||||
(core.warning as jest.Mock).mockReset();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
command=${1:?command is required}
|
||||
tool=${2:?tool is required}
|
||||
|
||||
case "$tool" in
|
||||
maven)
|
||||
dependency_cache="$HOME/.m2/repository"
|
||||
wrapper_cache="$HOME/.m2/wrapper/dists"
|
||||
dependency_file="benchmark/pom.xml"
|
||||
wrapper_file="benchmark/.mvn/wrapper/maven-wrapper.properties"
|
||||
;;
|
||||
gradle)
|
||||
dependency_cache="$HOME/.gradle/caches"
|
||||
wrapper_cache="$HOME/.gradle/wrapper"
|
||||
dependency_file="benchmark/build.gradle"
|
||||
wrapper_file="benchmark/gradle/wrapper/gradle-wrapper.properties"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported tool: $tool" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$command" in
|
||||
prepare)
|
||||
profile=${3:?profile is required}
|
||||
mkdir -p "$(dirname "$dependency_file")" "$(dirname "$wrapper_file")"
|
||||
printf '// setup-java cache benchmark v1: %s\n' "$profile" > "$dependency_file"
|
||||
printf '# setup-java cache benchmark v1: %s\n' "$profile" > "$wrapper_file"
|
||||
;;
|
||||
reset)
|
||||
rm -rf "$dependency_cache" "$wrapper_cache"
|
||||
;;
|
||||
populate)
|
||||
profile=${3:?profile is required}
|
||||
case "$profile" in
|
||||
small)
|
||||
dependency_megabytes=8
|
||||
wrapper_megabytes=2
|
||||
;;
|
||||
large)
|
||||
dependency_megabytes=128
|
||||
wrapper_megabytes=32
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported profile: $profile" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
mkdir -p "$dependency_cache/setup-java-benchmark"
|
||||
mkdir -p "$wrapper_cache/setup-java-benchmark"
|
||||
dd if=/dev/urandom \
|
||||
of="$dependency_cache/setup-java-benchmark/payload" \
|
||||
bs=1048576 count="$dependency_megabytes" 2>/dev/null
|
||||
dd if=/dev/urandom \
|
||||
of="$wrapper_cache/setup-java-benchmark/payload" \
|
||||
bs=1048576 count="$wrapper_megabytes" 2>/dev/null
|
||||
;;
|
||||
start)
|
||||
node -e "require('fs').writeFileSync('.benchmark-start', String(Date.now()))"
|
||||
;;
|
||||
record)
|
||||
os=${3:?os is required}
|
||||
profile=${4:?profile is required}
|
||||
implementation=${5:?implementation is required}
|
||||
iteration=${6:?iteration is required}
|
||||
cache_hit=${7:?cache-hit output is required}
|
||||
if [ "$cache_hit" != "true" ]; then
|
||||
echo "Expected an exact dependency-cache hit for $implementation" >&2
|
||||
exit 1
|
||||
fi
|
||||
test -f "$dependency_cache/setup-java-benchmark/payload"
|
||||
started=$(cat .benchmark-start)
|
||||
finished=$(node -e "process.stdout.write(String(Date.now()))")
|
||||
elapsed=$((finished - started))
|
||||
mkdir -p .benchmark-results
|
||||
printf '%s,%s,%s,%s,%s,%s\n' \
|
||||
"$os" "$tool" "$profile" "$implementation" "$iteration" "$elapsed" \
|
||||
>> .benchmark-results/timings.csv
|
||||
;;
|
||||
summarize)
|
||||
summary_file=${3:?summary file is required}
|
||||
results_file=".benchmark-results/timings.csv"
|
||||
node --input-type=module - "$results_file" "$summary_file" <<'NODE'
|
||||
import fs from 'node:fs';
|
||||
|
||||
const [, , resultsFile, summaryFile] = process.argv;
|
||||
const rows = fs
|
||||
.readFileSync(resultsFile, 'utf8')
|
||||
.trim()
|
||||
.split('\n')
|
||||
.map(line => {
|
||||
const [os, tool, profile, implementation, iteration, elapsed] =
|
||||
line.split(',');
|
||||
return {os, tool, profile, implementation, iteration, elapsed: +elapsed};
|
||||
});
|
||||
const average = implementation => {
|
||||
const values = rows
|
||||
.filter(row => row.implementation === implementation)
|
||||
.map(row => row.elapsed);
|
||||
if (values.length === 0) {
|
||||
throw new Error(`No ${implementation} benchmark results were recorded`);
|
||||
}
|
||||
return Math.round(values.reduce((sum, value) => sum + value, 0) / values.length);
|
||||
};
|
||||
const baseline = average('baseline');
|
||||
const candidate = average('candidate');
|
||||
const change = (((candidate - baseline) / baseline) * 100).toFixed(1);
|
||||
const {os, tool, profile} = rows[0];
|
||||
const lines = [
|
||||
`### ${tool} ${profile} cache restore on ${os}`,
|
||||
'',
|
||||
'| Implementation | Iteration | Wall time (ms) |',
|
||||
'| --- | ---: | ---: |',
|
||||
...rows.map(
|
||||
row =>
|
||||
`| ${row.implementation} | ${row.iteration} | ${row.elapsed} |`
|
||||
),
|
||||
`| **baseline average** | | **${baseline}** |`,
|
||||
`| **candidate average** | | **${candidate}** |`,
|
||||
'',
|
||||
`Candidate change from baseline: **${change}%**`,
|
||||
''
|
||||
];
|
||||
fs.appendFileSync(summaryFile, `${lines.join('\n')}\n`);
|
||||
NODE
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported command: $command" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,80 @@
|
||||
import {jest, describe, it, expect, afterEach} from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('@actions/cache', () => ({
|
||||
isFeatureAvailable: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
info: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
const cache = await import('@actions/cache');
|
||||
const core = await import('@actions/core');
|
||||
const {isCacheFeatureAvailable} = await import('../src/cache-feature.js');
|
||||
|
||||
describe('isCacheFeatureAvailable', () => {
|
||||
it('is disabled on GHES when cache feature is unavailable', () => {
|
||||
(cache.isFeatureAvailable as jest.Mock<any>).mockImplementation(
|
||||
() => false
|
||||
);
|
||||
const warningMock = core.warning as jest.Mock;
|
||||
const message =
|
||||
'Caching is only supported on GHES version >= 3.5. If you are on a version >= 3.5, please check with your GHES admin if the Actions cache service is enabled or not.';
|
||||
|
||||
try {
|
||||
process.env['GITHUB_SERVER_URL'] = 'http://example.com';
|
||||
expect(isCacheFeatureAvailable()).toBe(false);
|
||||
expect(warningMock).toHaveBeenCalledWith(message);
|
||||
} finally {
|
||||
delete process.env['GITHUB_SERVER_URL'];
|
||||
}
|
||||
});
|
||||
|
||||
it('is disabled on dotcom when cache feature is unavailable', () => {
|
||||
(cache.isFeatureAvailable as jest.Mock<any>).mockImplementation(
|
||||
() => false
|
||||
);
|
||||
const warningMock = core.warning as jest.Mock;
|
||||
const message =
|
||||
'The runner was not able to contact the cache service. Caching will be skipped';
|
||||
|
||||
try {
|
||||
process.env['GITHUB_SERVER_URL'] = 'http://github.com';
|
||||
expect(isCacheFeatureAvailable()).toBe(false);
|
||||
expect(warningMock).toHaveBeenCalledWith(message);
|
||||
} finally {
|
||||
delete process.env['GITHUB_SERVER_URL'];
|
||||
}
|
||||
});
|
||||
|
||||
it('is enabled when cache feature is available', () => {
|
||||
(cache.isFeatureAvailable as jest.Mock<any>).mockImplementation(() => true);
|
||||
expect(isCacheFeatureAvailable()).toBe(true);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
});
|
||||
+593
-52
@@ -1,23 +1,84 @@
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import {mkdtempSync} from 'fs';
|
||||
import {tmpdir} from 'os';
|
||||
import {join} from 'path';
|
||||
import {restore, save} from '../src/cache';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as core from '@actions/core';
|
||||
import * as cache from '@actions/cache';
|
||||
import * as glob from '@actions/glob';
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('@actions/cache', () => ({
|
||||
restoreCache: jest.fn(),
|
||||
saveCache: jest.fn(),
|
||||
isFeatureAvailable: jest.fn(),
|
||||
ValidationError: class ValidationError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = 'ValidationError';
|
||||
}
|
||||
},
|
||||
ReserveCacheError: class ReserveCacheError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = 'ReserveCacheError';
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('@actions/glob', () => ({
|
||||
hashFiles: jest.fn(),
|
||||
create: jest.fn()
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const cache = await import('@actions/cache');
|
||||
const glob = await import('@actions/glob');
|
||||
const {restore, save} = await import('../src/cache.js');
|
||||
|
||||
describe('dependency cache', () => {
|
||||
const ORIGINAL_RUNNER_OS = process.env['RUNNER_OS'];
|
||||
const ORIGINAL_GITHUB_WORKSPACE = process.env['GITHUB_WORKSPACE'];
|
||||
const ORIGINAL_CWD = process.cwd();
|
||||
let workspace: string;
|
||||
let spyInfo: jest.SpyInstance<void, Parameters<typeof core.info>>;
|
||||
let spyWarning: jest.SpyInstance<void, Parameters<typeof core.warning>>;
|
||||
let spyDebug: jest.SpyInstance<void, Parameters<typeof core.debug>>;
|
||||
let spySaveState: jest.SpyInstance<void, Parameters<typeof core.saveState>>;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyInfo: any;
|
||||
let spyWarning: any;
|
||||
let spyDebug: any;
|
||||
let spySaveState: any;
|
||||
let spyCoreError: any;
|
||||
|
||||
beforeEach(() => {
|
||||
workspace = mkdtempSync(join(tmpdir(), 'setup-java-cache-'));
|
||||
@@ -41,20 +102,20 @@ describe('dependency cache', () => {
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
spyInfo = jest.spyOn(core, 'info');
|
||||
spyInfo = core.info as jest.Mock;
|
||||
spyInfo.mockImplementation(() => null);
|
||||
|
||||
spyWarning = jest.spyOn(core, 'warning');
|
||||
spyWarning = core.warning as jest.Mock;
|
||||
spyWarning.mockImplementation(() => null);
|
||||
|
||||
spyDebug = jest.spyOn(core, 'debug');
|
||||
spyDebug = core.debug as jest.Mock;
|
||||
spyDebug.mockImplementation(() => null);
|
||||
|
||||
spySaveState = jest.spyOn(core, 'saveState');
|
||||
spySaveState = core.saveState as jest.Mock;
|
||||
spySaveState.mockImplementation(() => null);
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -70,22 +131,18 @@ describe('dependency cache', () => {
|
||||
});
|
||||
|
||||
describe('restore', () => {
|
||||
let spyCacheRestore: jest.SpyInstance<
|
||||
ReturnType<typeof cache.restoreCache>,
|
||||
Parameters<typeof cache.restoreCache>
|
||||
>;
|
||||
let spyGlobHashFiles: jest.SpyInstance<
|
||||
ReturnType<typeof glob.hashFiles>,
|
||||
Parameters<typeof glob.hashFiles>
|
||||
>;
|
||||
let spyCacheRestore: any;
|
||||
let spyGlobHashFiles: any;
|
||||
let spySetOutput: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyCacheRestore = jest
|
||||
.spyOn(cache, 'restoreCache')
|
||||
.mockImplementation((paths: string[], primaryKey: string) =>
|
||||
Promise.resolve(undefined)
|
||||
);
|
||||
spyGlobHashFiles = jest.spyOn(glob, 'hashFiles');
|
||||
spyCacheRestore = (cache.restoreCache as any).mockImplementation(
|
||||
(paths: string[], primaryKey: string) => Promise.resolve(undefined)
|
||||
);
|
||||
spyGlobHashFiles = glob.hashFiles as jest.Mock;
|
||||
spyGlobHashFiles.mockResolvedValue('hash-stub');
|
||||
spySetOutput = core.setOutput as jest.Mock;
|
||||
spySetOutput.mockImplementation(() => null);
|
||||
spyWarning.mockImplementation(() => null);
|
||||
});
|
||||
|
||||
@@ -96,11 +153,12 @@ describe('dependency cache', () => {
|
||||
});
|
||||
|
||||
describe('for maven', () => {
|
||||
it('throws error if no pom.xml or maven-wrapper.properties found', async () => {
|
||||
it('throws error if no pom.xml, maven-wrapper.properties, or extensions.xml found', async () => {
|
||||
spyGlobHashFiles.mockResolvedValue('');
|
||||
await expect(restore('maven', '')).rejects.toThrow(
|
||||
`No file in ${projectRoot(
|
||||
workspace
|
||||
)} matched to [**/pom.xml,**/.mvn/wrapper/maven-wrapper.properties], make sure you have checked out the target repository`
|
||||
)} matched to [**/pom.xml,**/.mvn/wrapper/maven-wrapper.properties,**/.mvn/extensions.xml], make sure you have checked out the target repository`
|
||||
);
|
||||
});
|
||||
it('downloads cache based on pom.xml', async () => {
|
||||
@@ -108,18 +166,24 @@ describe('dependency cache', () => {
|
||||
|
||||
await restore('maven', '');
|
||||
expect(spyCacheRestore).toHaveBeenCalledWith(
|
||||
[
|
||||
join(os.homedir(), '.m2', 'repository'),
|
||||
join(os.homedir(), '.m2', 'wrapper', 'dists')
|
||||
],
|
||||
[join(os.homedir(), '.m2', 'repository')],
|
||||
expect.any(String)
|
||||
);
|
||||
expect(spyGlobHashFiles).toHaveBeenCalledWith(
|
||||
'**/pom.xml\n**/.mvn/wrapper/maven-wrapper.properties'
|
||||
'**/pom.xml\n**/.mvn/wrapper/maven-wrapper.properties\n**/.mvn/extensions.xml'
|
||||
);
|
||||
expect(spyWarning).not.toHaveBeenCalled();
|
||||
expect(spyInfo).toHaveBeenCalledWith('maven cache is not found');
|
||||
});
|
||||
it('sets the cache-primary-key output', async () => {
|
||||
createFile(join(workspace, 'pom.xml'));
|
||||
|
||||
await restore('maven', '');
|
||||
expect(spySetOutput).toHaveBeenCalledWith(
|
||||
'cache-primary-key',
|
||||
expect.stringContaining('setup-java-')
|
||||
);
|
||||
});
|
||||
it('downloads cache based on maven-wrapper.properties', async () => {
|
||||
createDirectory(join(workspace, '.mvn'));
|
||||
createDirectory(join(workspace, '.mvn', 'wrapper'));
|
||||
@@ -129,21 +193,152 @@ describe('dependency cache', () => {
|
||||
|
||||
await restore('maven', '');
|
||||
expect(spyCacheRestore).toHaveBeenCalledWith(
|
||||
[
|
||||
join(os.homedir(), '.m2', 'repository'),
|
||||
join(os.homedir(), '.m2', 'wrapper', 'dists')
|
||||
],
|
||||
[join(os.homedir(), '.m2', 'repository')],
|
||||
expect.any(String)
|
||||
);
|
||||
expect(spyGlobHashFiles).toHaveBeenCalledWith(
|
||||
'**/pom.xml\n**/.mvn/wrapper/maven-wrapper.properties'
|
||||
'**/pom.xml\n**/.mvn/wrapper/maven-wrapper.properties\n**/.mvn/extensions.xml'
|
||||
);
|
||||
expect(spyWarning).not.toHaveBeenCalled();
|
||||
expect(spyInfo).toHaveBeenCalledWith('maven cache is not found');
|
||||
});
|
||||
it('downloads cache based on extensions.xml', async () => {
|
||||
createDirectory(join(workspace, '.mvn'));
|
||||
createFile(join(workspace, '.mvn', 'extensions.xml'));
|
||||
|
||||
await restore('maven', '');
|
||||
expect(spyCacheRestore).toHaveBeenCalledWith(
|
||||
[join(os.homedir(), '.m2', 'repository')],
|
||||
expect.any(String)
|
||||
);
|
||||
expect(spyGlobHashFiles).toHaveBeenCalledWith(
|
||||
'**/pom.xml\n**/.mvn/wrapper/maven-wrapper.properties\n**/.mvn/extensions.xml'
|
||||
);
|
||||
expect(spyWarning).not.toHaveBeenCalled();
|
||||
expect(spyInfo).toHaveBeenCalledWith('maven cache is not found');
|
||||
});
|
||||
it('restores the maven wrapper distribution cache independently of the main cache', async () => {
|
||||
createDirectory(join(workspace, '.mvn'));
|
||||
createDirectory(join(workspace, '.mvn', 'wrapper'));
|
||||
createFile(
|
||||
join(workspace, '.mvn', 'wrapper', 'maven-wrapper.properties')
|
||||
);
|
||||
|
||||
await restore('maven', '', ['/custom/maven/repository']);
|
||||
// Main dependency cache no longer carries the wrapper dists path.
|
||||
expect(spyCacheRestore).toHaveBeenCalledWith(
|
||||
['/custom/maven/repository'],
|
||||
expect.any(String)
|
||||
);
|
||||
expect(spyCacheRestore).toHaveBeenCalledWith(
|
||||
[join(os.homedir(), '.m2', 'wrapper', 'dists')],
|
||||
expect.stringContaining('maven-wrapper')
|
||||
);
|
||||
expect(spyGlobHashFiles).toHaveBeenCalledWith(
|
||||
'**/.mvn/wrapper/maven-wrapper.properties'
|
||||
);
|
||||
expect(spyInfo).toHaveBeenCalledWith(
|
||||
'maven-wrapper cache is not found'
|
||||
);
|
||||
});
|
||||
it('starts maven dependency and wrapper restores before either completes', async () => {
|
||||
createDirectory(join(workspace, '.mvn'));
|
||||
createDirectory(join(workspace, '.mvn', 'wrapper'));
|
||||
createFile(
|
||||
join(workspace, '.mvn', 'wrapper', 'maven-wrapper.properties')
|
||||
);
|
||||
const dependencyRestore = deferred<string | undefined>();
|
||||
const wrapperRestore = deferred<string | undefined>();
|
||||
const bothRestoresStarted = deferred<void>();
|
||||
let restoreCount = 0;
|
||||
spyCacheRestore.mockImplementation((paths: string[]) => {
|
||||
restoreCount++;
|
||||
if (restoreCount === 2) {
|
||||
bothRestoresStarted.resolve();
|
||||
}
|
||||
return paths.includes(join(os.homedir(), '.m2', 'repository'))
|
||||
? dependencyRestore.promise
|
||||
: wrapperRestore.promise;
|
||||
});
|
||||
|
||||
const restorePromise = restore('maven', '');
|
||||
await bothRestoresStarted.promise;
|
||||
|
||||
expect(spyCacheRestore).toHaveBeenCalledTimes(2);
|
||||
expect(spySaveState).toHaveBeenCalledWith(
|
||||
'cache-primary-key',
|
||||
expect.any(String)
|
||||
);
|
||||
expect(spySaveState).toHaveBeenCalledWith(
|
||||
'cache-primary-key-maven-wrapper',
|
||||
expect.any(String)
|
||||
);
|
||||
|
||||
wrapperRestore.resolve('maven-wrapper-hit');
|
||||
dependencyRestore.resolve('maven-dependency-hit');
|
||||
await restorePromise;
|
||||
|
||||
expect(spySaveState).toHaveBeenCalledWith(
|
||||
'cache-matched-key-maven-wrapper',
|
||||
'maven-wrapper-hit'
|
||||
);
|
||||
expect(spySaveState).toHaveBeenCalledWith(
|
||||
'cache-matched-key',
|
||||
'maven-dependency-hit'
|
||||
);
|
||||
expect(spySetOutput).toHaveBeenCalledWith('cache-hit', false);
|
||||
});
|
||||
it('propagates a wrapper restore failure after starting both restores', async () => {
|
||||
createDirectory(join(workspace, '.mvn'));
|
||||
createDirectory(join(workspace, '.mvn', 'wrapper'));
|
||||
createFile(
|
||||
join(workspace, '.mvn', 'wrapper', 'maven-wrapper.properties')
|
||||
);
|
||||
const dependencyRestore = deferred<string | undefined>();
|
||||
const wrapperRestore = deferred<string | undefined>();
|
||||
const bothRestoresStarted = deferred<void>();
|
||||
let restoreCount = 0;
|
||||
spyCacheRestore.mockImplementation((paths: string[]) => {
|
||||
restoreCount++;
|
||||
if (restoreCount === 2) {
|
||||
bothRestoresStarted.resolve();
|
||||
}
|
||||
return paths.includes(join(os.homedir(), '.m2', 'repository'))
|
||||
? dependencyRestore.promise
|
||||
: wrapperRestore.promise;
|
||||
});
|
||||
|
||||
const restorePromise = restore('maven', '');
|
||||
await bothRestoresStarted.promise;
|
||||
wrapperRestore.reject(new Error('wrapper restore failed'));
|
||||
dependencyRestore.resolve(undefined);
|
||||
|
||||
await expect(restorePromise).rejects.toThrow('wrapper restore failed');
|
||||
});
|
||||
it('skips the maven wrapper cache when no wrapper properties exist', async () => {
|
||||
createFile(join(workspace, 'pom.xml'));
|
||||
spyGlobHashFiles.mockImplementation((pattern: string) =>
|
||||
Promise.resolve(
|
||||
pattern === '**/.mvn/wrapper/maven-wrapper.properties'
|
||||
? ''
|
||||
: 'hash-stub'
|
||||
)
|
||||
);
|
||||
|
||||
await restore('maven', '');
|
||||
// Only the main dependency cache is restored; the wrapper cache path is
|
||||
// never touched because the project does not use mvnw.
|
||||
expect(spyCacheRestore).toHaveBeenCalledTimes(1);
|
||||
expect(spyCacheRestore).toHaveBeenCalledWith(
|
||||
[join(os.homedir(), '.m2', 'repository')],
|
||||
expect.any(String)
|
||||
);
|
||||
expect(spyWarning).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
describe('for gradle', () => {
|
||||
it('throws error if no build.gradle found', async () => {
|
||||
spyGlobHashFiles.mockResolvedValue('');
|
||||
await expect(restore('gradle', '')).rejects.toThrow(
|
||||
`No file in ${projectRoot(
|
||||
workspace
|
||||
@@ -196,9 +391,91 @@ describe('dependency cache', () => {
|
||||
expect(spyWarning).not.toHaveBeenCalled();
|
||||
expect(spyInfo).toHaveBeenCalledWith('gradle cache is not found');
|
||||
});
|
||||
it('restores the gradle wrapper distribution cache independently of the main cache', async () => {
|
||||
createFile(join(workspace, 'build.gradle'));
|
||||
|
||||
await restore('gradle', '', ['/custom/gradle/caches']);
|
||||
// Main dependency cache no longer carries the wrapper path.
|
||||
expect(spyCacheRestore).toHaveBeenCalledWith(
|
||||
['/custom/gradle/caches'],
|
||||
expect.any(String)
|
||||
);
|
||||
// Wrapper distribution is restored on its own, keyed only on the
|
||||
// wrapper properties file.
|
||||
expect(spyCacheRestore).toHaveBeenCalledWith(
|
||||
[join(os.homedir(), '.gradle', 'wrapper')],
|
||||
expect.stringContaining('setup-java-')
|
||||
);
|
||||
expect(spyGlobHashFiles).toHaveBeenCalledWith(
|
||||
'**/gradle-wrapper.properties'
|
||||
);
|
||||
});
|
||||
it('starts gradle dependency and wrapper restores before either completes', async () => {
|
||||
createFile(join(workspace, 'build.gradle'));
|
||||
createFile(join(workspace, 'gradle-wrapper.properties'));
|
||||
const dependencyRestore = deferred<string | undefined>();
|
||||
const wrapperRestore = deferred<string | undefined>();
|
||||
const bothRestoresStarted = deferred<void>();
|
||||
let restoreCount = 0;
|
||||
spyCacheRestore.mockImplementation((paths: string[]) => {
|
||||
restoreCount++;
|
||||
if (restoreCount === 2) {
|
||||
bothRestoresStarted.resolve();
|
||||
}
|
||||
return paths.includes(join(os.homedir(), '.gradle', 'caches'))
|
||||
? dependencyRestore.promise
|
||||
: wrapperRestore.promise;
|
||||
});
|
||||
|
||||
const restorePromise = restore('gradle', '');
|
||||
await bothRestoresStarted.promise;
|
||||
|
||||
expect(spyCacheRestore).toHaveBeenCalledTimes(2);
|
||||
expect(spySaveState).toHaveBeenCalledWith(
|
||||
'cache-primary-key',
|
||||
expect.any(String)
|
||||
);
|
||||
expect(spySaveState).toHaveBeenCalledWith(
|
||||
'cache-primary-key-gradle-wrapper',
|
||||
expect.any(String)
|
||||
);
|
||||
|
||||
dependencyRestore.resolve('gradle-dependency-hit');
|
||||
wrapperRestore.resolve('gradle-wrapper-hit');
|
||||
await restorePromise;
|
||||
|
||||
expect(spySaveState).toHaveBeenCalledWith(
|
||||
'cache-matched-key',
|
||||
'gradle-dependency-hit'
|
||||
);
|
||||
expect(spySaveState).toHaveBeenCalledWith(
|
||||
'cache-matched-key-gradle-wrapper',
|
||||
'gradle-wrapper-hit'
|
||||
);
|
||||
expect(spySetOutput).toHaveBeenCalledWith('cache-hit', false);
|
||||
});
|
||||
it('skips the gradle wrapper cache when no wrapper properties exist', async () => {
|
||||
createFile(join(workspace, 'build.gradle'));
|
||||
spyGlobHashFiles.mockImplementation((pattern: string) =>
|
||||
Promise.resolve(
|
||||
pattern === '**/gradle-wrapper.properties' ? '' : 'hash-stub'
|
||||
)
|
||||
);
|
||||
|
||||
await restore('gradle', '');
|
||||
// Only the main dependency cache is restored; the wrapper cache path is
|
||||
// never touched because the project does not use the gradle wrapper.
|
||||
expect(spyCacheRestore).toHaveBeenCalledTimes(1);
|
||||
expect(spyCacheRestore).toHaveBeenCalledWith(
|
||||
[join(os.homedir(), '.gradle', 'caches')],
|
||||
expect.any(String)
|
||||
);
|
||||
expect(spyWarning).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
describe('for sbt', () => {
|
||||
it('throws error if no build.sbt found', async () => {
|
||||
spyGlobHashFiles.mockResolvedValue('');
|
||||
await expect(restore('sbt', '')).rejects.toThrow(
|
||||
`No file in ${projectRoot(
|
||||
workspace
|
||||
@@ -217,6 +494,13 @@ describe('dependency cache', () => {
|
||||
expect(spyInfo).toHaveBeenCalledWith('sbt cache is not found');
|
||||
});
|
||||
it('detects scala and sbt changes under **/project/ folder', async () => {
|
||||
let callCount = 0;
|
||||
spyGlobHashFiles.mockImplementation(async () => {
|
||||
callCount++;
|
||||
// Return same hash for first two calls, different for third
|
||||
return callCount <= 2 ? 'hash-v1' : 'hash-v2';
|
||||
});
|
||||
|
||||
createFile(join(workspace, 'build.sbt'));
|
||||
createDirectory(join(workspace, 'project'));
|
||||
createFile(join(workspace, 'project/DependenciesV1.scala'));
|
||||
@@ -252,6 +536,7 @@ describe('dependency cache', () => {
|
||||
});
|
||||
describe('cache-dependency-path', () => {
|
||||
it('throws error if no matching dependency file found', async () => {
|
||||
spyGlobHashFiles.mockResolvedValue('');
|
||||
createFile(join(workspace, 'build.gradle.kts'));
|
||||
await expect(
|
||||
restore('gradle', 'sub-project/**/build.gradle.kts')
|
||||
@@ -291,19 +576,47 @@ describe('dependency cache', () => {
|
||||
expect(spyInfo).toHaveBeenCalledWith('gradle cache is not found');
|
||||
});
|
||||
});
|
||||
describe('cache-path', () => {
|
||||
it.each([
|
||||
['maven', ['/custom/maven/repository']],
|
||||
['gradle', ['/custom/gradle/caches']],
|
||||
[
|
||||
'sbt',
|
||||
[
|
||||
'/custom/ivy/cache',
|
||||
'/custom/coursier/cache',
|
||||
'!/custom/ivy/cache/*.lock'
|
||||
]
|
||||
]
|
||||
])(
|
||||
'restores and persists custom paths for %s',
|
||||
async (packageManager, cachePaths) => {
|
||||
await restore(packageManager, '', cachePaths);
|
||||
|
||||
expect(spyCacheRestore).toHaveBeenCalledWith(
|
||||
cachePaths,
|
||||
expect.any(String)
|
||||
);
|
||||
expect(spySaveState).toHaveBeenCalledWith(
|
||||
'cache-paths',
|
||||
JSON.stringify(cachePaths)
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('save', () => {
|
||||
let spyCacheSave: jest.SpyInstance<
|
||||
ReturnType<typeof cache.saveCache>,
|
||||
Parameters<typeof cache.saveCache>
|
||||
>;
|
||||
let spyCacheSave: any;
|
||||
let spyGlobCreate: jest.Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
spyCacheSave = jest
|
||||
.spyOn(cache, 'saveCache')
|
||||
.mockImplementation((paths: string[], key: string) =>
|
||||
Promise.resolve(0)
|
||||
);
|
||||
spyCacheSave = (cache.saveCache as any).mockImplementation(
|
||||
(paths: string[], key: string) => Promise.resolve(0)
|
||||
);
|
||||
spyGlobCreate = glob.create as jest.Mock;
|
||||
spyGlobCreate.mockResolvedValue({
|
||||
glob: jest.fn(() => Promise.resolve(['wrapper-path']))
|
||||
});
|
||||
spyWarning.mockImplementation(() => null);
|
||||
});
|
||||
|
||||
@@ -340,6 +653,42 @@ describe('dependency cache', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
['maven', ['/custom/maven/repository']],
|
||||
['gradle', ['/custom/gradle/caches']],
|
||||
[
|
||||
'sbt',
|
||||
[
|
||||
'/custom/ivy/cache',
|
||||
'/custom/coursier/cache',
|
||||
'!/custom/ivy/cache/*.lock'
|
||||
]
|
||||
]
|
||||
])(
|
||||
'saves the persisted custom paths for %s',
|
||||
async (packageManager, cachePaths) => {
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: any) => {
|
||||
switch (name) {
|
||||
case 'cache-primary-key':
|
||||
return 'setup-java-cache-primary-key';
|
||||
case 'cache-matched-key':
|
||||
return 'setup-java-cache-matched-key';
|
||||
case 'cache-paths':
|
||||
return JSON.stringify(cachePaths);
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
await save(packageManager);
|
||||
|
||||
expect(spyCacheSave).toHaveBeenCalledWith(
|
||||
cachePaths,
|
||||
'setup-java-cache-primary-key'
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
describe('for maven', () => {
|
||||
it('uploads cache even if no pom.xml found', async () => {
|
||||
createStateForMissingBuildFile();
|
||||
@@ -367,6 +716,114 @@ describe('dependency cache', () => {
|
||||
expect.stringMatching(/^Cache saved with the key:.*/)
|
||||
);
|
||||
});
|
||||
it('saves the maven wrapper distribution cache under its own key', async () => {
|
||||
createFile(join(workspace, 'pom.xml'));
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: any) => {
|
||||
switch (name) {
|
||||
case 'cache-primary-key':
|
||||
return 'setup-java-cache-primary-key';
|
||||
case 'cache-matched-key':
|
||||
return 'setup-java-cache-matched-key';
|
||||
case 'cache-primary-key-maven-wrapper':
|
||||
return 'setup-java-maven-wrapper-key';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
await save('maven');
|
||||
expect(spyCacheSave).toHaveBeenCalledWith(
|
||||
['wrapper-path'],
|
||||
'setup-java-maven-wrapper-key'
|
||||
);
|
||||
expect(spyWarning).not.toHaveBeenCalled();
|
||||
});
|
||||
it('does not save the maven wrapper cache on an exact wrapper hit', async () => {
|
||||
createFile(join(workspace, 'pom.xml'));
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: any) => {
|
||||
switch (name) {
|
||||
case 'cache-primary-key':
|
||||
return 'setup-java-cache-primary-key';
|
||||
case 'cache-matched-key':
|
||||
return 'setup-java-cache-matched-key';
|
||||
case 'cache-primary-key-maven-wrapper':
|
||||
case 'cache-matched-key-maven-wrapper':
|
||||
return 'setup-java-maven-wrapper-key';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
await save('maven');
|
||||
expect(spyCacheSave).not.toHaveBeenCalledWith(
|
||||
[join(os.homedir(), '.m2', 'wrapper', 'dists')],
|
||||
expect.any(String)
|
||||
);
|
||||
});
|
||||
it('does not fail the post step when the wrapper distribution path is missing', async () => {
|
||||
createFile(join(workspace, 'pom.xml'));
|
||||
createDirectory(join(workspace, '.mvn'));
|
||||
createDirectory(join(workspace, '.mvn', 'wrapper'));
|
||||
createFile(
|
||||
join(workspace, '.mvn', 'wrapper', 'maven-wrapper.properties')
|
||||
);
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: any) => {
|
||||
switch (name) {
|
||||
case 'cache-primary-key':
|
||||
return 'setup-java-cache-primary-key';
|
||||
case 'cache-matched-key':
|
||||
return 'setup-java-cache-matched-key';
|
||||
case 'cache-primary-key-maven-wrapper':
|
||||
return 'setup-java-maven-wrapper-key';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
spyGlobCreate.mockResolvedValue({
|
||||
glob: jest.fn(() => Promise.resolve([]))
|
||||
});
|
||||
|
||||
await expect(save('maven')).resolves.toBeUndefined();
|
||||
expect(spyCacheSave).not.toHaveBeenCalledWith(
|
||||
[join(os.homedir(), '.m2', 'wrapper', 'dists')],
|
||||
expect.any(String)
|
||||
);
|
||||
expect(spyCacheSave).toHaveBeenCalledWith(
|
||||
[join(os.homedir(), '.m2', 'repository')],
|
||||
'setup-java-cache-primary-key'
|
||||
);
|
||||
expect(spyWarning).not.toHaveBeenCalled();
|
||||
});
|
||||
it('continues with primary cache save when additional cache save fails unexpectedly', async () => {
|
||||
createFile(join(workspace, 'pom.xml'));
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: any) => {
|
||||
switch (name) {
|
||||
case 'cache-primary-key':
|
||||
return 'setup-java-cache-primary-key';
|
||||
case 'cache-matched-key':
|
||||
return 'setup-java-cache-matched-key';
|
||||
case 'cache-primary-key-maven-wrapper':
|
||||
return 'setup-java-maven-wrapper-key';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
spyCacheSave.mockImplementation((paths: string[], key: string) => {
|
||||
if (paths[0] === 'wrapper-path') {
|
||||
return Promise.reject(new Error('wrapper save exploded'));
|
||||
}
|
||||
return Promise.resolve(0);
|
||||
});
|
||||
|
||||
await expect(save('maven')).resolves.toBeUndefined();
|
||||
expect(spyWarning).toHaveBeenCalledWith(
|
||||
'Failed to save maven-wrapper cache: wrapper save exploded. Continuing with primary cache save.'
|
||||
);
|
||||
expect(spyCacheSave).toHaveBeenCalledWith(
|
||||
[join(os.homedir(), '.m2', 'repository')],
|
||||
'setup-java-cache-primary-key'
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('for gradle', () => {
|
||||
it('uploads cache even if no build.gradle found', async () => {
|
||||
@@ -419,6 +876,80 @@ describe('dependency cache', () => {
|
||||
expect.stringMatching(/^Cache saved with the key:.*/)
|
||||
);
|
||||
});
|
||||
it('saves the gradle wrapper distribution cache under its own key', async () => {
|
||||
createFile(join(workspace, 'build.gradle'));
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: any) => {
|
||||
switch (name) {
|
||||
case 'cache-primary-key':
|
||||
return 'setup-java-cache-primary-key';
|
||||
case 'cache-matched-key':
|
||||
return 'setup-java-cache-matched-key';
|
||||
case 'cache-primary-key-gradle-wrapper':
|
||||
return 'setup-java-gradle-wrapper-key';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
await save('gradle');
|
||||
expect(spyCacheSave).toHaveBeenCalledWith(
|
||||
['wrapper-path'],
|
||||
'setup-java-gradle-wrapper-key'
|
||||
);
|
||||
expect(spyWarning).not.toHaveBeenCalled();
|
||||
});
|
||||
it('does not save the gradle wrapper cache on an exact wrapper hit', async () => {
|
||||
createFile(join(workspace, 'build.gradle'));
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: any) => {
|
||||
switch (name) {
|
||||
case 'cache-primary-key':
|
||||
return 'setup-java-cache-primary-key';
|
||||
case 'cache-matched-key':
|
||||
return 'setup-java-cache-matched-key';
|
||||
case 'cache-primary-key-gradle-wrapper':
|
||||
case 'cache-matched-key-gradle-wrapper':
|
||||
return 'setup-java-gradle-wrapper-key';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
await save('gradle');
|
||||
expect(spyCacheSave).not.toHaveBeenCalledWith(
|
||||
[join(os.homedir(), '.gradle', 'wrapper')],
|
||||
expect.any(String)
|
||||
);
|
||||
});
|
||||
it('does not fail the post step when the wrapper distribution path is missing', async () => {
|
||||
createFile(join(workspace, 'build.gradle'));
|
||||
createFile(join(workspace, 'gradle-wrapper.properties'));
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: any) => {
|
||||
switch (name) {
|
||||
case 'cache-primary-key':
|
||||
return 'setup-java-cache-primary-key';
|
||||
case 'cache-matched-key':
|
||||
return 'setup-java-cache-matched-key';
|
||||
case 'cache-primary-key-gradle-wrapper':
|
||||
return 'setup-java-gradle-wrapper-key';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
spyGlobCreate.mockResolvedValue({
|
||||
glob: jest.fn(() => Promise.resolve([]))
|
||||
});
|
||||
|
||||
await expect(save('gradle')).resolves.toBeUndefined();
|
||||
expect(spyCacheSave).not.toHaveBeenCalledWith(
|
||||
[join(os.homedir(), '.gradle', 'wrapper')],
|
||||
expect.any(String)
|
||||
);
|
||||
expect(spyCacheSave).toHaveBeenCalledWith(
|
||||
[join(os.homedir(), '.gradle', 'caches')],
|
||||
'setup-java-cache-primary-key'
|
||||
);
|
||||
expect(spyWarning).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
describe('for sbt', () => {
|
||||
it('uploads cache even if no build.sbt found', async () => {
|
||||
@@ -463,14 +994,14 @@ describe('dependency cache', () => {
|
||||
});
|
||||
|
||||
function resetState() {
|
||||
jest.spyOn(core, 'getState').mockReset();
|
||||
(core.getState as jest.Mock).mockReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create states to emulate a restore process without build file.
|
||||
*/
|
||||
function createStateForMissingBuildFile() {
|
||||
jest.spyOn(core, 'getState').mockImplementation(name => {
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: any) => {
|
||||
switch (name) {
|
||||
case 'cache-primary-key':
|
||||
return 'setup-java-cache-';
|
||||
@@ -484,7 +1015,7 @@ function createStateForMissingBuildFile() {
|
||||
* Create states to emulate a successful restore process.
|
||||
*/
|
||||
function createStateForSuccessfulRestore() {
|
||||
jest.spyOn(core, 'getState').mockImplementation(name => {
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: any) => {
|
||||
switch (name) {
|
||||
case 'cache-primary-key':
|
||||
return 'setup-java-cache-primary-key';
|
||||
@@ -501,6 +1032,16 @@ function createFile(path: string) {
|
||||
fs.writeFileSync(path, '');
|
||||
}
|
||||
|
||||
function deferred<T>() {
|
||||
let resolve!: (value: T | PromiseLike<T>) => void;
|
||||
let reject!: (reason?: unknown) => void;
|
||||
const promise = new Promise<T>((promiseResolve, promiseReject) => {
|
||||
resolve = promiseResolve;
|
||||
reject = promiseReject;
|
||||
});
|
||||
return {promise, resolve, reject};
|
||||
}
|
||||
|
||||
function createDirectory(path: string) {
|
||||
core.info(`created a directory at ${path}`);
|
||||
fs.mkdirSync(path);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
|
||||
@@ -0,0 +1 @@
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip
|
||||
@@ -0,0 +1,11 @@
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.mvn/timing.properties
|
||||
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
|
||||
.mvn/wrapper/maven-wrapper.jar
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
<?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>io.github.actions</groupId>
|
||||
<artifactId>setup-java-maven2-example</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.12.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1 @@
|
||||
target/
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
ThisBuild / scalaVersion := "2.12.15"
|
||||
|
||||
libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "2.1.1"
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#!/bin/sh
|
||||
# Assert whether a directory exists, for use in the e2e cache workflows.
|
||||
#
|
||||
# Usage: check-dir.sh <dir> [present|absent]
|
||||
#
|
||||
# present (default): fail if <dir> does NOT exist, otherwise list its contents.
|
||||
# absent: fail if <dir> DOES exist.
|
||||
#
|
||||
# Call with already-expanded paths (e.g. "$HOME/.gradle/caches") to avoid
|
||||
# tilde-expansion pitfalls.
|
||||
set -eu
|
||||
|
||||
if [ "$#" -lt 1 ]; then
|
||||
echo "Usage: check-dir.sh <dir> [present|absent]" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dir=$1
|
||||
mode=${2:-present}
|
||||
|
||||
case "$mode" in
|
||||
present)
|
||||
if [ ! -d "$dir" ]; then
|
||||
echo "::error::The $dir directory does not exist unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
ls "$dir"
|
||||
;;
|
||||
absent)
|
||||
if [ -d "$dir" ]; then
|
||||
echo "::error::The $dir directory exists unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "::error::Unknown mode '$mode' (expected 'present' or 'absent')"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,130 @@
|
||||
import {afterEach, describe, expect, it, jest} from '@jest/globals';
|
||||
import {createHash} from 'crypto';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
import {calculateChecksum, verifyChecksum} from '../src/checksum.js';
|
||||
import type {ChecksumMetadata} from '../src/distributions/base-models.js';
|
||||
|
||||
const temporaryPaths: string[] = [];
|
||||
|
||||
async function temporaryFile(contents: string): Promise<string> {
|
||||
const directory = await fs.promises.mkdtemp(
|
||||
path.join(os.tmpdir(), 'setup-java-checksum-')
|
||||
);
|
||||
const file = path.join(directory, 'archive');
|
||||
await fs.promises.writeFile(file, contents);
|
||||
temporaryPaths.push(directory);
|
||||
return file;
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(
|
||||
temporaryPaths
|
||||
.splice(0)
|
||||
.map(item => fs.promises.rm(item, {recursive: true, force: true}))
|
||||
);
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('verifyChecksum', () => {
|
||||
it.each(['sha256', 'sha512'] as const)(
|
||||
'verifies a matching %s digest',
|
||||
async algorithm => {
|
||||
const contents = `jdk archive for ${algorithm}`;
|
||||
const file = await temporaryFile(contents);
|
||||
const value = createHash(algorithm).update(contents).digest('hex');
|
||||
|
||||
await expect(
|
||||
verifyChecksum(
|
||||
file,
|
||||
{algorithm, value: value.toUpperCase()},
|
||||
{distribution: 'Test', version: '21.0.1'}
|
||||
)
|
||||
).resolves.toBeUndefined();
|
||||
}
|
||||
);
|
||||
|
||||
it('reports mismatch context and both digests', async () => {
|
||||
const file = await temporaryFile('corrupt archive');
|
||||
const expected = 'a'.repeat(64);
|
||||
const actual = await calculateChecksum(file, 'sha256');
|
||||
|
||||
await expect(
|
||||
verifyChecksum(
|
||||
file,
|
||||
{algorithm: 'sha256', value: expected},
|
||||
{distribution: 'Corretto', version: '21.0.8'}
|
||||
)
|
||||
).rejects.toThrow(
|
||||
`Checksum verification failed for Corretto version 21.0.8: sha256 expected ${expected}, actual ${actual}.`
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects malformed digest metadata before reading the file', async () => {
|
||||
await expect(
|
||||
verifyChecksum(
|
||||
'/missing/archive',
|
||||
{algorithm: 'sha512', value: 'not-a-digest'},
|
||||
{distribution: 'Test', version: '17'}
|
||||
)
|
||||
).rejects.toThrow(
|
||||
'Malformed sha512 checksum metadata: expected a 128-character hexadecimal digest.'
|
||||
);
|
||||
});
|
||||
|
||||
it.each([undefined, null, 123])(
|
||||
'reports a malformed digest when the value is %p',
|
||||
async value => {
|
||||
const checksum = {
|
||||
algorithm: 'sha256',
|
||||
value
|
||||
} as unknown as ChecksumMetadata;
|
||||
|
||||
await expect(
|
||||
verifyChecksum('/missing/archive', checksum, {
|
||||
distribution: 'Test',
|
||||
version: '17'
|
||||
})
|
||||
).rejects.toThrow(
|
||||
'Malformed sha256 checksum metadata: expected a 64-character hexadecimal digest.'
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
it('rejects unsupported algorithms without leaking source query parameters', async () => {
|
||||
const checksum = {
|
||||
algorithm: 'md5',
|
||||
value: 'a'.repeat(32),
|
||||
source: 'https://vendor.example/checksum.txt?token=secret-value#private'
|
||||
} as unknown as ChecksumMetadata;
|
||||
|
||||
let message = '';
|
||||
try {
|
||||
await verifyChecksum('/missing/archive', checksum, {
|
||||
distribution: 'Test',
|
||||
version: '17'
|
||||
});
|
||||
} catch (error) {
|
||||
message = (error as Error).message;
|
||||
}
|
||||
|
||||
expect(message).toContain(
|
||||
"Unsupported checksum algorithm 'md5' from https://vendor.example/checksum.txt"
|
||||
);
|
||||
expect(message).not.toContain('secret-value');
|
||||
expect(message).not.toContain('token=');
|
||||
expect(message).not.toContain('#private');
|
||||
});
|
||||
|
||||
it('surfaces file read errors', async () => {
|
||||
await expect(
|
||||
verifyChecksum(
|
||||
'/missing/archive',
|
||||
{algorithm: 'sha256', value: 'a'.repeat(64)},
|
||||
{distribution: 'Test', version: '17'}
|
||||
)
|
||||
).rejects.toMatchObject({code: 'ENOENT'});
|
||||
});
|
||||
});
|
||||
+134
-21
@@ -1,32 +1,87 @@
|
||||
import {run as cleanup} from '../src/cleanup-java';
|
||||
import * as core from '@actions/core';
|
||||
import * as cache from '@actions/cache';
|
||||
import * as util from '../src/util';
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
|
||||
// Mock @actions/cache before importing source modules
|
||||
const real_cache_module = await import('@actions/cache');
|
||||
jest.unstable_mockModule('@actions/cache', () => ({
|
||||
...real_cache_module,
|
||||
saveCache: jest.fn(),
|
||||
restoreCache: jest.fn()
|
||||
}));
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
const real_util_module = await import('../src/util.js');
|
||||
jest.unstable_mockModule('../src/util.js', () => ({
|
||||
...real_util_module,
|
||||
extractJdkFile: jest.fn(),
|
||||
getDownloadArchiveExtension: jest.fn(),
|
||||
getToolcachePath: jest.fn(),
|
||||
isJobStatusSuccess: jest.fn(),
|
||||
renameWinArchive: jest.fn(),
|
||||
isVersionSatisfies: real_util_module.isVersionSatisfies,
|
||||
getTempDir: real_util_module.getTempDir
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const cache = await import('@actions/cache');
|
||||
const {run: cleanup} = await import('../src/cleanup-java.js');
|
||||
const util = await import('../src/util.js');
|
||||
|
||||
describe('cleanup', () => {
|
||||
let spyWarning: jest.SpyInstance<void, Parameters<typeof core.warning>>;
|
||||
let spyInfo: jest.SpyInstance<void, Parameters<typeof core.info>>;
|
||||
let spyCacheSave: jest.SpyInstance<
|
||||
ReturnType<typeof cache.saveCache>,
|
||||
Parameters<typeof cache.saveCache>
|
||||
>;
|
||||
let spyJobStatusSuccess: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyWarning: any;
|
||||
let spyInfo: any;
|
||||
let spyCacheSave: any;
|
||||
let spyJobStatusSuccess: any;
|
||||
let spyCoreError: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyWarning = jest.spyOn(core, 'warning');
|
||||
spyWarning = core.warning as jest.Mock;
|
||||
spyWarning.mockImplementation(() => null);
|
||||
|
||||
spyInfo = jest.spyOn(core, 'info');
|
||||
spyInfo = core.info as jest.Mock;
|
||||
spyInfo.mockImplementation(() => null);
|
||||
|
||||
spyCacheSave = jest.spyOn(cache, 'saveCache');
|
||||
spyCacheSave = cache.saveCache as jest.Mock;
|
||||
|
||||
spyJobStatusSuccess = jest.spyOn(util, 'isJobStatusSuccess');
|
||||
spyJobStatusSuccess = util.isJobStatusSuccess as jest.Mock;
|
||||
spyJobStatusSuccess.mockReturnValue(true);
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
|
||||
createStateForSuccessfulRestore();
|
||||
@@ -47,7 +102,7 @@ describe('cleanup', () => {
|
||||
)
|
||||
)
|
||||
);
|
||||
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
|
||||
(core.getInput as jest.Mock<any>).mockImplementation((name: string) => {
|
||||
return name === 'cache' ? 'gradle' : '';
|
||||
});
|
||||
await cleanup();
|
||||
@@ -59,23 +114,66 @@ describe('cleanup', () => {
|
||||
spyCacheSave.mockImplementation((paths: string[], key: string) =>
|
||||
Promise.reject(new Error('Unexpected error'))
|
||||
);
|
||||
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
|
||||
(core.getInput as jest.Mock<any>).mockImplementation((name: string) => {
|
||||
return name === 'cache' ? 'gradle' : '';
|
||||
});
|
||||
await cleanup();
|
||||
expect(spyCacheSave).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it.each(['maven', 'gradle', 'sbt'])(
|
||||
'does not save the %s cache in read-only mode',
|
||||
async packageManager => {
|
||||
createStateForSuccessfulRestoreWithWrapper(packageManager);
|
||||
(core.getInput as jest.Mock<any>).mockImplementation((name: string) => {
|
||||
switch (name) {
|
||||
case 'cache':
|
||||
return packageManager;
|
||||
case 'cache-read-only':
|
||||
return 'true';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
await cleanup();
|
||||
|
||||
expect(spyCacheSave).not.toHaveBeenCalled();
|
||||
expect(core.getState).not.toHaveBeenCalled();
|
||||
expect(spyInfo).toHaveBeenCalledWith(
|
||||
'Cache saving is skipped because cache-read-only is enabled.'
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
it('saves the cache when read-only mode is explicitly disabled', async () => {
|
||||
spyCacheSave.mockResolvedValue(0);
|
||||
(core.getInput as jest.Mock<any>).mockImplementation((name: string) => {
|
||||
switch (name) {
|
||||
case 'cache':
|
||||
return 'maven';
|
||||
case 'cache-read-only':
|
||||
return 'false';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
await cleanup();
|
||||
|
||||
expect(spyCacheSave).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
function resetState() {
|
||||
jest.spyOn(core, 'getState').mockReset();
|
||||
(core.getState as jest.Mock).mockReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create states to emulate a successful restore process.
|
||||
*/
|
||||
function createStateForSuccessfulRestore() {
|
||||
jest.spyOn(core, 'getState').mockImplementation(name => {
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: any) => {
|
||||
switch (name) {
|
||||
case 'cache-primary-key':
|
||||
return 'setup-java-cache-primary-key';
|
||||
@@ -86,3 +184,18 @@ function createStateForSuccessfulRestore() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function createStateForSuccessfulRestoreWithWrapper(packageManager: string) {
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: any) => {
|
||||
switch (name) {
|
||||
case 'cache-primary-key':
|
||||
return 'setup-java-cache-primary-key';
|
||||
case 'cache-matched-key':
|
||||
return 'setup-java-cache-matched-key';
|
||||
case `cache-primary-key-${packageManager}-wrapper`:
|
||||
return `setup-java-${packageManager}-wrapper-primary-key`;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
{
|
||||
"8": [
|
||||
{
|
||||
"version": "8.0.20",
|
||||
"jdkVersion": "8u432",
|
||||
"latest": true,
|
||||
"baseUrl": "https://github.com/Tencent/TencentKona-8/releases/download/8.0.20-GA/",
|
||||
"files": [
|
||||
{
|
||||
"os": "linux",
|
||||
"arch": "aarch64",
|
||||
"filename": "TencentKona8.0.20.b1_jdk_linux-aarch64_8u432.tar.gz",
|
||||
"checksum": "8e6ab38b17f98d7ba727037cb49bbd174f3103a6ddacafb1fb7c0231006a80a7"
|
||||
},
|
||||
{
|
||||
"os": "linux",
|
||||
"arch": "x86_64",
|
||||
"filename": "TencentKona8.0.20.b1_jdk_linux-x86_64_8u432.tar.gz",
|
||||
"checksum": "384cdb36b38993f4b7292682a5dfd8d5d33ba7bdbca2d95018d1341c792d2823"
|
||||
},
|
||||
{
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"filename": "TencentKona8.0.20.b1_jdk_macosx-aarch64_8u432_notarized.tar.gz",
|
||||
"checksum": "829c46691a4b519f14fedfcdca32a94d7793d3570c4a51b3a5072cc394619f25"
|
||||
},
|
||||
{
|
||||
"os": "macos",
|
||||
"arch": "x86_64",
|
||||
"filename": "TencentKona8.0.20.b1_jdk_macosx-x86_64_8u432_notarized.tar.gz",
|
||||
"checksum": ""
|
||||
},
|
||||
{
|
||||
"os": "windows",
|
||||
"arch": "x86_64",
|
||||
"filename": "TencentKona8.0.20.b1_jdk_windows-x86_64_8u432_signed.zip",
|
||||
"checksum": "339646817254dbcb5c17904807bbfdeafaa8e4bac9f2aae25434870cdeaba296"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"11": [
|
||||
{
|
||||
"version": "11.0.25",
|
||||
"jdkVersion": "11.0.25",
|
||||
"latest": true,
|
||||
"baseUrl": "https://github.com/Tencent/TencentKona-11/releases/download/kona11.0.25/",
|
||||
"files": [
|
||||
{
|
||||
"os": "linux",
|
||||
"arch": "aarch64",
|
||||
"filename": "TencentKona-11.0.25.b1-jdk_linux-aarch64.tar.gz",
|
||||
"checksum": "887ca5eeb675dd9b9d22833a8b0c1031ee1a031227d6cf2d8c1920cc585d2b71"
|
||||
},
|
||||
{
|
||||
"os": "linux",
|
||||
"arch": "x86_64",
|
||||
"filename": "TencentKona-11.0.25.b1-jdk_linux-x86_64.tar.gz",
|
||||
"checksum": "6642d7cccf98f33b3ec55cdbf77979c614f0d3cbbd282e8d0df52233edc52f9a"
|
||||
},
|
||||
{
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"filename": "TencentKona-11.0.25.b1_jdk_macosx-aarch64_notarized.tar.gz",
|
||||
"checksum": "8f07242d3191a35c3b2fca1122f315518c7312f0155e98ac7ae39ea083f93e21"
|
||||
},
|
||||
{
|
||||
"os": "macos",
|
||||
"arch": "x86_64",
|
||||
"filename": "TencentKona-11.0.25.b1_jdk_macosx-x86_64_notarized.tar.gz",
|
||||
"checksum": "0832b93d8d8122cb72db85321ddd85c9a6086e0f28327733fc2da3c0ecc9c455"
|
||||
},
|
||||
{
|
||||
"os": "windows",
|
||||
"arch": "x86_64",
|
||||
"filename": "TencentKona-11.0.25.b1_jdk_windows-x86_64_signed.zip",
|
||||
"checksum": "05c470c5da4b3bc1844117f611ecd241d3ae9e5d01c17ffafffde0f23825aad7"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"17": [
|
||||
{
|
||||
"version": "17.0.13",
|
||||
"jdkVersion": "17.0.13",
|
||||
"latest": true,
|
||||
"baseUrl": "https://github.com/Tencent/TencentKona-17/releases/download/TencentKona-17.0.13/",
|
||||
"files": [
|
||||
{
|
||||
"os": "linux",
|
||||
"arch": "aarch64",
|
||||
"filename": "TencentKona-17.0.13.b1-jdk_linux-aarch64.tar.gz",
|
||||
"checksum": "372411dff5b42f6e419f1dd40772d98141a15c3d180ed1af6f2b49bdbbd32d52"
|
||||
},
|
||||
{
|
||||
"os": "linux",
|
||||
"arch": "x86_64",
|
||||
"filename": "TencentKona-17.0.13.b1-jdk_linux-x86_64.tar.gz",
|
||||
"checksum": "b54bb023d1187737b23ca34d0857d2d40822b14e38d28c7948c8ff6b5927e523"
|
||||
},
|
||||
{
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"filename": "TencentKona-17.0.13.b1_jdk_macosx-aarch64_notarized.tar.gz",
|
||||
"checksum": "22f5d296c407fc137e6af9ce275e662346ca82f1a5acfc407247efd8cedf5256"
|
||||
},
|
||||
{
|
||||
"os": "macos",
|
||||
"arch": "x86_64",
|
||||
"filename": "TencentKona-17.0.13.b1_jdk_macosx-x86_64_notarized.tar.gz",
|
||||
"checksum": "87ace41ac9718f2a9512b24bad0f735bc5ac61b8198b4cd5634199f124883b36"
|
||||
},
|
||||
{
|
||||
"os": "windows",
|
||||
"arch": "x86_64",
|
||||
"filename": "TencentKona-17.0.13.b1_jdk_windows-x86_64_signed.zip",
|
||||
"checksum": "616089018151e8e5daf8e88276063633a2cb28a718a2afce49bb8fc10541e83d"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"21": [
|
||||
{
|
||||
"version": "21.0.5",
|
||||
"jdkVersion": "21.0.5",
|
||||
"latest": true,
|
||||
"baseUrl": "https://github.com/Tencent/TencentKona-21/releases/download/TencentKona-21.0.5/",
|
||||
"files": [
|
||||
{
|
||||
"os": "linux",
|
||||
"arch": "aarch64",
|
||||
"filename": "TencentKona-21.0.5.b1-jdk_linux-aarch64.tar.gz",
|
||||
"checksum": "d8ca108147db3f19134d7aa995bac14e1fb3d124b0300a9a7893266a8f028104"
|
||||
},
|
||||
{
|
||||
"os": "linux",
|
||||
"arch": "x86_64",
|
||||
"filename": "TencentKona-21.0.5.b1-jdk_linux-x86_64.tar.gz",
|
||||
"checksum": "afae039d9666fadcb84940c5350b29cd061019b0cc43700f0bf0342320892adf"
|
||||
},
|
||||
{
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"filename": "TencentKona-21.0.5.b1_jdk_macosx-aarch64_notarized.tar.gz",
|
||||
"checksum": "7621a218767bfbd3023b176dc6d9dd019677f8efec0d48a4eb2b2ed2b50bd1fb"
|
||||
},
|
||||
{
|
||||
"os": "macos",
|
||||
"arch": "x86_64",
|
||||
"filename": "TencentKona-21.0.5.b1_jdk_macosx-x86_64_notarized.tar.gz",
|
||||
"checksum": "6c54d46f979ad998b708f664c5aeeeef855660ef527d584a7c2930951cca9999"
|
||||
},
|
||||
{
|
||||
"os": "windows",
|
||||
"arch": "x86_64",
|
||||
"filename": "TencentKona-21.0.5.b1_jdk_windows-x86_64_signed.zip",
|
||||
"checksum": "ee1ee730fc5e02268d91b9df602b65122dad25b3d3898069331ebc8338005da1"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"25": [
|
||||
{
|
||||
"version": "25.0.3",
|
||||
"jdkVersion": "25.0.3",
|
||||
"latest": true,
|
||||
"baseUrl": "https://github.com/Tencent/TencentKona-25/releases/download/TencentKona-25.0.3/",
|
||||
"files": [
|
||||
{
|
||||
"os": "linux",
|
||||
"arch": "aarch64",
|
||||
"filename": "TencentKona-25.0.3.b1-jdk_linux-aarch64.tar.gz",
|
||||
"checksum": "2fb77e3ba9c00045ca497ea22210f18dae4bf7df4c87029f5abadd42a5daf8c7"
|
||||
},
|
||||
{
|
||||
"os": "linux",
|
||||
"arch": "x86_64",
|
||||
"filename": "TencentKona-25.0.3.b1-jdk_linux-x86_64.tar.gz",
|
||||
"checksum": "47445e6fad020e834055a705bb48fa3cd0727a2c57ad6f1c5206a45f4efb2d67"
|
||||
},
|
||||
{
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"filename": "TencentKona-25.0.3.b1_jdk_macosx-aarch64_notarized.tar.gz",
|
||||
"checksum": "e29405eff95da412ed7ecc890e6ef5ebbfcd9ab334005b3d32d1700bbe4204d2"
|
||||
},
|
||||
{
|
||||
"os": "macos",
|
||||
"arch": "x86_64",
|
||||
"filename": "TencentKona-25.0.3.b1_jdk_macosx-x86_64_notarized.tar.gz",
|
||||
"checksum": "d512db5c079db16bd3a9c86d9cb979808994e90e4de29e17d27e5219fe488659"
|
||||
},
|
||||
{
|
||||
"os": "windows",
|
||||
"arch": "x86_64",
|
||||
"filename": "TencentKona-25.0.3.b1_jdk_windows-x86_64_signed.zip",
|
||||
"checksum": "865bce92ccbbca75115076e618a98baa1d0f30fcccdce954c0a22bee33d6ae83"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,739 @@
|
||||
[
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/25.0.1+3-25.0.1+16/bellsoft-liberica-vm-openjdk25.0.1+16-25.0.1+3-linux-amd64.tar.gz",
|
||||
"version": "25.0.1+3",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "25.0.1+16",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/24.1.0+1-23+38/bellsoft-liberica-vm-openjdk23+38-24.1.0+1-linux-amd64.tar.gz",
|
||||
"version": "24.1.0+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "23+38",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/21.3.2/bellsoft-liberica-vm-openjdk11.0.15.1+2-21.3.2+2-linux-amd64.tar.gz",
|
||||
"version": "21.3.2+2",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.15.1+2",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/22.3.0/bellsoft-liberica-vm-openjdk17.0.5+8-22.3.0+2-linux-amd64.tar.gz",
|
||||
"version": "22.3.0+2",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.5+8",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.0.9+1-17.0.16+13/bellsoft-liberica-vm-openjdk17.0.16+13-23.0.9+1-linux-amd64.tar.gz",
|
||||
"version": "23.0.9+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.16+13",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/23.0.0/bellsoft-liberica-vm-openjdk17.0.7+7-23.0.0+1-src.tar.gz",
|
||||
"version": "23.0.0+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.7+7",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/25.0.2+1-25.0.2+13/bellsoft-liberica-vm-openjdk25.0.2+13-25.0.2+1-linux-amd64.tar.gz",
|
||||
"version": "25.0.2+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "25.0.2+13",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/24.1.1+1-23.0.1+13/bellsoft-liberica-vm-openjdk23.0.1+13-24.1.1+1-linux-amd64.tar.gz",
|
||||
"version": "24.1.1+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "23.0.1+13",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.0.12+1-17.0.19+12/bellsoft-liberica-vm-openjdk17.0.19+12-23.0.12+1-linux-amd64.tar.gz",
|
||||
"version": "23.0.12+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.19+12",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.0.3+1-17.0.10+13/bellsoft-liberica-vm-openjdk17.0.10+13-23.0.3+1-linux-amd64.tar.gz",
|
||||
"version": "23.0.3+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.10+13",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/21.3.2/bellsoft-liberica-vm-openjdk11-21.3.2-src.tar.gz",
|
||||
"version": "21.3.2+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.15+10",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/22.3.3/bellsoft-liberica-vm-openjdk11.0.20+8-22.3.3+1-src.tar.gz",
|
||||
"version": "22.3.3+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.20+8",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.0.8+1-17.0.15+10/bellsoft-liberica-vm-openjdk17.0.15+10-23.0.8+1-linux-amd64.tar.gz",
|
||||
"version": "23.0.8+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.15+10",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/21.3.3/bellsoft-liberica-vm-openjdk17.0.4-21.3.3-src.tar.gz",
|
||||
"version": "21.3.3+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.4+8",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.1.7+1-21.0.7+9/bellsoft-liberica-vm-openjdk21.0.7+9-23.1.7+1-linux-amd64.tar.gz",
|
||||
"version": "23.1.7+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "21.0.7+9",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.1.8+1-21.0.8+13/bellsoft-liberica-vm-openjdk21.0.8+13-23.1.8+1-linux-amd64.tar.gz",
|
||||
"version": "23.1.8+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "21.0.8+13",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/21.0.0.2/bellsoft-liberica-vm-openjdk11-21.0.0.2-src.tar.gz",
|
||||
"version": "21.0.0.2",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.10+9",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/23.0.1/bellsoft-liberica-vm-openjdk17.0.8+7-23.0.1+1-linux-amd64.tar.gz",
|
||||
"version": "23.0.1+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.8+7",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/24.0.0+1-22+37/bellsoft-liberica-vm-openjdk22+37-24.0.0+1-linux-amd64.tar.gz",
|
||||
"version": "24.0.0+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "22+37",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/22.1.0/bellsoft-liberica-vm-openjdk17-22.1.0-src.tar.gz",
|
||||
"version": "22.1.0+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.3+7",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/24.0.2+1-22.0.2+11/bellsoft-liberica-vm-openjdk22.0.2+11-24.0.2+1-linux-amd64.tar.gz",
|
||||
"version": "24.0.2+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "22.0.2+11",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/23.0.1/bellsoft-liberica-vm-openjdk20.0.2+10-23.0.1+1-src.tar.gz",
|
||||
"version": "23.0.1+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "20.0.2+10",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/23.1.0/bellsoft-liberica-vm-openjdk21+37-23.1.0+1-linux-amd64.tar.gz",
|
||||
"version": "23.1.0+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "21+37",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.1.4+3-21.0.4+9/bellsoft-liberica-vm-openjdk21.0.4+9-23.1.4+3-linux-amd64.tar.gz",
|
||||
"version": "23.1.4+3",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "21.0.4+9",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/22.3.3/bellsoft-liberica-vm-openjdk11.0.20.1+1-22.3.3+2-linux-amd64.tar.gz",
|
||||
"version": "22.3.3+2",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.20.1+1",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.0.4+1-17.0.11+10/bellsoft-liberica-vm-openjdk17.0.11+10-23.0.4+1-linux-amd64.tar.gz",
|
||||
"version": "23.0.4+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.11+10",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/24.1.2+1-23.0.2+9/bellsoft-liberica-vm-openjdk23.0.2+9-24.1.2+1-linux-amd64.tar.gz",
|
||||
"version": "24.1.2+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "23.0.2+9",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.0.10+1-17.0.17+12/bellsoft-liberica-vm-openjdk17.0.17+12-23.0.10+1-linux-amd64.tar.gz",
|
||||
"version": "23.0.10+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.17+12",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/22.3.1/bellsoft-liberica-vm-openjdk11.0.18+10-22.3.1+1-src.tar.gz",
|
||||
"version": "22.3.1+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.18+10",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/22.0.0.2/bellsoft-liberica-vm-openjdk17-22.0.0.2-src.tar.gz",
|
||||
"version": "22.0.0.2",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.2+9",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/22.0.0.2/bellsoft-liberica-vm-openjdk11-22.0.0.2-linux-amd64.tar.gz",
|
||||
"version": "22.0.0.2",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.14.1+1",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/25.0.1+2-25.0.1+14/bellsoft-liberica-vm-openjdk25.0.1+14-25.0.1+2-linux-amd64.tar.gz",
|
||||
"version": "25.0.1+2",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "25.0.1+14",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/21.3.3/bellsoft-liberica-vm-openjdk11.0.16-21.3.3-src.tar.gz",
|
||||
"version": "21.3.3+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.16+8",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.1.5+1-21.0.5+11/bellsoft-liberica-vm-openjdk21.0.5+11-23.1.5+1-linux-amd64.tar.gz",
|
||||
"version": "23.1.5+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "21.0.5+11",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/22.3.4/bellsoft-liberica-vm-openjdk17.0.9+11-22.3.4+1-linux-amd64.tar.gz",
|
||||
"version": "22.3.4+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.9+11",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/25.0.0+1-25+37/bellsoft-liberica-vm-openjdk25+37-25.0.0+1-linux-amd64.tar.gz",
|
||||
"version": "25.0.0+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "25+37",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/22.3.3/bellsoft-liberica-vm-openjdk17.0.8.1+1-22.3.3+2-linux-amd64.tar.gz",
|
||||
"version": "22.3.3+2",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.8.1+1",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.1.3+1-21.0.3+10/bellsoft-liberica-vm-openjdk21.0.3+10-23.1.3+1-linux-amd64.tar.gz",
|
||||
"version": "23.1.3+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "21.0.3+10",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/24.2.0+1-24+37/bellsoft-liberica-vm-openjdk24+37-24.2.0+1-linux-amd64.tar.gz",
|
||||
"version": "24.2.0+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "24+37",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/23.1.1/bellsoft-liberica-vm-openjdk21.0.1+12-23.1.1+1-linux-amd64.tar.gz",
|
||||
"version": "23.1.1+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "21.0.1+12",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/21.3.3/bellsoft-liberica-vm-openjdk17.0.4.1-21.3.3-src.tar.gz",
|
||||
"version": "21.3.3+2",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.4.1+1",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.1.11+2-21.0.11+12/bellsoft-liberica-vm-openjdk21.0.11+12-23.1.11+2-linux-amd64.tar.gz",
|
||||
"version": "23.1.11+2",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "21.0.11+12",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/22.3.2/bellsoft-liberica-vm-openjdk11.0.19+7-22.3.2+1-src.tar.gz",
|
||||
"version": "22.3.2+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.19+7",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/22.3.4/bellsoft-liberica-vm-openjdk11.0.21+10-22.3.4+1-src.tar.gz",
|
||||
"version": "22.3.4+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.21+10",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/25.0.3+2-25.0.3+12/bellsoft-liberica-vm-openjdk25.0.3+12-25.0.3+2-linux-amd64.tar.gz",
|
||||
"version": "25.0.3+2",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "25.0.3+12",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/21.3.2/bellsoft-liberica-vm-openjdk17.0.3.1+2-21.3.2+2-linux-amd64.tar.gz",
|
||||
"version": "21.3.2+2",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.3.1+2",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/24.2.1+1-24.0.1+11/bellsoft-liberica-vm-openjdk24.0.1+11-24.2.1+1-linux-amd64.tar.gz",
|
||||
"version": "24.2.1+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "24.0.1+11",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/22.2.0/bellsoft-liberica-vm-openjdk11.0.16.1+1-22.2.0+3-linux-amd64.tar.gz",
|
||||
"version": "22.2.0+3",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.16.1+1",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.0.6+1-17.0.13+12/bellsoft-liberica-vm-openjdk17.0.13+12-23.0.6+1-linux-amd64.tar.gz",
|
||||
"version": "23.0.6+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.13+12",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/23.0.0/bellsoft-liberica-vm-openjdk20.0.1+10-23.0.0+1-linux-amd64.tar.gz",
|
||||
"version": "23.0.0+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "20.0.1+10",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.1.10+1-21.0.10+11/bellsoft-liberica-vm-openjdk21.0.10+11-23.1.10+1-linux-amd64.tar.gz",
|
||||
"version": "23.1.10+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "21.0.10+11",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/22.3.1/bellsoft-liberica-vm-openjdk17.0.6+10-22.3.1+1-src.tar.gz",
|
||||
"version": "22.3.1+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.6+10",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/21.3.0/bellsoft-liberica-vm-openjdk17-21.3.0-src.tar.gz",
|
||||
"version": "21.3.0",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.1+12",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/21.3.0/bellsoft-liberica-vm-openjdk11-21.3.0-src.tar.gz",
|
||||
"version": "21.3.0",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.13+8",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/24.0.1+1-22.0.1+10/bellsoft-liberica-vm-openjdk22.0.1+10-24.0.1+1-linux-amd64.tar.gz",
|
||||
"version": "24.0.1+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "22.0.1+10",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.0.7+1-17.0.14+10/bellsoft-liberica-vm-openjdk17.0.14+10-23.0.7+1-linux-amd64.tar.gz",
|
||||
"version": "23.0.7+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.14+10",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/21.1.0/bellsoft-liberica-vm-openjdk11-21.1.0-src.tar.gz",
|
||||
"version": "21.1.0",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.11+9",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.1.6+1-21.0.6+10/bellsoft-liberica-vm-openjdk21.0.6+10-23.1.6+1-linux-amd64.tar.gz",
|
||||
"version": "23.1.6+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "21.0.6+10",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/25.0.1+1-25.0.1+12/bellsoft-liberica-vm-openjdk25.0.1+12-25.0.1+1-linux-amd64.tar.gz",
|
||||
"version": "25.0.1+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "25.0.1+12",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.1.9+1-21.0.9+12/bellsoft-liberica-vm-openjdk21.0.9+12-23.1.9+1-linux-amd64.tar.gz",
|
||||
"version": "23.1.9+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "21.0.9+12",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/22.3.5+1-11.0.22+12/bellsoft-liberica-vm-openjdk11.0.22+12-22.3.5+1-linux-amd64.tar.gz",
|
||||
"version": "22.3.5+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.22+12",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.0.5+1-17.0.12+10/bellsoft-liberica-vm-openjdk17.0.12+10-23.0.5+1-linux-amd64.tar.gz",
|
||||
"version": "23.0.5+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.12+10",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/21.3.3.1/bellsoft-liberica-vm-openjdk11.0.17+7-21.3.3.1+1-linux-amd64.tar.gz",
|
||||
"version": "21.3.3.1+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.17+7",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://download.bell-sw.com/vm/21.2.0/bellsoft-liberica-vm-openjdk11-21.2.0-linux-amd64.tar.gz",
|
||||
"version": "21.2.0",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "11.0.12+7",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.0.11+1-17.0.18+11/bellsoft-liberica-vm-openjdk17.0.18+11-23.0.11+1-linux-amd64.tar.gz",
|
||||
"version": "23.0.11+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "17.0.18+11",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/23.1.2+1-21.0.2+14/bellsoft-liberica-vm-openjdk21.0.2+14-23.1.2+1-linux-amd64.tar.gz",
|
||||
"version": "23.1.2+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "21.0.2+14",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"downloadUrl": "https://github.com/bell-sw/LibericaNIK/releases/download/24.2.2+1-24.0.2+13/bellsoft-liberica-vm-openjdk24.0.2+13-24.2.2+1-linux-amd64.tar.gz",
|
||||
"version": "24.2.2+1",
|
||||
"components": [
|
||||
{
|
||||
"component": "liberica",
|
||||
"version": "24.0.2+13",
|
||||
"embedded": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -2,7 +2,7 @@
|
||||
7.0.352-zulu, 7.0.352
|
||||
8.0.282-trava, 8.0.282
|
||||
8.0.432-albba, 8.0.432
|
||||
8.0.432-amzn, 8.0.432
|
||||
8.0.432-amzn, 8
|
||||
8.0.432-kona, 8.0.432
|
||||
8.0.432-librca, 8.0.432
|
||||
8.0.432-sem, 8.0.432
|
||||
@@ -10,7 +10,7 @@
|
||||
8.0.432-zulu, 8.0.432
|
||||
8.0.432.fx-librca, 8.0.432
|
||||
8.0.432.fx-zulu, 8.0.432
|
||||
8.0.442-amzn, 8.0.442
|
||||
8.0.442-amzn, 8
|
||||
8.0.442-librca, 8.0.442
|
||||
8.0.442-tem, 8.0.442
|
||||
8.0.442-zulu, 8.0.442
|
||||
@@ -19,7 +19,7 @@
|
||||
11.0.14.1-jbr, 11.0.14
|
||||
11.0.15-trava, 11.0.15
|
||||
11.0.25-albba, 11.0.25
|
||||
11.0.25-amzn, 11.0.25
|
||||
11.0.25-amzn, 11
|
||||
11.0.25-kona, 11.0.25
|
||||
11.0.25-librca, 11.0.25
|
||||
11.0.25-ms, 11.0.25
|
||||
@@ -29,7 +29,7 @@
|
||||
11.0.25-zulu, 11.0.25
|
||||
11.0.25.fx-librca, 11.0.25
|
||||
11.0.25.fx-zulu, 11.0.25
|
||||
11.0.26-amzn, 11.0.26
|
||||
11.0.26-amzn, 11
|
||||
11.0.26-librca, 11.0.26
|
||||
11.0.26-ms, 11.0.26
|
||||
11.0.26-sapmchn, 11.0.26
|
||||
@@ -40,7 +40,7 @@
|
||||
17.0.12-jbr, 17.0.12
|
||||
17.0.12-oracle, 17.0.12
|
||||
17.0.13-albba, 17.0.13
|
||||
17.0.13-amzn, 17.0.13
|
||||
17.0.13-amzn, 17
|
||||
17.0.13-kona, 17.0.13
|
||||
17.0.13-librca, 17.0.13
|
||||
17.0.13-ms, 17.0.13
|
||||
@@ -52,7 +52,7 @@
|
||||
17.0.13.crac-zulu, 17.0.13
|
||||
17.0.13.fx-librca, 17.0.13
|
||||
17.0.13.fx-zulu, 17.0.13
|
||||
17.0.14-amzn, 17.0.14
|
||||
17.0.14-amzn, 17
|
||||
17.0.14-librca, 17.0.14
|
||||
17.0.14-ms, 17.0.14
|
||||
17.0.14-sapmchn, 17.0.14
|
||||
@@ -62,7 +62,7 @@
|
||||
17.0.9-graalce, 17.0.9
|
||||
21.0.2-graalce, 21.0.2
|
||||
21.0.2-open, 21.0.2
|
||||
21.0.5-amzn, 21.0.5
|
||||
21.0.5-amzn, 21
|
||||
21.0.5-graal, 21.0.5
|
||||
21.0.5-jbr, 21.0.5
|
||||
21.0.5-kona, 21.0.5
|
||||
@@ -77,7 +77,7 @@
|
||||
21.0.5.crac-zulu, 21.0.5
|
||||
21.0.5.fx-librca, 21.0.5
|
||||
21.0.5.fx-zulu, 21.0.5
|
||||
21.0.6-amzn, 21.0.6
|
||||
21.0.6-amzn, 21
|
||||
21.0.6-graal, 21.0.6
|
||||
21.0.6-librca, 21.0.6
|
||||
21.0.6-ms, 21.0.6
|
||||
@@ -94,7 +94,7 @@
|
||||
22.3.5.r17-mandrel, 22.3.5
|
||||
22.3.5.r17-nik, 22.3.5
|
||||
23-open, 23
|
||||
23.0.1-amzn, 23.0.1
|
||||
23.0.1-amzn, 23
|
||||
23.0.1-graal, 23.0.1
|
||||
23.0.1-graalce, 23.0.1
|
||||
23.0.1-librca, 23.0.1
|
||||
@@ -106,7 +106,7 @@
|
||||
23.0.1.crac-zulu, 23.0.1
|
||||
23.0.1.fx-librca, 23.0.1
|
||||
23.0.1.fx-zulu, 23.0.1
|
||||
23.0.2-amzn, 23.0.2
|
||||
23.0.2-amzn, 23
|
||||
23.0.2-graal, 23.0.2
|
||||
23.0.2-graalce, 23.0.2
|
||||
23.0.2-librca, 23.0.2
|
||||
|
||||
|
+578
-146
@@ -1,254 +1,686 @@
|
||||
[
|
||||
[
|
||||
{
|
||||
"id": 10996,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu1.8.0_05-8.1.0.10-linux.tar.gz",
|
||||
"package_uuid": "test-uuid-10996",
|
||||
"name": "zulu1.8.0_05-8.1.0.10-linux.tar.gz",
|
||||
"zulu_version": [8, 1, 0, 10],
|
||||
"jdk_version": [8, 0, 5, 13]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu1.8.0_05-8.1.0.10-linux.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"openjdk_build_number": 13,
|
||||
"distro_version": [
|
||||
8,
|
||||
1,
|
||||
0,
|
||||
10
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10997,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu1.8.0_11-8.2.0.1-linux.tar.gz",
|
||||
"package_uuid": "test-uuid-10997",
|
||||
"name": "zulu1.8.0_11-8.2.0.1-linux.tar.gz",
|
||||
"zulu_version": [8, 2, 0, 1],
|
||||
"jdk_version": [8, 0, 11, 12]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu1.8.0_11-8.2.0.1-linux.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
11
|
||||
],
|
||||
"openjdk_build_number": 12,
|
||||
"distro_version": [
|
||||
8,
|
||||
2,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10346,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.21.0.1-jdk8.0.131-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10346",
|
||||
"name": "zulu8.21.0.1-jdk8.0.131-linux_x64.tar.gz",
|
||||
"zulu_version": [8, 21, 0, 1],
|
||||
"jdk_version": [8, 0, 131, 11]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.21.0.1-jdk8.0.131-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
131
|
||||
],
|
||||
"openjdk_build_number": 11,
|
||||
"distro_version": [
|
||||
8,
|
||||
21,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10362,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.23.0.3-jdk8.0.144-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10362",
|
||||
"name": "zulu8.23.0.3-jdk8.0.144-linux_x64.tar.gz",
|
||||
"zulu_version": [8, 23, 0, 3],
|
||||
"jdk_version": [8, 0, 144, 1]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.23.0.3-jdk8.0.144-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
144
|
||||
],
|
||||
"openjdk_build_number": 1,
|
||||
"distro_version": [
|
||||
8,
|
||||
23,
|
||||
0,
|
||||
3
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10399,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.25.0.1-jdk8.0.152-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10399",
|
||||
"name": "zulu8.25.0.1-jdk8.0.152-linux_x64.tar.gz",
|
||||
"zulu_version": [8, 25, 0, 1],
|
||||
"jdk_version": [8, 0, 152, 16]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.25.0.1-jdk8.0.152-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
152
|
||||
],
|
||||
"openjdk_build_number": 16,
|
||||
"distro_version": [
|
||||
8,
|
||||
25,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11355,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.46.0.19-ca-jdk8.0.252-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11355",
|
||||
"name": "zulu8.46.0.19-ca-jdk8.0.252-linux_x64.tar.gz",
|
||||
"zulu_version": [8, 46, 0, 19],
|
||||
"jdk_version": [8, 0, 252, 14]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.46.0.19-ca-jdk8.0.252-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
252
|
||||
],
|
||||
"openjdk_build_number": 14,
|
||||
"distro_version": [
|
||||
8,
|
||||
46,
|
||||
0,
|
||||
19
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11481,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.47-ca-jdk8.0.262-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11481",
|
||||
"name": "zulu8.48.0.47-ca-jdk8.0.262-linux_x64.tar.gz",
|
||||
"zulu_version": [8, 48, 0, 47],
|
||||
"jdk_version": [8, 0, 262, 17]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.47-ca-jdk8.0.262-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
262
|
||||
],
|
||||
"openjdk_build_number": 17,
|
||||
"distro_version": [
|
||||
8,
|
||||
48,
|
||||
0,
|
||||
47
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11622,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.51-ca-jdk8.0.262-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11622",
|
||||
"name": "zulu8.48.0.51-ca-jdk8.0.262-linux_x64.tar.gz",
|
||||
"zulu_version": [8, 48, 0, 51],
|
||||
"jdk_version": [8, 0, 262, 19]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.51-ca-jdk8.0.262-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
262
|
||||
],
|
||||
"openjdk_build_number": 19,
|
||||
"distro_version": [
|
||||
8,
|
||||
48,
|
||||
0,
|
||||
51
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11535,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.49-ca-jdk8.0.262-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11535",
|
||||
"name": "zulu8.48.0.49-ca-jdk8.0.262-linux_x64.tar.gz",
|
||||
"zulu_version": [8, 48, 0, 49],
|
||||
"jdk_version": [8, 0, 262, 18]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.49-ca-jdk8.0.262-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
262
|
||||
],
|
||||
"openjdk_build_number": 18,
|
||||
"distro_version": [
|
||||
8,
|
||||
48,
|
||||
0,
|
||||
49
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12424,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.52.0.23-ca-jdk8.0.282-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-12424",
|
||||
"name": "zulu8.52.0.23-ca-jdk8.0.282-linux_x64.tar.gz",
|
||||
"zulu_version": [8, 52, 0, 23],
|
||||
"jdk_version": [8, 0, 282, 8]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.52.0.23-ca-jdk8.0.282-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
282
|
||||
],
|
||||
"openjdk_build_number": 8,
|
||||
"distro_version": [
|
||||
8,
|
||||
52,
|
||||
0,
|
||||
23
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10383,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu9.0.0.15-jdk9.0.0-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10383",
|
||||
"name": "zulu9.0.0.15-jdk9.0.0-linux_x64.tar.gz",
|
||||
"zulu_version": [9, 0, 0, 15],
|
||||
"jdk_version": [9, 0, 0, 0]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu9.0.0.15-jdk9.0.0-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
9,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"openjdk_build_number": 0,
|
||||
"distro_version": [
|
||||
9,
|
||||
0,
|
||||
0,
|
||||
15
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10413,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu9.0.1.3-jdk9.0.1-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10413",
|
||||
"name": "zulu9.0.1.3-jdk9.0.1-linux_x64.tar.gz",
|
||||
"zulu_version": [9, 0, 1, 3],
|
||||
"jdk_version": [9, 0, 1, 0]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu9.0.1.3-jdk9.0.1-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
9,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 0,
|
||||
"distro_version": [
|
||||
9,
|
||||
0,
|
||||
1,
|
||||
3
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10503,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu10.2+3-jdk10.0.1-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10503",
|
||||
"name": "zulu10.2+3-jdk10.0.1-linux_x64.tar.gz",
|
||||
"zulu_version": [10, 2, 3, 0],
|
||||
"jdk_version": [10, 0, 1, 9]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu10.2+3-jdk10.0.1-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
10,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 9,
|
||||
"distro_version": [
|
||||
10,
|
||||
2,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10541,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu10.3+5-jdk10.0.2-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10541",
|
||||
"name": "zulu10.3+5-jdk10.0.2-linux_x64.tar.gz",
|
||||
"zulu_version": [10, 3, 5, 0],
|
||||
"jdk_version": [10, 0, 2, 13]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu10.3+5-jdk10.0.2-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
10,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 13,
|
||||
"distro_version": [
|
||||
10,
|
||||
3,
|
||||
5,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10576,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.2.3-jdk11.0.1-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10576",
|
||||
"name": "zulu11.2.3-jdk11.0.1-linux_x64.tar.gz",
|
||||
"zulu_version": [11, 2, 3, 0],
|
||||
"jdk_version": [11, 0, 1, 13]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.2.3-jdk11.0.1-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 13,
|
||||
"distro_version": [
|
||||
11,
|
||||
2,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10604,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.29.3-ca-jdk11.0.2-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10604",
|
||||
"name": "zulu11.29.3-ca-jdk11.0.2-linux_x64.tar.gz",
|
||||
"zulu_version": [11, 29, 3, 0],
|
||||
"jdk_version": [11, 0, 2, 7]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.29.3-ca-jdk11.0.2-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 7,
|
||||
"distro_version": [
|
||||
11,
|
||||
29,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10687,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.31.11-ca-jdk11.0.3-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10687",
|
||||
"name": "zulu11.31.11-ca-jdk11.0.3-linux_x64.tar.gz",
|
||||
"zulu_version": [11, 31, 11, 0],
|
||||
"jdk_version": [11, 0, 3, 7]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.31.11-ca-jdk11.0.3-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
3
|
||||
],
|
||||
"openjdk_build_number": 7,
|
||||
"distro_version": [
|
||||
11,
|
||||
31,
|
||||
11,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10856,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.35.13-ca-jdk11.0.5-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10856",
|
||||
"name": "zulu11.35.13-ca-jdk11.0.5-linux_x64.tar.gz",
|
||||
"zulu_version": [11, 35, 13, 0],
|
||||
"jdk_version": [11, 0, 5, 10]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.35.13-ca-jdk11.0.5-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"openjdk_build_number": 10,
|
||||
"distro_version": [
|
||||
11,
|
||||
35,
|
||||
13,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10933,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.35.15-ca-jdk11.0.5-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10933",
|
||||
"name": "zulu11.35.15-ca-jdk11.0.5-linux_x64.tar.gz",
|
||||
"zulu_version": [11, 35, 15, 0],
|
||||
"jdk_version": [11, 0, 5, 10]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.35.15-ca-jdk11.0.5-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"openjdk_build_number": 10,
|
||||
"distro_version": [
|
||||
11,
|
||||
35,
|
||||
15,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10933,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.35.11-ca-jdk11.0.5-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10933",
|
||||
"name": "zulu11.35.15-ca-jdk11.0.5-linux_x64.tar.gz",
|
||||
"zulu_version": [11, 35, 11, 0],
|
||||
"jdk_version": [11, 0, 5, 10]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.35.11-ca-jdk11.0.5-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"openjdk_build_number": 10,
|
||||
"distro_version": [
|
||||
11,
|
||||
35,
|
||||
11,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12397,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.45.27-ca-jdk11.0.10-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-12397",
|
||||
"name": "zulu11.45.27-ca-jdk11.0.10-linux_x64.tar.gz",
|
||||
"zulu_version": [11, 45, 27, 0],
|
||||
"jdk_version": [11, 0, 10, 9]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.45.27-ca-jdk11.0.10-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
10
|
||||
],
|
||||
"openjdk_build_number": 9,
|
||||
"distro_version": [
|
||||
11,
|
||||
45,
|
||||
27,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10667,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu12.1.3-ca-jdk12.0.0-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10667",
|
||||
"name": "zulu12.1.3-ca-jdk12.0.0-linux_x64.tar.gz",
|
||||
"zulu_version": [12, 1, 3, 0],
|
||||
"jdk_version": [12, 0, 0, 33]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu12.1.3-ca-jdk12.0.0-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
12,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"openjdk_build_number": 33,
|
||||
"distro_version": [
|
||||
12,
|
||||
1,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10710,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu12.2.3-ca-jdk12.0.1-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10710",
|
||||
"name": "zulu12.2.3-ca-jdk12.0.1-linux_x64.tar.gz",
|
||||
"zulu_version": [12, 2, 3, 0],
|
||||
"jdk_version": [12, 0, 1, 12]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu12.2.3-ca-jdk12.0.1-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
12,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 12,
|
||||
"distro_version": [
|
||||
12,
|
||||
2,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10780,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu12.3.11-ca-jdk12.0.2-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10780",
|
||||
"name": "zulu12.3.11-ca-jdk12.0.2-linux_x64.tar.gz",
|
||||
"zulu_version": [12, 3, 11, 0],
|
||||
"jdk_version": [12, 0, 2, 3]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu12.3.11-ca-jdk12.0.2-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
12,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 3,
|
||||
"distro_version": [
|
||||
12,
|
||||
3,
|
||||
11,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10846,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu13.27.9-ca-jdk13.0.0-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10846",
|
||||
"name": "zulu13.27.9-ca-jdk13.0.0-linux_x64.tar.gz",
|
||||
"zulu_version": [13, 27, 9, 0],
|
||||
"jdk_version": [13, 0, 0, 33]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu13.27.9-ca-jdk13.0.0-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
13,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"openjdk_build_number": 33,
|
||||
"distro_version": [
|
||||
13,
|
||||
27,
|
||||
9,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10888,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu13.28.11-ca-jdk13.0.1-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10888",
|
||||
"name": "zulu13.28.11-ca-jdk13.0.1-linux_x64.tar.gz",
|
||||
"zulu_version": [13, 28, 11, 0],
|
||||
"jdk_version": [13, 0, 1, 10]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu13.28.11-ca-jdk13.0.1-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
13,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 10,
|
||||
"distro_version": [
|
||||
13,
|
||||
28,
|
||||
11,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11073,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu13.29.9-ca-jdk13.0.2-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11073",
|
||||
"name": "zulu13.29.9-ca-jdk13.0.2-linux_x64.tar.gz",
|
||||
"zulu_version": [13, 29, 9, 0],
|
||||
"jdk_version": [13, 0, 2, 6]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu13.29.9-ca-jdk13.0.2-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
13,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 6,
|
||||
"distro_version": [
|
||||
13,
|
||||
29,
|
||||
9,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12408,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu13.37.21-ca-jdk13.0.6-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-12408",
|
||||
"name": "zulu13.37.21-ca-jdk13.0.6-linux_x64.tar.gz",
|
||||
"zulu_version": [13, 37, 21, 0],
|
||||
"jdk_version": [13, 0, 6, 5]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu13.37.21-ca-jdk13.0.6-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
13,
|
||||
0,
|
||||
6
|
||||
],
|
||||
"openjdk_build_number": 5,
|
||||
"distro_version": [
|
||||
13,
|
||||
37,
|
||||
21,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11236,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu14.27.1-ca-jdk14.0.0-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11236",
|
||||
"name": "zulu14.27.1-ca-jdk14.0.0-linux_x64.tar.gz",
|
||||
"zulu_version": [14, 27, 1, 0],
|
||||
"jdk_version": [14, 0, 0, 36]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu14.27.1-ca-jdk14.0.0-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
14,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"openjdk_build_number": 36,
|
||||
"distro_version": [
|
||||
14,
|
||||
27,
|
||||
1,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11349,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu14.28.21-ca-jdk14.0.1-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11349",
|
||||
"name": "zulu14.28.21-ca-jdk14.0.1-linux_x64.tar.gz",
|
||||
"zulu_version": [14, 28, 21, 0],
|
||||
"jdk_version": [14, 0, 1, 8]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu14.28.21-ca-jdk14.0.1-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
14,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 8,
|
||||
"distro_version": [
|
||||
14,
|
||||
28,
|
||||
21,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11513,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu14.29.23-ca-jdk14.0.2-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11513",
|
||||
"name": "zulu14.29.23-ca-jdk14.0.2-linux_x64.tar.gz",
|
||||
"zulu_version": [14, 29, 23, 0],
|
||||
"jdk_version": [14, 0, 2, 12]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu14.29.23-ca-jdk14.0.2-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
14,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 12,
|
||||
"distro_version": [
|
||||
14,
|
||||
29,
|
||||
23,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11780,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu15.27.17-ca-jdk15.0.0-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11780",
|
||||
"name": "zulu15.27.17-ca-jdk15.0.0-linux_x64.tar.gz",
|
||||
"zulu_version": [15, 27, 17, 0],
|
||||
"jdk_version": [15, 0, 0, 36]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu15.27.17-ca-jdk15.0.0-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
15,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"openjdk_build_number": 36,
|
||||
"distro_version": [
|
||||
15,
|
||||
27,
|
||||
17,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11924,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu15.28.13-ca-jdk15.0.1-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11924",
|
||||
"name": "zulu15.28.13-ca-jdk15.0.1-linux_x64.tar.gz",
|
||||
"zulu_version": [15, 28, 13, 0],
|
||||
"jdk_version": [15, 0, 1, 8]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu15.28.13-ca-jdk15.0.1-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
15,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 8,
|
||||
"distro_version": [
|
||||
15,
|
||||
28,
|
||||
13,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12101,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu15.28.51-ca-jdk15.0.1-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-12101",
|
||||
"name": "zulu15.28.51-ca-jdk15.0.1-linux_x64.tar.gz",
|
||||
"zulu_version": [15, 28, 51, 0],
|
||||
"jdk_version": [15, 0, 1, 9]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu15.28.51-ca-jdk15.0.1-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
15,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 9,
|
||||
"distro_version": [
|
||||
15,
|
||||
28,
|
||||
51,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12445,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu15.29.15-ca-jdk15.0.2-linux_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-12445",
|
||||
"name": "zulu15.29.15-ca-jdk15.0.2-linux_x64.tar.gz",
|
||||
"zulu_version": [15, 29, 15, 0],
|
||||
"jdk_version": [15, 0, 2, 7]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu15.29.15-ca-jdk15.0.2-linux_x64.tar.gz",
|
||||
"java_version": [
|
||||
15,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 7,
|
||||
"distro_version": [
|
||||
15,
|
||||
29,
|
||||
15,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12447,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu21.32.17-ca-jdk21.0.2-linux_aarch64.tar.gz",
|
||||
"package_uuid": "test-uuid-12447",
|
||||
"name": "zulu21.32.17-ca-jdk21.0.2-linux_aarch64.tar.gz",
|
||||
"zulu_version": [21, 32, 17, 0],
|
||||
"jdk_version": [21, 0, 2, 6]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu21.32.17-ca-jdk21.0.2-linux_aarch64.tar.gz",
|
||||
"java_version": [
|
||||
21,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 6,
|
||||
"distro_version": [
|
||||
21,
|
||||
32,
|
||||
17,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -1,247 +1,667 @@
|
||||
[
|
||||
{
|
||||
"id": 10996,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu1.8.0_05-8.1.0.10-macosx.tar.gz",
|
||||
"package_uuid": "test-uuid-10996",
|
||||
"name": "zulu1.8.0_05-8.1.0.10-macosx.tar.gz",
|
||||
"zulu_version": [8, 1, 0, 10],
|
||||
"jdk_version": [8, 0, 5, 13]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu1.8.0_05-8.1.0.10-macosx.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"openjdk_build_number": 13,
|
||||
"distro_version": [
|
||||
8,
|
||||
1,
|
||||
0,
|
||||
10
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10997,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu1.8.0_11-8.2.0.1-macosx.tar.gz",
|
||||
"package_uuid": "test-uuid-10997",
|
||||
"name": "zulu1.8.0_11-8.2.0.1-macosx.tar.gz",
|
||||
"zulu_version": [8, 2, 0, 1],
|
||||
"jdk_version": [8, 0, 11, 12]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu1.8.0_11-8.2.0.1-macosx.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
11
|
||||
],
|
||||
"openjdk_build_number": 12,
|
||||
"distro_version": [
|
||||
8,
|
||||
2,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10346,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.21.0.1-jdk8.0.131-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10346",
|
||||
"name": "zulu8.21.0.1-jdk8.0.131-macosx_x64.tar.gz",
|
||||
"zulu_version": [8, 21, 0, 1],
|
||||
"jdk_version": [8, 0, 131, 11]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.21.0.1-jdk8.0.131-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
131
|
||||
],
|
||||
"openjdk_build_number": 11,
|
||||
"distro_version": [
|
||||
8,
|
||||
21,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10362,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.23.0.3-jdk8.0.144-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10362",
|
||||
"name": "zulu8.23.0.3-jdk8.0.144-macosx_x64.tar.gz",
|
||||
"zulu_version": [8, 23, 0, 3],
|
||||
"jdk_version": [8, 0, 144, 1]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.23.0.3-jdk8.0.144-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
144
|
||||
],
|
||||
"openjdk_build_number": 1,
|
||||
"distro_version": [
|
||||
8,
|
||||
23,
|
||||
0,
|
||||
3
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10399,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.25.0.1-jdk8.0.152-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10399",
|
||||
"name": "zulu8.25.0.1-jdk8.0.152-macosx_x64.tar.gz",
|
||||
"zulu_version": [8, 25, 0, 1],
|
||||
"jdk_version": [8, 0, 152, 16]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.25.0.1-jdk8.0.152-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
152
|
||||
],
|
||||
"openjdk_build_number": 16,
|
||||
"distro_version": [
|
||||
8,
|
||||
25,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11355,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.46.0.19-ca-jdk8.0.252-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11355",
|
||||
"name": "zulu8.46.0.19-ca-jdk8.0.252-macosx_x64.tar.gz",
|
||||
"zulu_version": [8, 46, 0, 19],
|
||||
"jdk_version": [8, 0, 252, 14]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.46.0.19-ca-jdk8.0.252-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
252
|
||||
],
|
||||
"openjdk_build_number": 14,
|
||||
"distro_version": [
|
||||
8,
|
||||
46,
|
||||
0,
|
||||
19
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11481,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.47-ca-jdk8.0.262-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11481",
|
||||
"name": "zulu8.48.0.47-ca-jdk8.0.262-macosx_x64.tar.gz",
|
||||
"zulu_version": [8, 48, 0, 47],
|
||||
"jdk_version": [8, 0, 262, 17]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.47-ca-jdk8.0.262-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
262
|
||||
],
|
||||
"openjdk_build_number": 17,
|
||||
"distro_version": [
|
||||
8,
|
||||
48,
|
||||
0,
|
||||
47
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11622,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.51-ca-jdk8.0.262-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11622",
|
||||
"name": "zulu8.48.0.51-ca-jdk8.0.262-macosx_x64.tar.gz",
|
||||
"zulu_version": [8, 48, 0, 51],
|
||||
"jdk_version": [8, 0, 262, 19]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.51-ca-jdk8.0.262-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
262
|
||||
],
|
||||
"openjdk_build_number": 19,
|
||||
"distro_version": [
|
||||
8,
|
||||
48,
|
||||
0,
|
||||
51
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11535,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.49-ca-jdk8.0.262-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11535",
|
||||
"name": "zulu8.48.0.49-ca-jdk8.0.262-macosx_x64.tar.gz",
|
||||
"zulu_version": [8, 48, 0, 49],
|
||||
"jdk_version": [8, 0, 262, 18]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.49-ca-jdk8.0.262-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
262
|
||||
],
|
||||
"openjdk_build_number": 18,
|
||||
"distro_version": [
|
||||
8,
|
||||
48,
|
||||
0,
|
||||
49
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12424,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.52.0.23-ca-jdk8.0.282-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-12424",
|
||||
"name": "zulu8.52.0.23-ca-jdk8.0.282-macosx_x64.tar.gz",
|
||||
"zulu_version": [8, 52, 0, 23],
|
||||
"jdk_version": [8, 0, 282, 8]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.52.0.23-ca-jdk8.0.282-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
282
|
||||
],
|
||||
"openjdk_build_number": 8,
|
||||
"distro_version": [
|
||||
8,
|
||||
52,
|
||||
0,
|
||||
23
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10383,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu9.0.0.15-jdk9.0.0-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10383",
|
||||
"name": "zulu9.0.0.15-jdk9.0.0-macosx_x64.tar.gz",
|
||||
"zulu_version": [9, 0, 0, 15],
|
||||
"jdk_version": [9, 0, 0, 0]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu9.0.0.15-jdk9.0.0-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
9,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"openjdk_build_number": 0,
|
||||
"distro_version": [
|
||||
9,
|
||||
0,
|
||||
0,
|
||||
15
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10413,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu9.0.1.3-jdk9.0.1-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10413",
|
||||
"name": "zulu9.0.1.3-jdk9.0.1-macosx_x64.tar.gz",
|
||||
"zulu_version": [9, 0, 1, 3],
|
||||
"jdk_version": [9, 0, 1, 0]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu9.0.1.3-jdk9.0.1-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
9,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 0,
|
||||
"distro_version": [
|
||||
9,
|
||||
0,
|
||||
1,
|
||||
3
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10503,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu10.2+3-jdk10.0.1-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10503",
|
||||
"name": "zulu10.2+3-jdk10.0.1-macosx_x64.tar.gz",
|
||||
"zulu_version": [10, 2, 3, 0],
|
||||
"jdk_version": [10, 0, 1, 9]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu10.2+3-jdk10.0.1-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
10,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 9,
|
||||
"distro_version": [
|
||||
10,
|
||||
2,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10541,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu10.3+5-jdk10.0.2-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10541",
|
||||
"name": "zulu10.3+5-jdk10.0.2-macosx_x64.tar.gz",
|
||||
"zulu_version": [10, 3, 5, 0],
|
||||
"jdk_version": [10, 0, 2, 13]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu10.3+5-jdk10.0.2-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
10,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 13,
|
||||
"distro_version": [
|
||||
10,
|
||||
3,
|
||||
5,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10576,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.2.3-jdk11.0.1-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10576",
|
||||
"name": "zulu11.2.3-jdk11.0.1-macosx_x64.tar.gz",
|
||||
"zulu_version": [11, 2, 3, 0],
|
||||
"jdk_version": [11, 0, 1, 13]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.2.3-jdk11.0.1-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 13,
|
||||
"distro_version": [
|
||||
11,
|
||||
2,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10604,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.29.3-ca-jdk11.0.2-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10604",
|
||||
"name": "zulu11.29.3-ca-jdk11.0.2-macosx_x64.tar.gz",
|
||||
"zulu_version": [11, 29, 3, 0],
|
||||
"jdk_version": [11, 0, 2, 7]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.29.3-ca-jdk11.0.2-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 7,
|
||||
"distro_version": [
|
||||
11,
|
||||
29,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10687,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.31.11-ca-jdk11.0.3-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10687",
|
||||
"name": "zulu11.31.11-ca-jdk11.0.3-macosx_x64.tar.gz",
|
||||
"zulu_version": [11, 31, 11, 0],
|
||||
"jdk_version": [11, 0, 3, 7]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.31.11-ca-jdk11.0.3-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
3
|
||||
],
|
||||
"openjdk_build_number": 7,
|
||||
"distro_version": [
|
||||
11,
|
||||
31,
|
||||
11,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10856,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.35.13-ca-jdk11.0.5-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10856",
|
||||
"name": "zulu11.35.13-ca-jdk11.0.5-macosx_x64.tar.gz",
|
||||
"zulu_version": [11, 35, 13, 0],
|
||||
"jdk_version": [11, 0, 5, 10]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.35.13-ca-jdk11.0.5-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"openjdk_build_number": 10,
|
||||
"distro_version": [
|
||||
11,
|
||||
35,
|
||||
13,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10933,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.35.15-ca-jdk11.0.5-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10933",
|
||||
"name": "zulu11.35.15-ca-jdk11.0.5-macosx_x64.tar.gz",
|
||||
"zulu_version": [11, 35, 15, 0],
|
||||
"jdk_version": [11, 0, 5, 10]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.35.15-ca-jdk11.0.5-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"openjdk_build_number": 10,
|
||||
"distro_version": [
|
||||
11,
|
||||
35,
|
||||
15,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10933,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.35.11-ca-jdk11.0.5-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10933",
|
||||
"name": "zulu11.35.15-ca-jdk11.0.5-macosx_x64.tar.gz",
|
||||
"zulu_version": [11, 35, 11, 0],
|
||||
"jdk_version": [11, 0, 5, 10]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.35.11-ca-jdk11.0.5-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"openjdk_build_number": 10,
|
||||
"distro_version": [
|
||||
11,
|
||||
35,
|
||||
11,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12397,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.45.27-ca-jdk11.0.10-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-12397",
|
||||
"name": "zulu11.45.27-ca-jdk11.0.10-macosx_x64.tar.gz",
|
||||
"zulu_version": [11, 45, 27, 0],
|
||||
"jdk_version": [11, 0, 10, 9]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.45.27-ca-jdk11.0.10-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
10
|
||||
],
|
||||
"openjdk_build_number": 9,
|
||||
"distro_version": [
|
||||
11,
|
||||
45,
|
||||
27,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10667,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu12.1.3-ca-jdk12.0.0-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10667",
|
||||
"name": "zulu12.1.3-ca-jdk12.0.0-macosx_x64.tar.gz",
|
||||
"zulu_version": [12, 1, 3, 0],
|
||||
"jdk_version": [12, 0, 0, 33]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu12.1.3-ca-jdk12.0.0-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
12,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"openjdk_build_number": 33,
|
||||
"distro_version": [
|
||||
12,
|
||||
1,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10710,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu12.2.3-ca-jdk12.0.1-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10710",
|
||||
"name": "zulu12.2.3-ca-jdk12.0.1-macosx_x64.tar.gz",
|
||||
"zulu_version": [12, 2, 3, 0],
|
||||
"jdk_version": [12, 0, 1, 12]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu12.2.3-ca-jdk12.0.1-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
12,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 12,
|
||||
"distro_version": [
|
||||
12,
|
||||
2,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10780,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu12.3.11-ca-jdk12.0.2-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10780",
|
||||
"name": "zulu12.3.11-ca-jdk12.0.2-macosx_x64.tar.gz",
|
||||
"zulu_version": [12, 3, 11, 0],
|
||||
"jdk_version": [12, 0, 2, 3]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu12.3.11-ca-jdk12.0.2-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
12,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 3,
|
||||
"distro_version": [
|
||||
12,
|
||||
3,
|
||||
11,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10846,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu13.27.9-ca-jdk13.0.0-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10846",
|
||||
"name": "zulu13.27.9-ca-jdk13.0.0-macosx_x64.tar.gz",
|
||||
"zulu_version": [13, 27, 9, 0],
|
||||
"jdk_version": [13, 0, 0, 33]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu13.27.9-ca-jdk13.0.0-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
13,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"openjdk_build_number": 33,
|
||||
"distro_version": [
|
||||
13,
|
||||
27,
|
||||
9,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10888,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu13.28.11-ca-jdk13.0.1-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10888",
|
||||
"name": "zulu13.28.11-ca-jdk13.0.1-macosx_x64.tar.gz",
|
||||
"zulu_version": [13, 28, 11, 0],
|
||||
"jdk_version": [13, 0, 1, 10]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu13.28.11-ca-jdk13.0.1-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
13,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 10,
|
||||
"distro_version": [
|
||||
13,
|
||||
28,
|
||||
11,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11073,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu13.29.9-ca-jdk13.0.2-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11073",
|
||||
"name": "zulu13.29.9-ca-jdk13.0.2-macosx_x64.tar.gz",
|
||||
"zulu_version": [13, 29, 9, 0],
|
||||
"jdk_version": [13, 0, 2, 6]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu13.29.9-ca-jdk13.0.2-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
13,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 6,
|
||||
"distro_version": [
|
||||
13,
|
||||
29,
|
||||
9,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12408,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu13.37.21-ca-jdk13.0.6-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-12408",
|
||||
"name": "zulu13.37.21-ca-jdk13.0.6-macosx_x64.tar.gz",
|
||||
"zulu_version": [13, 37, 21, 0],
|
||||
"jdk_version": [13, 0, 6, 5]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu13.37.21-ca-jdk13.0.6-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
13,
|
||||
0,
|
||||
6
|
||||
],
|
||||
"openjdk_build_number": 5,
|
||||
"distro_version": [
|
||||
13,
|
||||
37,
|
||||
21,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11236,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu14.27.1-ca-jdk14.0.0-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11236",
|
||||
"name": "zulu14.27.1-ca-jdk14.0.0-macosx_x64.tar.gz",
|
||||
"zulu_version": [14, 27, 1, 0],
|
||||
"jdk_version": [14, 0, 0, 36]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu14.27.1-ca-jdk14.0.0-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
14,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"openjdk_build_number": 36,
|
||||
"distro_version": [
|
||||
14,
|
||||
27,
|
||||
1,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11349,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu14.28.21-ca-jdk14.0.1-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11349",
|
||||
"name": "zulu14.28.21-ca-jdk14.0.1-macosx_x64.tar.gz",
|
||||
"zulu_version": [14, 28, 21, 0],
|
||||
"jdk_version": [14, 0, 1, 8]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu14.28.21-ca-jdk14.0.1-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
14,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 8,
|
||||
"distro_version": [
|
||||
14,
|
||||
28,
|
||||
21,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11513,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu14.29.23-ca-jdk14.0.2-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11513",
|
||||
"name": "zulu14.29.23-ca-jdk14.0.2-macosx_x64.tar.gz",
|
||||
"zulu_version": [14, 29, 23, 0],
|
||||
"jdk_version": [14, 0, 2, 12]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu14.29.23-ca-jdk14.0.2-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
14,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 12,
|
||||
"distro_version": [
|
||||
14,
|
||||
29,
|
||||
23,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11780,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu15.27.17-ca-jdk15.0.0-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11780",
|
||||
"name": "zulu15.27.17-ca-jdk15.0.0-macosx_x64.tar.gz",
|
||||
"zulu_version": [15, 27, 17, 0],
|
||||
"jdk_version": [15, 0, 0, 36]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu15.27.17-ca-jdk15.0.0-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
15,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"openjdk_build_number": 36,
|
||||
"distro_version": [
|
||||
15,
|
||||
27,
|
||||
17,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11924,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu15.28.13-ca-jdk15.0.1-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11924",
|
||||
"name": "zulu15.28.13-ca-jdk15.0.1-macosx_x64.tar.gz",
|
||||
"zulu_version": [15, 28, 13, 0],
|
||||
"jdk_version": [15, 0, 1, 8]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu15.28.13-ca-jdk15.0.1-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
15,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 8,
|
||||
"distro_version": [
|
||||
15,
|
||||
28,
|
||||
13,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12101,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu15.28.51-ca-jdk15.0.1-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-12101",
|
||||
"name": "zulu15.28.51-ca-jdk15.0.1-macosx_x64.tar.gz",
|
||||
"zulu_version": [15, 28, 51, 0],
|
||||
"jdk_version": [15, 0, 1, 9]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu15.28.51-ca-jdk15.0.1-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
15,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 9,
|
||||
"distro_version": [
|
||||
15,
|
||||
28,
|
||||
51,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12445,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu15.29.15-ca-jdk15.0.2-macosx_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-12445",
|
||||
"name": "zulu15.29.15-ca-jdk15.0.2-macosx_x64.tar.gz",
|
||||
"zulu_version": [15, 29, 15, 0],
|
||||
"jdk_version": [15, 0, 2, 7]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu15.29.15-ca-jdk15.0.2-macosx_x64.tar.gz",
|
||||
"java_version": [
|
||||
15,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 7,
|
||||
"distro_version": [
|
||||
15,
|
||||
29,
|
||||
15,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
}
|
||||
]
|
||||
|
||||
+579
-147
@@ -1,254 +1,686 @@
|
||||
[
|
||||
[
|
||||
{
|
||||
"id": 10996,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu1.8.0_05-8.1.0.10-windows.tar.gz",
|
||||
"package_uuid": "test-uuid-10996",
|
||||
"name": "zulu1.8.0_05-8.1.0.10-windows.tar.gz",
|
||||
"zulu_version": [8, 1, 0, 10],
|
||||
"jdk_version": [8, 0, 5, 13]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu1.8.0_05-8.1.0.10-windows.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"openjdk_build_number": 13,
|
||||
"distro_version": [
|
||||
8,
|
||||
1,
|
||||
0,
|
||||
10
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10997,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu1.8.0_11-8.2.0.1-windows.tar.gz",
|
||||
"package_uuid": "test-uuid-10997",
|
||||
"name": "zulu1.8.0_11-8.2.0.1-windows.tar.gz",
|
||||
"zulu_version": [8, 2, 0, 1],
|
||||
"jdk_version": [8, 0, 11, 12]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu1.8.0_11-8.2.0.1-windows.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
11
|
||||
],
|
||||
"openjdk_build_number": 12,
|
||||
"distro_version": [
|
||||
8,
|
||||
2,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10346,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.21.0.1-jdk8.0.131-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10346",
|
||||
"name": "zulu8.21.0.1-jdk8.0.131-windows_x64.tar.gz",
|
||||
"zulu_version": [8, 21, 0, 1],
|
||||
"jdk_version": [8, 0, 131, 11]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.21.0.1-jdk8.0.131-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
131
|
||||
],
|
||||
"openjdk_build_number": 11,
|
||||
"distro_version": [
|
||||
8,
|
||||
21,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10362,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.23.0.3-jdk8.0.144-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10362",
|
||||
"name": "zulu8.23.0.3-jdk8.0.144-windows_x64.tar.gz",
|
||||
"zulu_version": [8, 23, 0, 3],
|
||||
"jdk_version": [8, 0, 144, 1]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.23.0.3-jdk8.0.144-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
144
|
||||
],
|
||||
"openjdk_build_number": 1,
|
||||
"distro_version": [
|
||||
8,
|
||||
23,
|
||||
0,
|
||||
3
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10399,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.25.0.1-jdk8.0.152-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10399",
|
||||
"name": "zulu8.25.0.1-jdk8.0.152-windows_x64.tar.gz",
|
||||
"zulu_version": [8, 25, 0, 1],
|
||||
"jdk_version": [8, 0, 152, 16]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.25.0.1-jdk8.0.152-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
152
|
||||
],
|
||||
"openjdk_build_number": 16,
|
||||
"distro_version": [
|
||||
8,
|
||||
25,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11355,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.46.0.19-ca-jdk8.0.252-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11355",
|
||||
"name": "zulu8.46.0.19-ca-jdk8.0.252-windows_x64.tar.gz",
|
||||
"zulu_version": [8, 46, 0, 19],
|
||||
"jdk_version": [8, 0, 252, 14]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.46.0.19-ca-jdk8.0.252-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
252
|
||||
],
|
||||
"openjdk_build_number": 14,
|
||||
"distro_version": [
|
||||
8,
|
||||
46,
|
||||
0,
|
||||
19
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11481,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.47-ca-jdk8.0.262-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11481",
|
||||
"name": "zulu8.48.0.47-ca-jdk8.0.262-windows_x64.tar.gz",
|
||||
"zulu_version": [8, 48, 0, 47],
|
||||
"jdk_version": [8, 0, 262, 17]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.47-ca-jdk8.0.262-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
262
|
||||
],
|
||||
"openjdk_build_number": 17,
|
||||
"distro_version": [
|
||||
8,
|
||||
48,
|
||||
0,
|
||||
47
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11622,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.51-ca-jdk8.0.262-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11622",
|
||||
"name": "zulu8.48.0.51-ca-jdk8.0.262-windows_x64.tar.gz",
|
||||
"zulu_version": [8, 48, 0, 51],
|
||||
"jdk_version": [8, 0, 262, 19]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.51-ca-jdk8.0.262-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
262
|
||||
],
|
||||
"openjdk_build_number": 19,
|
||||
"distro_version": [
|
||||
8,
|
||||
48,
|
||||
0,
|
||||
51
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11535,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.49-ca-jdk8.0.262-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11535",
|
||||
"name": "zulu8.48.0.49-ca-jdk8.0.262-windows_x64.tar.gz",
|
||||
"zulu_version": [8, 48, 0, 49],
|
||||
"jdk_version": [8, 0, 262, 18]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.49-ca-jdk8.0.262-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
262
|
||||
],
|
||||
"openjdk_build_number": 18,
|
||||
"distro_version": [
|
||||
8,
|
||||
48,
|
||||
0,
|
||||
49
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12424,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu8.52.0.23-ca-jdk8.0.282-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-12424",
|
||||
"name": "zulu8.52.0.23-ca-jdk8.0.282-windows_x64.tar.gz",
|
||||
"zulu_version": [8, 52, 0, 23],
|
||||
"jdk_version": [8, 0, 282, 8]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu8.52.0.23-ca-jdk8.0.282-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
8,
|
||||
0,
|
||||
282
|
||||
],
|
||||
"openjdk_build_number": 8,
|
||||
"distro_version": [
|
||||
8,
|
||||
52,
|
||||
0,
|
||||
23
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10383,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu9.0.0.15-jdk9.0.0-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10383",
|
||||
"name": "zulu9.0.0.15-jdk9.0.0-windows_x64.tar.gz",
|
||||
"zulu_version": [9, 0, 0, 15],
|
||||
"jdk_version": [9, 0, 0, 0]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu9.0.0.15-jdk9.0.0-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
9,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"openjdk_build_number": 0,
|
||||
"distro_version": [
|
||||
9,
|
||||
0,
|
||||
0,
|
||||
15
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10413,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu9.0.1.3-jdk9.0.1-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10413",
|
||||
"name": "zulu9.0.1.3-jdk9.0.1-windows_x64.tar.gz",
|
||||
"zulu_version": [9, 0, 1, 3],
|
||||
"jdk_version": [9, 0, 1, 0]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu9.0.1.3-jdk9.0.1-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
9,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 0,
|
||||
"distro_version": [
|
||||
9,
|
||||
0,
|
||||
1,
|
||||
3
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10503,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu10.2+3-jdk10.0.1-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10503",
|
||||
"name": "zulu10.2+3-jdk10.0.1-windows_x64.tar.gz",
|
||||
"zulu_version": [10, 2, 3, 0],
|
||||
"jdk_version": [10, 0, 1, 9]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu10.2+3-jdk10.0.1-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
10,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 9,
|
||||
"distro_version": [
|
||||
10,
|
||||
2,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10541,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu10.3+5-jdk10.0.2-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10541",
|
||||
"name": "zulu10.3+5-jdk10.0.2-windows_x64.tar.gz",
|
||||
"zulu_version": [10, 3, 5, 0],
|
||||
"jdk_version": [10, 0, 2, 13]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu10.3+5-jdk10.0.2-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
10,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 13,
|
||||
"distro_version": [
|
||||
10,
|
||||
3,
|
||||
5,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10576,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.2.3-jdk11.0.1-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10576",
|
||||
"name": "zulu11.2.3-jdk11.0.1-windows_x64.tar.gz",
|
||||
"zulu_version": [11, 2, 3, 0],
|
||||
"jdk_version": [11, 0, 1, 13]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.2.3-jdk11.0.1-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 13,
|
||||
"distro_version": [
|
||||
11,
|
||||
2,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10604,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.29.3-ca-jdk11.0.2-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10604",
|
||||
"name": "zulu11.29.3-ca-jdk11.0.2-windows_x64.tar.gz",
|
||||
"zulu_version": [11, 29, 3, 0],
|
||||
"jdk_version": [11, 0, 2, 7]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.29.3-ca-jdk11.0.2-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 7,
|
||||
"distro_version": [
|
||||
11,
|
||||
29,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10687,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.31.11-ca-jdk11.0.3-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10687",
|
||||
"name": "zulu11.31.11-ca-jdk11.0.3-windows_x64.tar.gz",
|
||||
"zulu_version": [11, 31, 11, 0],
|
||||
"jdk_version": [11, 0, 3, 7]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.31.11-ca-jdk11.0.3-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
3
|
||||
],
|
||||
"openjdk_build_number": 7,
|
||||
"distro_version": [
|
||||
11,
|
||||
31,
|
||||
11,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10856,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.35.13-ca-jdk11.0.5-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10856",
|
||||
"name": "zulu11.35.13-ca-jdk11.0.5-windows_x64.tar.gz",
|
||||
"zulu_version": [11, 35, 13, 0],
|
||||
"jdk_version": [11, 0, 5, 10]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.35.13-ca-jdk11.0.5-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"openjdk_build_number": 10,
|
||||
"distro_version": [
|
||||
11,
|
||||
35,
|
||||
13,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10933,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.35.15-ca-jdk11.0.5-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10933",
|
||||
"name": "zulu11.35.15-ca-jdk11.0.5-windows_x64.tar.gz",
|
||||
"zulu_version": [11, 35, 15, 0],
|
||||
"jdk_version": [11, 0, 5, 10]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.35.15-ca-jdk11.0.5-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"openjdk_build_number": 10,
|
||||
"distro_version": [
|
||||
11,
|
||||
35,
|
||||
15,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10933,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.35.11-ca-jdk11.0.5-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10933",
|
||||
"name": "zulu11.35.15-ca-jdk11.0.5-windows_x64.tar.gz",
|
||||
"zulu_version": [11, 35, 11, 0],
|
||||
"jdk_version": [11, 0, 5, 10]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.35.11-ca-jdk11.0.5-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
5
|
||||
],
|
||||
"openjdk_build_number": 10,
|
||||
"distro_version": [
|
||||
11,
|
||||
35,
|
||||
11,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12397,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu11.45.27-ca-jdk11.0.10-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-12397",
|
||||
"name": "zulu11.45.27-ca-jdk11.0.10-windows_x64.tar.gz",
|
||||
"zulu_version": [11, 45, 27, 0],
|
||||
"jdk_version": [11, 0, 10, 9]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu11.45.27-ca-jdk11.0.10-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
11,
|
||||
0,
|
||||
10
|
||||
],
|
||||
"openjdk_build_number": 9,
|
||||
"distro_version": [
|
||||
11,
|
||||
45,
|
||||
27,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10667,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu12.1.3-ca-jdk12.0.0-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10667",
|
||||
"name": "zulu12.1.3-ca-jdk12.0.0-windows_x64.tar.gz",
|
||||
"zulu_version": [12, 1, 3, 0],
|
||||
"jdk_version": [12, 0, 0, 33]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu12.1.3-ca-jdk12.0.0-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
12,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"openjdk_build_number": 33,
|
||||
"distro_version": [
|
||||
12,
|
||||
1,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10710,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu12.2.3-ca-jdk12.0.1-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10710",
|
||||
"name": "zulu12.2.3-ca-jdk12.0.1-windows_x64.tar.gz",
|
||||
"zulu_version": [12, 2, 3, 0],
|
||||
"jdk_version": [12, 0, 1, 12]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu12.2.3-ca-jdk12.0.1-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
12,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 12,
|
||||
"distro_version": [
|
||||
12,
|
||||
2,
|
||||
3,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10780,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu12.3.11-ca-jdk12.0.2-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10780",
|
||||
"name": "zulu12.3.11-ca-jdk12.0.2-windows_x64.tar.gz",
|
||||
"zulu_version": [12, 3, 11, 0],
|
||||
"jdk_version": [12, 0, 2, 3]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu12.3.11-ca-jdk12.0.2-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
12,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 3,
|
||||
"distro_version": [
|
||||
12,
|
||||
3,
|
||||
11,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10846,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu13.27.9-ca-jdk13.0.0-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10846",
|
||||
"name": "zulu13.27.9-ca-jdk13.0.0-windows_x64.tar.gz",
|
||||
"zulu_version": [13, 27, 9, 0],
|
||||
"jdk_version": [13, 0, 0, 33]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu13.27.9-ca-jdk13.0.0-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
13,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"openjdk_build_number": 33,
|
||||
"distro_version": [
|
||||
13,
|
||||
27,
|
||||
9,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 10888,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu13.28.11-ca-jdk13.0.1-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-10888",
|
||||
"name": "zulu13.28.11-ca-jdk13.0.1-windows_x64.tar.gz",
|
||||
"zulu_version": [13, 28, 11, 0],
|
||||
"jdk_version": [13, 0, 1, 10]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu13.28.11-ca-jdk13.0.1-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
13,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 10,
|
||||
"distro_version": [
|
||||
13,
|
||||
28,
|
||||
11,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11073,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu13.29.9-ca-jdk13.0.2-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11073",
|
||||
"name": "zulu13.29.9-ca-jdk13.0.2-windows_x64.tar.gz",
|
||||
"zulu_version": [13, 29, 9, 0],
|
||||
"jdk_version": [13, 0, 2, 6]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu13.29.9-ca-jdk13.0.2-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
13,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 6,
|
||||
"distro_version": [
|
||||
13,
|
||||
29,
|
||||
9,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12408,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu13.37.21-ca-jdk13.0.6-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-12408",
|
||||
"name": "zulu13.37.21-ca-jdk13.0.6-windows_x64.tar.gz",
|
||||
"zulu_version": [13, 37, 21, 0],
|
||||
"jdk_version": [13, 0, 6, 5]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu13.37.21-ca-jdk13.0.6-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
13,
|
||||
0,
|
||||
6
|
||||
],
|
||||
"openjdk_build_number": 5,
|
||||
"distro_version": [
|
||||
13,
|
||||
37,
|
||||
21,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11236,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu14.27.1-ca-jdk14.0.0-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11236",
|
||||
"name": "zulu14.27.1-ca-jdk14.0.0-windows_x64.tar.gz",
|
||||
"zulu_version": [14, 27, 1, 0],
|
||||
"jdk_version": [14, 0, 0, 36]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu14.27.1-ca-jdk14.0.0-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
14,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"openjdk_build_number": 36,
|
||||
"distro_version": [
|
||||
14,
|
||||
27,
|
||||
1,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11349,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu14.28.21-ca-jdk14.0.1-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11349",
|
||||
"name": "zulu14.28.21-ca-jdk14.0.1-windows_x64.tar.gz",
|
||||
"zulu_version": [14, 28, 21, 0],
|
||||
"jdk_version": [14, 0, 1, 8]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu14.28.21-ca-jdk14.0.1-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
14,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 8,
|
||||
"distro_version": [
|
||||
14,
|
||||
28,
|
||||
21,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11513,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu14.29.23-ca-jdk14.0.2-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11513",
|
||||
"name": "zulu14.29.23-ca-jdk14.0.2-windows_x64.tar.gz",
|
||||
"zulu_version": [14, 29, 23, 0],
|
||||
"jdk_version": [14, 0, 2, 12]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu14.29.23-ca-jdk14.0.2-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
14,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 12,
|
||||
"distro_version": [
|
||||
14,
|
||||
29,
|
||||
23,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11780,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu15.27.17-ca-jdk15.0.0-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11780",
|
||||
"name": "zulu15.27.17-ca-jdk15.0.0-windows_x64.tar.gz",
|
||||
"zulu_version": [15, 27, 17, 0],
|
||||
"jdk_version": [15, 0, 0, 36]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu15.27.17-ca-jdk15.0.0-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
15,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"openjdk_build_number": 36,
|
||||
"distro_version": [
|
||||
15,
|
||||
27,
|
||||
17,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 11924,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu15.28.13-ca-jdk15.0.1-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-11924",
|
||||
"name": "zulu15.28.13-ca-jdk15.0.1-windows_x64.tar.gz",
|
||||
"zulu_version": [15, 28, 13, 0],
|
||||
"jdk_version": [15, 0, 1, 8]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu15.28.13-ca-jdk15.0.1-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
15,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 8,
|
||||
"distro_version": [
|
||||
15,
|
||||
28,
|
||||
13,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12101,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu15.28.51-ca-jdk15.0.1-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-12101",
|
||||
"name": "zulu15.28.51-ca-jdk15.0.1-windows_x64.tar.gz",
|
||||
"zulu_version": [15, 28, 51, 0],
|
||||
"jdk_version": [15, 0, 1, 9]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu15.28.51-ca-jdk15.0.1-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
15,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"openjdk_build_number": 9,
|
||||
"distro_version": [
|
||||
15,
|
||||
28,
|
||||
51,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12445,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu15.29.15-ca-jdk15.0.2-windows_x64.tar.gz",
|
||||
"package_uuid": "test-uuid-12445",
|
||||
"name": "zulu15.29.15-ca-jdk15.0.2-windows_x64.tar.gz",
|
||||
"zulu_version": [15, 29, 15, 0],
|
||||
"jdk_version": [15, 0, 2, 7]
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu15.29.15-ca-jdk15.0.2-windows_x64.tar.gz",
|
||||
"java_version": [
|
||||
15,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"openjdk_build_number": 7,
|
||||
"distro_version": [
|
||||
15,
|
||||
29,
|
||||
15,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
},
|
||||
{
|
||||
"id": 12446,
|
||||
"url": "https://cdn.azul.com/zulu/bin/zulu17.48.15-ca-jdk17.0.10-windows_aarch64.zip",
|
||||
"name": "zulu17.48.15-ca-jdk17.0.10-win_aarch4.zip",
|
||||
"zulu_version": [17, 48, 15, 0],
|
||||
"jdk_version": [17, 0, 10, 7]
|
||||
"package_uuid": "test-uuid-12446",
|
||||
"name": "zulu17.48.15-ca-jdk17.0.10-win_aarch64.zip",
|
||||
"download_url": "https://cdn.azul.com/zulu/bin/zulu17.48.15-ca-jdk17.0.10-windows_aarch64.zip",
|
||||
"java_version": [
|
||||
17,
|
||||
0,
|
||||
10
|
||||
],
|
||||
"openjdk_build_number": 7,
|
||||
"distro_version": [
|
||||
17,
|
||||
48,
|
||||
15,
|
||||
0
|
||||
],
|
||||
"latest": false,
|
||||
"availability_type": "ca"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -1,21 +1,59 @@
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import {IAdoptAvailableVersions} from '../../src/distributions/adopt/models';
|
||||
import {
|
||||
AdoptDistribution,
|
||||
AdoptImplementation
|
||||
} from '../../src/distributions/adopt/installer';
|
||||
import {TemurinDistribution} from '../../src/distributions/temurin/installer';
|
||||
import {JavaInstallerOptions} from '../../src/distributions/base-models';
|
||||
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import os from 'os';
|
||||
|
||||
import manifestData from '../data/adopt.json';
|
||||
import * as core from '@actions/core';
|
||||
import manifestData from '../data/adopt.json' with {type: 'json'};
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const {AdoptDistribution, AdoptImplementation} =
|
||||
await import('../../src/distributions/adopt/installer.js');
|
||||
const {TemurinDistribution} =
|
||||
await import('../../src/distributions/temurin/installer.js');
|
||||
|
||||
import type {IAdoptAvailableVersions} from '../../src/distributions/adopt/models.js';
|
||||
import type {AdoptImplementation as AdoptImplementationType} from '../../src/distributions/adopt/installer.js';
|
||||
import type {JavaInstallerOptions} from '../../src/distributions/base-models.js';
|
||||
|
||||
describe('getAvailableVersions', () => {
|
||||
let spyHttpClient: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyCoreWarning: jest.SpyInstance;
|
||||
let spyHttpClient: any;
|
||||
let spyCoreError: any;
|
||||
let spyCoreWarning: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
@@ -26,9 +64,9 @@ describe('getAvailableVersions', () => {
|
||||
});
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
spyCoreWarning = jest.spyOn(core, 'warning');
|
||||
spyCoreWarning = core.warning as jest.Mock;
|
||||
spyCoreWarning.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -123,7 +161,7 @@ describe('getAvailableVersions', () => {
|
||||
'build correct url for %s',
|
||||
async (
|
||||
installerOptions: JavaInstallerOptions,
|
||||
impl: AdoptImplementation,
|
||||
impl: AdoptImplementationType,
|
||||
expectedParameters
|
||||
) => {
|
||||
const distribution = new AdoptDistribution(installerOptions, impl);
|
||||
@@ -204,7 +242,7 @@ describe('getAvailableVersions', () => {
|
||||
[AdoptImplementation.OpenJ9, 'jre', 'Java_Adopt-OpenJ9_jre']
|
||||
])(
|
||||
'find right toolchain folder',
|
||||
(impl: AdoptImplementation, packageType: string, expected: string) => {
|
||||
(impl: AdoptImplementationType, packageType: string, expected: string) => {
|
||||
const distribution = new AdoptDistribution(
|
||||
{
|
||||
version: '11',
|
||||
@@ -222,6 +260,7 @@ describe('getAvailableVersions', () => {
|
||||
|
||||
it.each([
|
||||
['amd64', 'x64'],
|
||||
['arm', 'arm'],
|
||||
['arm64', 'aarch64']
|
||||
])(
|
||||
'defaults to os.arch(): %s mapped to distro arch: %s',
|
||||
@@ -263,11 +302,11 @@ describe('findPackageForDownload', () => {
|
||||
url: 'https://example.test/temurin-11.tar.gz'
|
||||
};
|
||||
const temurinFindPackageForDownload = jest
|
||||
.fn()
|
||||
.fn<any>()
|
||||
.mockResolvedValue(temurinRelease);
|
||||
const temurinDistribution = {
|
||||
findPackageForDownload: temurinFindPackageForDownload
|
||||
} as unknown as TemurinDistribution;
|
||||
} as any;
|
||||
|
||||
const distribution = new AdoptDistribution(
|
||||
{
|
||||
@@ -279,7 +318,7 @@ describe('findPackageForDownload', () => {
|
||||
AdoptImplementation.Hotspot,
|
||||
temurinDistribution
|
||||
);
|
||||
const adoptLookupSpy = jest.fn();
|
||||
const adoptLookupSpy = jest.fn<any>();
|
||||
distribution['getAvailableVersions'] = adoptLookupSpy;
|
||||
|
||||
const resolvedVersion = await distribution['findPackageForDownload']('11');
|
||||
@@ -319,6 +358,14 @@ describe('findPackageForDownload', () => {
|
||||
distribution['getAvailableVersions'] = async () => manifestData as any;
|
||||
const resolvedVersion = await distribution['findPackageForDownload'](input);
|
||||
expect(resolvedVersion.version).toBe(expected);
|
||||
const vendorPackage = (manifestData as any[]).find(
|
||||
item => item.version_data.semver === expected
|
||||
).binaries[0].package;
|
||||
expect(resolvedVersion.checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: vendorPackage.checksum,
|
||||
source: vendorPackage.checksum_link
|
||||
});
|
||||
});
|
||||
|
||||
it('version is found but binaries list is empty', async () => {
|
||||
|
||||
@@ -1,19 +1,93 @@
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as core from '@actions/core';
|
||||
import * as util from '../../src/util';
|
||||
|
||||
import path from 'path';
|
||||
import * as semver from 'semver';
|
||||
|
||||
import {JavaBase} from '../../src/distributions/base-installer';
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import type {
|
||||
JavaDownloadRelease,
|
||||
JavaInstallerOptions,
|
||||
JavaInstallerResults
|
||||
} from '../../src/distributions/base-models';
|
||||
} from '../../src/distributions/base-models.js';
|
||||
|
||||
import path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import fs from 'fs';
|
||||
import {createHash} from 'crypto';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
|
||||
import os from 'os';
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('@actions/tool-cache', () => ({
|
||||
find: jest.fn(),
|
||||
findAllVersions: jest.fn(),
|
||||
downloadTool: jest.fn(),
|
||||
extractZip: jest.fn(),
|
||||
extractTar: jest.fn(),
|
||||
extract7z: jest.fn(),
|
||||
extractXar: jest.fn(),
|
||||
cacheDir: jest.fn(),
|
||||
cacheFile: jest.fn(),
|
||||
getManifestFromRepo: jest.fn(),
|
||||
findFromManifest: jest.fn(),
|
||||
evaluateVersions: jest.fn(),
|
||||
HTTPError: class HTTPError extends Error {
|
||||
httpStatusCode: number;
|
||||
constructor(statusCode: number) {
|
||||
super(`HTTP Error: ${statusCode}`);
|
||||
this.httpStatusCode = statusCode;
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
const real_util_module = await import('../../src/util.js');
|
||||
jest.unstable_mockModule('../../src/util.js', () => ({
|
||||
...real_util_module,
|
||||
extractJdkFile: jest.fn(),
|
||||
getDownloadArchiveExtension: jest.fn(),
|
||||
getToolcachePath: jest.fn(),
|
||||
isJobStatusSuccess: jest.fn(),
|
||||
renameWinArchive: jest.fn(),
|
||||
isVersionSatisfies: real_util_module.isVersionSatisfies,
|
||||
getTempDir: real_util_module.getTempDir
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const tc = await import('@actions/tool-cache');
|
||||
const util = await import('../../src/util.js');
|
||||
const {JavaBase} = await import('../../src/distributions/base-installer.js');
|
||||
|
||||
class EmptyJavaBase extends JavaBase {
|
||||
constructor(installerOptions: JavaInstallerOptions) {
|
||||
super('Empty', installerOptions);
|
||||
@@ -46,6 +120,17 @@ class EmptyJavaBase extends JavaBase {
|
||||
url: `some/random_url/java/${availableVersion}`
|
||||
};
|
||||
}
|
||||
|
||||
public downloadRelease(javaRelease: JavaDownloadRelease): Promise<string> {
|
||||
return this.downloadAndVerify(javaRelease);
|
||||
}
|
||||
|
||||
public fetchChecksumForTest(
|
||||
checksumUrl: string,
|
||||
algorithm: 'sha256' | 'sha512' | ('sha256' | 'sha512')[]
|
||||
) {
|
||||
return this.fetchChecksum(checksumUrl, algorithm);
|
||||
}
|
||||
}
|
||||
|
||||
describe('findInToolcache', () => {
|
||||
@@ -53,12 +138,12 @@ describe('findInToolcache', () => {
|
||||
const javaPath = path.join('Java_Empty_jdk', actualJavaVersion, 'x64');
|
||||
|
||||
let mockJavaBase: EmptyJavaBase;
|
||||
let spyGetToolcachePath: jest.SpyInstance;
|
||||
let spyTcFindAllVersions: jest.SpyInstance;
|
||||
let spyGetToolcachePath: any;
|
||||
let spyTcFindAllVersions: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyGetToolcachePath = jest.spyOn(util, 'getToolcachePath');
|
||||
spyTcFindAllVersions = jest.spyOn(tc, 'findAllVersions');
|
||||
spyGetToolcachePath = util.getToolcachePath as jest.Mock;
|
||||
spyTcFindAllVersions = tc.findAllVersions as jest.Mock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -241,17 +326,17 @@ describe('setupJava', () => {
|
||||
|
||||
let mockJavaBase: EmptyJavaBase;
|
||||
|
||||
let spyGetToolcachePath: jest.SpyInstance;
|
||||
let spyTcFindAllVersions: jest.SpyInstance;
|
||||
let spyCoreDebug: jest.SpyInstance;
|
||||
let spyCoreInfo: jest.SpyInstance;
|
||||
let spyCoreExportVariable: jest.SpyInstance;
|
||||
let spyCoreAddPath: jest.SpyInstance;
|
||||
let spyCoreSetOutput: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyGetToolcachePath: any;
|
||||
let spyTcFindAllVersions: any;
|
||||
let spyCoreDebug: any;
|
||||
let spyCoreInfo: any;
|
||||
let spyCoreExportVariable: any;
|
||||
let spyCoreAddPath: any;
|
||||
let spyCoreSetOutput: any;
|
||||
let spyCoreError: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyGetToolcachePath = jest.spyOn(util, 'getToolcachePath');
|
||||
spyGetToolcachePath = util.getToolcachePath as jest.Mock;
|
||||
spyGetToolcachePath.mockImplementation(
|
||||
(toolname: string, javaVersion: string, architecture: string) => {
|
||||
const semverVersion = new semver.Range(javaVersion);
|
||||
@@ -269,27 +354,27 @@ describe('setupJava', () => {
|
||||
}
|
||||
);
|
||||
|
||||
spyTcFindAllVersions = jest.spyOn(tc, 'findAllVersions');
|
||||
spyTcFindAllVersions = tc.findAllVersions as jest.Mock;
|
||||
spyTcFindAllVersions.mockReturnValue([installedJavaVersion]);
|
||||
|
||||
// Spy on core methods
|
||||
spyCoreDebug = jest.spyOn(core, 'debug');
|
||||
spyCoreDebug = core.debug as jest.Mock;
|
||||
spyCoreDebug.mockImplementation(() => undefined);
|
||||
|
||||
spyCoreInfo = jest.spyOn(core, 'info');
|
||||
spyCoreInfo = core.info as jest.Mock;
|
||||
spyCoreInfo.mockImplementation(() => undefined);
|
||||
|
||||
spyCoreAddPath = jest.spyOn(core, 'addPath');
|
||||
spyCoreAddPath = core.addPath as jest.Mock;
|
||||
spyCoreAddPath.mockImplementation(() => undefined);
|
||||
|
||||
spyCoreExportVariable = jest.spyOn(core, 'exportVariable');
|
||||
spyCoreExportVariable = core.exportVariable as jest.Mock;
|
||||
spyCoreExportVariable.mockImplementation(() => undefined);
|
||||
|
||||
spyCoreSetOutput = jest.spyOn(core, 'setOutput');
|
||||
spyCoreSetOutput = core.setOutput as jest.Mock;
|
||||
spyCoreSetOutput.mockImplementation(() => undefined);
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => undefined);
|
||||
|
||||
jest.spyOn(os, 'arch').mockReturnValue('x86' as ReturnType<typeof os.arch>);
|
||||
@@ -349,6 +434,58 @@ describe('setupJava', () => {
|
||||
expect(spyCoreInfo).not.toHaveBeenCalledWith('Trying to download...');
|
||||
});
|
||||
|
||||
it('should resolve the latest version from remote when java-version is "latest", even if a version is cached', async () => {
|
||||
mockJavaBase = new EmptyJavaBase({
|
||||
version: 'latest',
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
await expect(mockJavaBase.setupJava()).resolves.toEqual({
|
||||
version: actualJavaVersion,
|
||||
path: javaPathInstalled
|
||||
});
|
||||
|
||||
// `latest` must bypass the tool-cache short-circuit and always resolve remotely
|
||||
expect(spyCoreInfo).toHaveBeenCalledWith(
|
||||
'Trying to resolve the latest version from remote'
|
||||
);
|
||||
expect(spyCoreInfo).toHaveBeenCalledWith('Trying to download...');
|
||||
expect(spyCoreInfo).not.toHaveBeenCalledWith(
|
||||
`Resolved Java ${installedJavaVersion} from tool-cache`
|
||||
);
|
||||
});
|
||||
|
||||
it('should download java when force-download is enabled, even if the version is cached', async () => {
|
||||
mockJavaBase = new EmptyJavaBase({
|
||||
version: actualJavaVersion,
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false,
|
||||
forceDownload: true
|
||||
});
|
||||
const findInToolcache = jest.fn(() => ({
|
||||
version: actualJavaVersion,
|
||||
path: javaPathInstalled
|
||||
}));
|
||||
mockJavaBase['findInToolcache'] = findInToolcache;
|
||||
|
||||
await expect(mockJavaBase.setupJava()).resolves.toEqual({
|
||||
version: actualJavaVersion,
|
||||
path: javaPathInstalled
|
||||
});
|
||||
|
||||
expect(findInToolcache).not.toHaveBeenCalled();
|
||||
expect(spyCoreInfo).toHaveBeenCalledWith('Trying to download...');
|
||||
expect(spyCoreInfo).toHaveBeenCalledWith(
|
||||
`Java ${actualJavaVersion} was downloaded`
|
||||
);
|
||||
expect(spyCoreInfo).not.toHaveBeenCalledWith(
|
||||
`Resolved Java ${actualJavaVersion} from tool-cache`
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
[
|
||||
{
|
||||
@@ -482,6 +619,31 @@ describe('setupJava', () => {
|
||||
expect(spyCoreSetOutput).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not repeat version resolution when downloadTool fails', async () => {
|
||||
mockJavaBase = new EmptyJavaBase({
|
||||
version: '11',
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false,
|
||||
forceDownload: true
|
||||
});
|
||||
const findPackageForDownload = jest.fn(async () => ({
|
||||
version: '11.0.9',
|
||||
url: 'https://example.com/jdk.tar.gz'
|
||||
}));
|
||||
const downloadError = new Error('download failed');
|
||||
const downloadTool = jest.fn(async () => {
|
||||
throw downloadError;
|
||||
});
|
||||
mockJavaBase['findPackageForDownload'] = findPackageForDownload;
|
||||
mockJavaBase['downloadTool'] = downloadTool;
|
||||
|
||||
await expect(mockJavaBase.setupJava()).rejects.toBe(downloadError);
|
||||
|
||||
expect(findPackageForDownload).toHaveBeenCalledTimes(1);
|
||||
expect(downloadTool).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it.each([
|
||||
[
|
||||
{
|
||||
@@ -563,17 +725,428 @@ describe('setupJava', () => {
|
||||
expect(spyCoreExportVariable).not.toHaveBeenCalled();
|
||||
expect(spyCoreSetOutput).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not set JAVA_HOME and PATH when setDefault is false', async () => {
|
||||
mockJavaBase = new EmptyJavaBase({
|
||||
version: '11',
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false,
|
||||
setDefault: false
|
||||
});
|
||||
await expect(mockJavaBase.setupJava()).resolves.toEqual({
|
||||
version: installedJavaVersion,
|
||||
path: javaPath
|
||||
});
|
||||
expect(spyCoreExportVariable).not.toHaveBeenCalledWith(
|
||||
'JAVA_HOME',
|
||||
expect.anything()
|
||||
);
|
||||
expect(spyCoreAddPath).not.toHaveBeenCalled();
|
||||
expect(spyCoreExportVariable).toHaveBeenCalledWith(
|
||||
'JAVA_HOME_11_X86',
|
||||
javaPath
|
||||
);
|
||||
expect(spyCoreSetOutput).toHaveBeenCalledWith(
|
||||
'version',
|
||||
installedJavaVersion
|
||||
);
|
||||
expect(spyCoreSetOutput).toHaveBeenCalledWith('path', javaPath);
|
||||
expect(spyCoreSetOutput).toHaveBeenCalledWith('distribution', 'Empty');
|
||||
expect(spyCoreInfo).toHaveBeenCalledWith(
|
||||
`Installing Java ${installedJavaVersion} (not setting as default)`
|
||||
);
|
||||
});
|
||||
|
||||
it('should set JAVA_HOME and PATH when setDefault is true', async () => {
|
||||
mockJavaBase = new EmptyJavaBase({
|
||||
version: '11',
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false,
|
||||
setDefault: true
|
||||
});
|
||||
await expect(mockJavaBase.setupJava()).resolves.toEqual({
|
||||
version: installedJavaVersion,
|
||||
path: javaPath
|
||||
});
|
||||
expect(spyCoreExportVariable).toHaveBeenCalledWith('JAVA_HOME', javaPath);
|
||||
expect(spyCoreAddPath).toHaveBeenCalledWith(path.join(javaPath, 'bin'));
|
||||
expect(spyCoreExportVariable).toHaveBeenCalledWith(
|
||||
'JAVA_HOME_11_X86',
|
||||
javaPath
|
||||
);
|
||||
expect(spyCoreInfo).toHaveBeenCalledWith(
|
||||
`Setting Java ${installedJavaVersion} as the default`
|
||||
);
|
||||
});
|
||||
|
||||
it('should default to setting as default when setDefault is not specified', async () => {
|
||||
mockJavaBase = new EmptyJavaBase({
|
||||
version: '11',
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
await expect(mockJavaBase.setupJava()).resolves.toEqual({
|
||||
version: installedJavaVersion,
|
||||
path: javaPath
|
||||
});
|
||||
expect(spyCoreExportVariable).toHaveBeenCalledWith('JAVA_HOME', javaPath);
|
||||
expect(spyCoreAddPath).toHaveBeenCalledWith(path.join(javaPath, 'bin'));
|
||||
expect(spyCoreInfo).toHaveBeenCalledWith(
|
||||
`Setting Java ${installedJavaVersion} as the default`
|
||||
);
|
||||
});
|
||||
|
||||
it('should download and not set default when setDefault is false', async () => {
|
||||
mockJavaBase = new EmptyJavaBase({
|
||||
version: '11',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false,
|
||||
setDefault: false
|
||||
});
|
||||
await expect(mockJavaBase.setupJava()).resolves.toEqual({
|
||||
version: '11.0.9',
|
||||
path: path.join('toolcache', 'Java_Empty_jdk', '11.0.9', 'x64')
|
||||
});
|
||||
expect(spyCoreExportVariable).not.toHaveBeenCalledWith(
|
||||
'JAVA_HOME',
|
||||
expect.anything()
|
||||
);
|
||||
expect(spyCoreAddPath).not.toHaveBeenCalled();
|
||||
expect(spyCoreExportVariable).toHaveBeenCalledWith(
|
||||
'JAVA_HOME_11_X64',
|
||||
path.join('toolcache', 'Java_Empty_jdk', '11.0.9', 'x64')
|
||||
);
|
||||
expect(spyCoreSetOutput).toHaveBeenCalledWith('version', '11.0.9');
|
||||
expect(spyCoreSetOutput).toHaveBeenCalledWith(
|
||||
'path',
|
||||
path.join('toolcache', 'Java_Empty_jdk', '11.0.9', 'x64')
|
||||
);
|
||||
expect(spyCoreInfo).toHaveBeenCalledWith(
|
||||
'Installing Java 11.0.9 (not setting as default)'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('downloadAndVerify', () => {
|
||||
const options: JavaInstallerOptions = {
|
||||
version: '21',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
};
|
||||
let temporaryDirectory: string;
|
||||
let archivePath: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
temporaryDirectory = await fs.promises.mkdtemp(
|
||||
path.join(os.tmpdir(), 'setup-java-base-')
|
||||
);
|
||||
archivePath = path.join(temporaryDirectory, 'archive');
|
||||
await fs.promises.writeFile(archivePath, 'downloaded archive');
|
||||
(tc.downloadTool as jest.Mock<any>).mockResolvedValue(archivePath);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await fs.promises.rm(temporaryDirectory, {recursive: true, force: true});
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('returns a download after successful verification', async () => {
|
||||
const distribution = new EmptyJavaBase(options);
|
||||
const result = await distribution.downloadRelease({
|
||||
version: '21.0.8',
|
||||
url: 'https://vendor.example/jdk.tar.gz',
|
||||
checksum: {
|
||||
algorithm: 'sha256',
|
||||
value: createHash('sha256').update('downloaded archive').digest('hex')
|
||||
}
|
||||
});
|
||||
|
||||
expect(result).toBe(archivePath);
|
||||
expect(fs.existsSync(archivePath)).toBe(true);
|
||||
expect(core.debug).toHaveBeenCalledWith(
|
||||
'Verified sha256 checksum for Empty version 21.0.8.'
|
||||
);
|
||||
});
|
||||
|
||||
it('removes the download after verification failure', async () => {
|
||||
const distribution = new EmptyJavaBase(options);
|
||||
|
||||
await expect(
|
||||
distribution.downloadRelease({
|
||||
version: '21.0.8',
|
||||
url: 'https://vendor.example/jdk.tar.gz?token=secret',
|
||||
checksum: {algorithm: 'sha256', value: 'a'.repeat(64)}
|
||||
})
|
||||
).rejects.toThrow('Checksum verification failed for Empty version 21.0.8');
|
||||
|
||||
expect(fs.existsSync(archivePath)).toBe(false);
|
||||
});
|
||||
|
||||
it('preserves the verification error when removing the download fails', async () => {
|
||||
const distribution = new EmptyJavaBase(options);
|
||||
const cleanupError = new Error('cleanup failed');
|
||||
jest.spyOn(fs.promises, 'rm').mockRejectedValueOnce(cleanupError);
|
||||
|
||||
const result = distribution.downloadRelease({
|
||||
version: '21.0.8',
|
||||
url: 'https://vendor.example/jdk.tar.gz',
|
||||
checksum: {algorithm: 'sha256', value: 'a'.repeat(64)}
|
||||
});
|
||||
|
||||
await expect(result).rejects.toMatchObject({
|
||||
message: expect.stringContaining(
|
||||
'Failed to remove the downloaded archive after verification failure: cleanup failed'
|
||||
),
|
||||
cause: expect.objectContaining({
|
||||
message: expect.stringContaining(
|
||||
'Checksum verification failed for Empty version 21.0.8'
|
||||
)
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it('logs when authoritative checksum metadata is unavailable', async () => {
|
||||
const distribution = new EmptyJavaBase(options);
|
||||
|
||||
await expect(
|
||||
distribution.downloadRelease({
|
||||
version: '21.0.8',
|
||||
url: 'https://vendor.example/jdk.tar.gz'
|
||||
})
|
||||
).resolves.toBe(archivePath);
|
||||
|
||||
expect(core.debug).toHaveBeenCalledWith(
|
||||
'No authoritative checksum is available for Empty version 21.0.8; skipping checksum verification.'
|
||||
);
|
||||
});
|
||||
|
||||
it.each([undefined, '', ' '])(
|
||||
'skips verification when the vendor digest is %p',
|
||||
async value => {
|
||||
const distribution = new EmptyJavaBase(options);
|
||||
|
||||
await expect(
|
||||
distribution.downloadRelease({
|
||||
version: '21.0.8',
|
||||
url: 'https://vendor.example/jdk.tar.gz',
|
||||
checksum: {
|
||||
algorithm: 'sha256',
|
||||
value
|
||||
} as JavaDownloadRelease['checksum']
|
||||
})
|
||||
).resolves.toBe(archivePath);
|
||||
|
||||
expect(core.debug).toHaveBeenCalledWith(
|
||||
'No authoritative checksum is available for Empty version 21.0.8; skipping checksum verification.'
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('fetchChecksum', () => {
|
||||
const options: JavaInstallerOptions = {
|
||||
version: '21',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
function mockGet(statusCode: number, body: string) {
|
||||
return jest.spyOn(HttpClient.prototype, 'get').mockResolvedValue({
|
||||
message: {statusCode},
|
||||
readBody: async () => body
|
||||
} as any);
|
||||
}
|
||||
|
||||
it('parses a bare hex digest', async () => {
|
||||
const digest = 'a'.repeat(64);
|
||||
const spy = mockGet(200, digest);
|
||||
const distribution = new EmptyJavaBase(options);
|
||||
|
||||
const checksum = await distribution.fetchChecksumForTest(
|
||||
'https://vendor.example/jdk.tar.gz.sha256',
|
||||
'sha256'
|
||||
);
|
||||
|
||||
expect(spy).toHaveBeenCalledWith(
|
||||
'https://vendor.example/jdk.tar.gz.sha256'
|
||||
);
|
||||
expect(checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: digest,
|
||||
source: 'https://vendor.example/jdk.tar.gz.sha256'
|
||||
});
|
||||
});
|
||||
|
||||
it('parses only the first token of a GNU-style checksum file', async () => {
|
||||
const digest = 'b'.repeat(128);
|
||||
mockGet(200, `${digest} jbrsdk-21.0.3-linux-x64-b465.3.tar.gz\n`);
|
||||
const distribution = new EmptyJavaBase(options);
|
||||
|
||||
const checksum = await distribution.fetchChecksumForTest(
|
||||
'https://vendor.example/jdk.tar.gz.checksum',
|
||||
'sha512'
|
||||
);
|
||||
|
||||
expect(checksum).toEqual({
|
||||
algorithm: 'sha512',
|
||||
value: digest,
|
||||
source: 'https://vendor.example/jdk.tar.gz.checksum'
|
||||
});
|
||||
});
|
||||
|
||||
it('trims surrounding whitespace and newlines', async () => {
|
||||
const digest = 'c'.repeat(64);
|
||||
mockGet(200, `\n ${digest} \n`);
|
||||
const distribution = new EmptyJavaBase(options);
|
||||
|
||||
const checksum = await distribution.fetchChecksumForTest(
|
||||
'https://vendor.example/jdk.tar.gz.sha256',
|
||||
'sha256'
|
||||
);
|
||||
|
||||
expect(checksum.value).toBe(digest);
|
||||
});
|
||||
|
||||
it('skips verification when the sibling checksum is not published', async () => {
|
||||
mockGet(404, 'Not Found');
|
||||
const distribution = new EmptyJavaBase(options);
|
||||
|
||||
await expect(
|
||||
distribution.fetchChecksumForTest(
|
||||
'https://vendor.example/jdk.tar.gz.sha256',
|
||||
'sha256'
|
||||
)
|
||||
).resolves.toBeUndefined();
|
||||
expect(core.debug).toHaveBeenCalledWith(
|
||||
'No authoritative sha256 checksum is available for Empty from https://vendor.example/jdk.tar.gz.sha256; skipping checksum verification.'
|
||||
);
|
||||
});
|
||||
|
||||
it('surfaces unexpected HTTP failures without query parameters', async () => {
|
||||
mockGet(500, 'Server Error');
|
||||
const distribution = new EmptyJavaBase(options);
|
||||
|
||||
await expect(
|
||||
distribution.fetchChecksumForTest(
|
||||
'https://vendor.example/jdk.tar.gz.sha256?token=secret',
|
||||
'sha256'
|
||||
)
|
||||
).rejects.toThrow(
|
||||
'Failed to fetch the authoritative sha256 checksum for Empty from https://vendor.example/jdk.tar.gz.sha256 (HTTP 500).'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects an empty successful checksum response', async () => {
|
||||
mockGet(200, ' \n');
|
||||
const distribution = new EmptyJavaBase(options);
|
||||
|
||||
await expect(
|
||||
distribution.fetchChecksumForTest(
|
||||
'https://vendor.example/jdk.tar.gz.sha256',
|
||||
'sha256'
|
||||
)
|
||||
).rejects.toThrow(
|
||||
'Received an empty authoritative sha256 checksum for Empty from https://vendor.example/jdk.tar.gz.sha256.'
|
||||
);
|
||||
});
|
||||
|
||||
describe('with a list of candidate algorithms', () => {
|
||||
it('infers sha512 when the digest is 128 hex characters', async () => {
|
||||
const digest = 'd'.repeat(128);
|
||||
mockGet(200, `${digest} jbrsdk.tar.gz\n`);
|
||||
const distribution = new EmptyJavaBase(options);
|
||||
|
||||
const checksum = await distribution.fetchChecksumForTest(
|
||||
'https://vendor.example/jbrsdk.tar.gz.checksum',
|
||||
['sha512', 'sha256']
|
||||
);
|
||||
|
||||
expect(checksum).toEqual({
|
||||
algorithm: 'sha512',
|
||||
value: digest,
|
||||
source: 'https://vendor.example/jbrsdk.tar.gz.checksum'
|
||||
});
|
||||
});
|
||||
|
||||
it('infers sha256 when the digest is 64 hex characters, even though sha512 was preferred', async () => {
|
||||
// Reproduces older JetBrains JBR builds (e.g. JBR 11), which publish a
|
||||
// SHA-256 digest at the generic `.checksum` sibling instead of SHA-512.
|
||||
const digest = 'e'.repeat(64);
|
||||
mockGet(200, `${digest} jbrsdk_nomod-11_0_16-osx-x64-b2043.64.tar.gz\n`);
|
||||
const distribution = new EmptyJavaBase(options);
|
||||
|
||||
const checksum = await distribution.fetchChecksumForTest(
|
||||
'https://vendor.example/jbrsdk_nomod-11_0_16-osx-x64-b2043.64.tar.gz.checksum',
|
||||
['sha512', 'sha256']
|
||||
);
|
||||
|
||||
expect(checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: digest,
|
||||
source:
|
||||
'https://vendor.example/jbrsdk_nomod-11_0_16-osx-x64-b2043.64.tar.gz.checksum'
|
||||
});
|
||||
});
|
||||
|
||||
it('falls back to the first candidate algorithm when the digest length matches none of them', async () => {
|
||||
const digest = 'f'.repeat(40); // e.g. sha1, not supported
|
||||
mockGet(200, `${digest} jbrsdk.tar.gz\n`);
|
||||
const distribution = new EmptyJavaBase(options);
|
||||
|
||||
const checksum = await distribution.fetchChecksumForTest(
|
||||
'https://vendor.example/jbrsdk.tar.gz.checksum',
|
||||
['sha512', 'sha256']
|
||||
);
|
||||
|
||||
// No candidate algorithm matches, so the first-listed one is kept;
|
||||
// downstream verification will reject it as malformed.
|
||||
expect(checksum.algorithm).toBe('sha512');
|
||||
expect(checksum.value).toBe(digest);
|
||||
});
|
||||
|
||||
it('reports the checksum as unavailable using a combined algorithm label on 404', async () => {
|
||||
mockGet(404, 'Not Found');
|
||||
const distribution = new EmptyJavaBase(options);
|
||||
|
||||
await expect(
|
||||
distribution.fetchChecksumForTest(
|
||||
'https://vendor.example/jbrsdk.tar.gz.checksum',
|
||||
['sha512', 'sha256']
|
||||
)
|
||||
).resolves.toBeUndefined();
|
||||
expect(core.debug).toHaveBeenCalledWith(
|
||||
'No authoritative sha512 or sha256 checksum is available for Empty from https://vendor.example/jbrsdk.tar.gz.checksum; skipping checksum verification.'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('normalizeVersion', () => {
|
||||
const DummyJavaBase = JavaBase as any;
|
||||
|
||||
it.each([
|
||||
['11', {version: '11', stable: true}],
|
||||
['11.0', {version: '11.0', stable: true}],
|
||||
['11.0.10', {version: '11.0.10', stable: true}],
|
||||
['11-ea', {version: '11', stable: false}],
|
||||
['11.0.2-ea', {version: '11.0.2', stable: false}]
|
||||
['11', {version: '11', stable: true, latest: false}],
|
||||
['11.0', {version: '11.0', stable: true, latest: false}],
|
||||
['11.0.10', {version: '11.0.10', stable: true, latest: false}],
|
||||
['11-ea', {version: '11', stable: false, latest: false}],
|
||||
['11.0.2-ea', {version: '11.0.2', stable: false, latest: false}],
|
||||
['18.0.1.1', {version: '18.0.1+1', stable: true, latest: false}],
|
||||
['11.0.9.1', {version: '11.0.9+1', stable: true, latest: false}],
|
||||
['12.0.2.1.0', {version: '12.0.2+1.0', stable: true, latest: false}],
|
||||
['18.0.1.1-ea', {version: '18.0.1+1', stable: false, latest: false}],
|
||||
['latest', {version: 'x', stable: true, latest: true}],
|
||||
['LATEST', {version: 'x', stable: true, latest: true}],
|
||||
[' Latest ', {version: 'x', stable: true, latest: true}]
|
||||
])('normalizeVersion from %s to %s', (input, expected) => {
|
||||
expect(DummyJavaBase.prototype.normalizeVersion.call(null, input)).toEqual(
|
||||
expected
|
||||
@@ -588,6 +1161,17 @@ describe('normalizeVersion', () => {
|
||||
`The string '${version}' is not valid SemVer notation for a Java version. Please check README file for code snippets and more detailed information`
|
||||
);
|
||||
});
|
||||
|
||||
it.each(['latest-ea', 'latest.1', 'LATEST-EA', ' latest-ea '])(
|
||||
'normalizeVersion should throw a targeted error for latest combined with a qualifier (%s)',
|
||||
version => {
|
||||
expect(
|
||||
DummyJavaBase.prototype.normalizeVersion.bind(null, version)
|
||||
).toThrow(
|
||||
`The 'latest' alias resolves stable (GA) releases only and cannot be combined with '-ea' or other qualifiers (received '${version}'). Use 'latest' on its own, or specify a concrete version.`
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('createVersionNotFoundError', () => {
|
||||
|
||||
@@ -1,17 +1,62 @@
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import type {JavaInstallerOptions} from '../../src/distributions/base-models.js';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import {JavaInstallerOptions} from '../../src/distributions/base-models';
|
||||
|
||||
import {CorrettoDistribution} from '../../src/distributions/corretto/installer';
|
||||
import * as util from '../../src/util';
|
||||
import os from 'os';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import manifestData from '../data/corretto.json';
|
||||
import manifestData from '../data/corretto.json' with {type: 'json'};
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
const real_util_module = await import('../../src/util.js');
|
||||
jest.unstable_mockModule('../../src/util.js', () => ({
|
||||
...real_util_module,
|
||||
getDownloadArchiveExtension: jest.fn()
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const {CorrettoDistribution} =
|
||||
await import('../../src/distributions/corretto/installer.js');
|
||||
const util = await import('../../src/util.js');
|
||||
|
||||
describe('getAvailableVersions', () => {
|
||||
let spyHttpClient: jest.SpyInstance;
|
||||
let spyGetDownloadArchiveExtension: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyHttpClient: ReturnType<typeof jest.spyOn>;
|
||||
let spyGetDownloadArchiveExtension: any;
|
||||
let spyCoreError: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
@@ -20,13 +65,11 @@ describe('getAvailableVersions', () => {
|
||||
headers: {},
|
||||
result: manifestData
|
||||
});
|
||||
spyGetDownloadArchiveExtension = jest.spyOn(
|
||||
util,
|
||||
'getDownloadArchiveExtension'
|
||||
);
|
||||
spyGetDownloadArchiveExtension =
|
||||
util.getDownloadArchiveExtension as jest.Mock;
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -159,6 +202,30 @@ describe('getAvailableVersions', () => {
|
||||
await distribution['findPackageForDownload'](version);
|
||||
expect(availableVersion).not.toBeNull();
|
||||
expect(availableVersion.url).toBe(expectedLink);
|
||||
expect(availableVersion.checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: expect.stringMatching(/^[a-f0-9]{64}$/),
|
||||
source:
|
||||
'https://corretto.github.io/corretto-downloads/latest_links/indexmap_with_checksum.json'
|
||||
});
|
||||
});
|
||||
|
||||
it('with latest resolves to the newest available major version', async () => {
|
||||
const distribution = new CorrettoDistribution({
|
||||
version: 'latest',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
mockPlatform(distribution, 'linux');
|
||||
|
||||
const availableVersion =
|
||||
await distribution['findPackageForDownload']('x');
|
||||
expect(availableVersion).not.toBeNull();
|
||||
// 18 is the newest major present in the mocked Corretto index
|
||||
expect(availableVersion.url).toBe(
|
||||
'https://corretto.aws/downloads/resources/18.0.0.37.1/amazon-corretto-18.0.0.37.1-linux-x64.tar.gz'
|
||||
);
|
||||
});
|
||||
|
||||
it('with unstable version expect to throw not supported error', async () => {
|
||||
@@ -232,10 +299,23 @@ describe('getAvailableVersions', () => {
|
||||
expect(availableVersion.url).toBe(expectedLink);
|
||||
}
|
||||
);
|
||||
|
||||
it('keeps the canonical ARM runner value separate from the vendor value', () => {
|
||||
jest.spyOn(os, 'arch').mockReturnValue('arm');
|
||||
const distribution = new CorrettoDistribution({
|
||||
version: '11',
|
||||
architecture: '',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
expect(distribution['architecture']).toBe('armv7');
|
||||
expect(distribution['distributionArchitecture']()).toBe('arm');
|
||||
});
|
||||
});
|
||||
|
||||
const mockPlatform = (
|
||||
distribution: CorrettoDistribution,
|
||||
distribution: InstanceType<typeof CorrettoDistribution>,
|
||||
platform: string
|
||||
) => {
|
||||
distribution['getPlatformOption'] = () => platform;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import {jest, describe, it, expect} from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../src/distributions/zulu/installer.js', () => {
|
||||
throw new Error(
|
||||
'Zulu installer module must not be imported on the Temurin fast path'
|
||||
);
|
||||
});
|
||||
|
||||
const {getJavaDistribution} =
|
||||
await import('../../src/distributions/distribution-factory.js');
|
||||
|
||||
describe('distribution factory lazy loading', () => {
|
||||
it('does not load non-selected distribution installers for Temurin', async () => {
|
||||
const distribution = await getJavaDistribution('temurin', {
|
||||
version: '21',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
expect(distribution).not.toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,151 @@
|
||||
import {getJavaDistribution} from '../../src/distributions/distribution-factory.js';
|
||||
import {RetryingHttpClient} from '../../src/retrying-http-client.js';
|
||||
import {
|
||||
JAVA_PACKAGE_CAPABILITIES,
|
||||
JavaDistribution
|
||||
} from '../../src/distributions/package-types.js';
|
||||
import os from 'os';
|
||||
import {validateJavaPlatform} from '../../src/distributions/platform-types.js';
|
||||
import {normalizeArchitecture} from '../../src/distributions/platform-types.js';
|
||||
|
||||
const supportedDistributionsOnCurrentPlatform = Object.values(
|
||||
JavaDistribution
|
||||
).filter(distributionName => {
|
||||
try {
|
||||
validateJavaPlatform(distributionName, process.platform, 'x64', '25');
|
||||
return distributionName !== JavaDistribution.JdkFile;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
const installerOptions = (packageType: string, version = '25') => ({
|
||||
version,
|
||||
architecture: 'x64',
|
||||
packageType,
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
describe('getJavaDistribution', () => {
|
||||
it.each(supportedDistributionsOnCurrentPlatform)(
|
||||
'uses the shared retrying HTTP client for %s',
|
||||
async distributionName => {
|
||||
const distribution = await getJavaDistribution(distributionName, {
|
||||
version: '25',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
expect(distribution).not.toBeNull();
|
||||
expect(distribution!['http']).toBeInstanceOf(RetryingHttpClient);
|
||||
}
|
||||
);
|
||||
|
||||
it.each(
|
||||
Object.entries(JAVA_PACKAGE_CAPABILITIES).flatMap(
|
||||
([distributionName, packageTypes]) =>
|
||||
supportedDistributionsOnCurrentPlatform.includes(
|
||||
distributionName as JavaDistribution
|
||||
) || distributionName === JavaDistribution.JdkFile
|
||||
? packageTypes.map(packageType => [distributionName, packageType])
|
||||
: []
|
||||
)
|
||||
)(
|
||||
'accepts %s with java-package %s',
|
||||
async (distributionName, packageType) => {
|
||||
expect(
|
||||
await getJavaDistribution(
|
||||
distributionName,
|
||||
installerOptions(packageType as string)
|
||||
)
|
||||
).not.toBeNull();
|
||||
}
|
||||
);
|
||||
|
||||
it.each(Object.entries(JAVA_PACKAGE_CAPABILITIES))(
|
||||
'rejects unsupported java-package values for %s',
|
||||
async (distributionName, packageTypes) => {
|
||||
await expect(
|
||||
getJavaDistribution(distributionName, installerOptions('jdk+typo'))
|
||||
).rejects.toThrow(
|
||||
`Java package 'jdk+typo' is not supported for distribution '${distributionName}'. Supported package types: ${packageTypes.join(', ')}.`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
it("rejects java-package 'jdk+jmods' for non-Temurin distributions", async () => {
|
||||
await expect(
|
||||
getJavaDistribution('zulu', installerOptions('jdk+jmods'))
|
||||
).rejects.toThrow(
|
||||
"Java package 'jdk+jmods' is not supported for distribution 'zulu'. Supported package types: jdk, jre, jdk+fx, jre+fx, jdk+crac, jre+crac."
|
||||
);
|
||||
});
|
||||
|
||||
it.each(['8', '23.x', '23.0.1.1', '<24'])(
|
||||
"rejects Temurin java-package 'jdk+jmods' for version %s",
|
||||
async version => {
|
||||
await expect(
|
||||
getJavaDistribution(
|
||||
JavaDistribution.Temurin,
|
||||
installerOptions('jdk+jmods', version)
|
||||
)
|
||||
).rejects.toThrow(
|
||||
`Java package 'jdk+jmods' is not supported for distribution 'temurin'. Supported package types: jdk, jre, jdk+jmods. Package 'jdk+jmods' requires Java 24 or later; requested version '${version}'.`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
it.each(['24', '24.0.1.1', '25-ea', '>=21', 'latest'])(
|
||||
"accepts Temurin java-package 'jdk+jmods' for version %s",
|
||||
async version => {
|
||||
expect(
|
||||
await getJavaDistribution(
|
||||
JavaDistribution.Temurin,
|
||||
installerOptions('jdk+jmods', version)
|
||||
)
|
||||
).not.toBeNull();
|
||||
}
|
||||
);
|
||||
|
||||
it('preserves unsupported distribution handling', async () => {
|
||||
expect(
|
||||
await getJavaDistribution(
|
||||
'not-a-distribution',
|
||||
installerOptions('not-a-package')
|
||||
)
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it.each([
|
||||
['amd64', 'x64'],
|
||||
['ia32', 'x86'],
|
||||
['arm64', 'aarch64']
|
||||
])('passes normalized architecture %s as %s', async (input, expected) => {
|
||||
const normalized = await getJavaDistribution(JavaDistribution.JdkFile, {
|
||||
...installerOptions('jdk'),
|
||||
architecture: input
|
||||
});
|
||||
|
||||
expect(normalized!['architecture']).toBe(expected);
|
||||
});
|
||||
|
||||
it('uses the runner architecture when the input is empty', async () => {
|
||||
const distribution = await getJavaDistribution(JavaDistribution.Temurin, {
|
||||
...installerOptions('jdk'),
|
||||
architecture: ''
|
||||
});
|
||||
|
||||
const expected = normalizeArchitecture(os.arch());
|
||||
expect(distribution!['architecture']).toBe(expected);
|
||||
});
|
||||
|
||||
it('rejects an unsupported combination before creating an HTTP client', async () => {
|
||||
await expect(
|
||||
getJavaDistribution(JavaDistribution.Oracle, {
|
||||
...installerOptions('jdk'),
|
||||
architecture: 'x86'
|
||||
})
|
||||
).rejects.toThrow(/does not support operating system/);
|
||||
});
|
||||
});
|
||||
@@ -1,14 +1,59 @@
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import {DragonwellDistribution} from '../../src/distributions/dragonwell/installer';
|
||||
import * as utils from '../../src/util';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import manifestData from '../data/dragonwell.json';
|
||||
import manifestData from '../data/dragonwell.json' with {type: 'json'};
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
const real_util_module = await import('../../src/util.js');
|
||||
jest.unstable_mockModule('../../src/util.js', () => ({
|
||||
...real_util_module,
|
||||
getDownloadArchiveExtension: jest.fn()
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const {DragonwellDistribution} =
|
||||
await import('../../src/distributions/dragonwell/installer.js');
|
||||
const utils = await import('../../src/util.js');
|
||||
|
||||
describe('getAvailableVersions', () => {
|
||||
let spyHttpClient: jest.SpyInstance;
|
||||
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyHttpClient: any;
|
||||
let spyUtilGetDownloadArchiveExtension: any;
|
||||
let spyCoreError: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
@@ -18,14 +63,12 @@ describe('getAvailableVersions', () => {
|
||||
result: manifestData
|
||||
});
|
||||
|
||||
spyUtilGetDownloadArchiveExtension = jest.spyOn(
|
||||
utils,
|
||||
'getDownloadArchiveExtension'
|
||||
);
|
||||
spyUtilGetDownloadArchiveExtension =
|
||||
utils.getDownloadArchiveExtension as jest.Mock;
|
||||
spyUtilGetDownloadArchiveExtension.mockReturnValue('tar.gz');
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -36,7 +79,7 @@ describe('getAvailableVersions', () => {
|
||||
});
|
||||
|
||||
const mockPlatform = (
|
||||
distribution: DragonwellDistribution,
|
||||
distribution: InstanceType<typeof DragonwellDistribution>,
|
||||
platform: string
|
||||
) => {
|
||||
distribution['getPlatformOption'] = () => platform;
|
||||
@@ -216,6 +259,10 @@ describe('getAvailableVersions', () => {
|
||||
await distribution['findPackageForDownload'](jdkVersion);
|
||||
expect(availableVersion).not.toBeNull();
|
||||
expect(availableVersion.url).toBe(expectedLink);
|
||||
expect(availableVersion.checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: expect.stringMatching(/^[a-f0-9]{64}$/)
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -1,53 +1,116 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as http from '@actions/http-client';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import {
|
||||
GraalVMCommunityDistribution,
|
||||
GraalVMDistribution
|
||||
} from '../../src/distributions/graalvm/installer';
|
||||
import {getJavaDistribution} from '../../src/distributions/distribution-factory';
|
||||
import {JavaInstallerOptions} from '../../src/distributions/base-models';
|
||||
import * as util from '../../src/util';
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import path from 'path';
|
||||
|
||||
jest.mock('@actions/core');
|
||||
jest.mock('@actions/tool-cache');
|
||||
jest.mock('@actions/http-client');
|
||||
// Mock @actions modules
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
jest.mock('../../src/util', () => ({
|
||||
...jest.requireActual('../../src/util'),
|
||||
jest.unstable_mockModule('@actions/tool-cache', () => ({
|
||||
find: jest.fn(),
|
||||
findAllVersions: jest.fn(),
|
||||
downloadTool: jest.fn(),
|
||||
extractZip: jest.fn(),
|
||||
extractTar: jest.fn(),
|
||||
extract7z: jest.fn(),
|
||||
extractXar: jest.fn(),
|
||||
cacheDir: jest.fn(),
|
||||
cacheFile: jest.fn(),
|
||||
getManifestFromRepo: jest.fn(),
|
||||
findFromManifest: jest.fn(),
|
||||
evaluateVersions: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('@actions/http-client', () => ({
|
||||
HttpClient: jest.fn().mockImplementation(() => ({
|
||||
getJson: jest.fn(),
|
||||
head: jest.fn(),
|
||||
get: jest.fn()
|
||||
})),
|
||||
HttpClientError: class HttpClientError extends Error {
|
||||
statusCode: number;
|
||||
constructor(message: string, statusCode: number) {
|
||||
super(message);
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
},
|
||||
HttpCodes: {OK: 200, NotFound: 404, Unauthorized: 401, Forbidden: 403}
|
||||
}));
|
||||
|
||||
// Get real util first, then mock specific functions
|
||||
const realUtil = await import('../../src/util.js');
|
||||
jest.unstable_mockModule('../../src/util.js', () => ({
|
||||
...realUtil,
|
||||
extractJdkFile: jest.fn(),
|
||||
getDownloadArchiveExtension: jest.fn(),
|
||||
renameWinArchive: jest.fn(),
|
||||
getGitHubHttpHeaders: jest.fn().mockReturnValue({Accept: 'application/json'})
|
||||
}));
|
||||
|
||||
jest.mock('fs', () => ({
|
||||
...jest.requireActual('fs'),
|
||||
const real_fs_module = await import('fs');
|
||||
jest.unstable_mockModule('fs', () => ({
|
||||
...real_fs_module,
|
||||
default: {
|
||||
...real_fs_module.default,
|
||||
readdirSync: jest.fn(),
|
||||
existsSync: jest.fn()
|
||||
},
|
||||
readdirSync: jest.fn(),
|
||||
existsSync: jest.fn()
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const tc = await import('@actions/tool-cache');
|
||||
const http = await import('@actions/http-client');
|
||||
const fs = (await import('fs')).default;
|
||||
const util = await import('../../src/util.js');
|
||||
const {GraalVMCommunityDistribution, GraalVMDistribution} =
|
||||
await import('../../src/distributions/graalvm/installer.js');
|
||||
const {getJavaDistribution} =
|
||||
await import('../../src/distributions/distribution-factory.js');
|
||||
|
||||
import type {JavaInstallerOptions} from '../../src/distributions/base-models.js';
|
||||
|
||||
beforeAll(() => {
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
if (!jest.isMockFunction(http.HttpClient)) {
|
||||
throw new Error('HTTP client must be mocked in tests!');
|
||||
}
|
||||
|
||||
if (!jest.isMockFunction(tc.downloadTool)) {
|
||||
throw new Error('Tool cache downloadTool must be mocked in tests!');
|
||||
}
|
||||
|
||||
console.log('✅ All external dependencies are properly mocked');
|
||||
});
|
||||
|
||||
describe('GraalVMDistribution', () => {
|
||||
let distribution: GraalVMDistribution;
|
||||
let communityDistribution: GraalVMCommunityDistribution;
|
||||
let mockHttpClient: jest.Mocked<http.HttpClient>;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let distribution: InstanceType<typeof GraalVMDistribution>;
|
||||
let communityDistribution: InstanceType<typeof GraalVMCommunityDistribution>;
|
||||
let mockHttpClient: any;
|
||||
let spyCoreError: any;
|
||||
|
||||
const defaultOptions: JavaInstallerOptions = {
|
||||
version: '17',
|
||||
@@ -62,23 +125,28 @@ describe('GraalVMDistribution', () => {
|
||||
distribution = new GraalVMDistribution(defaultOptions);
|
||||
communityDistribution = new GraalVMCommunityDistribution(defaultOptions);
|
||||
|
||||
mockHttpClient = new http.HttpClient() as jest.Mocked<http.HttpClient>;
|
||||
mockHttpClient = new (http.HttpClient as any)();
|
||||
(distribution as any).http = mockHttpClient;
|
||||
(communityDistribution as any).http = mockHttpClient;
|
||||
|
||||
(util.getDownloadArchiveExtension as jest.Mock).mockReturnValue('tar.gz');
|
||||
// Default checksum sibling response for `${url}.sha256` requests made by
|
||||
// GraalVM (Oracle) and GraalVM EA. Individual tests override this when
|
||||
// they need to assert the exact URL/digest contract.
|
||||
mockHttpClient.get.mockResolvedValue({
|
||||
message: {statusCode: 200},
|
||||
readBody: jest.fn().mockResolvedValue('a'.repeat(64))
|
||||
});
|
||||
|
||||
(util.getDownloadArchiveExtension as jest.Mock<any>).mockReturnValue(
|
||||
'tar.gz'
|
||||
);
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
expect(jest.isMockFunction(http.HttpClient)).toBe(true);
|
||||
|
||||
expect(jest.isMockFunction(tc.downloadTool)).toBe(true);
|
||||
expect(jest.isMockFunction(tc.cacheDir)).toBe(true);
|
||||
|
||||
jest.restoreAllMocks();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
@@ -106,6 +174,29 @@ describe('GraalVMDistribution', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('setJavaDefault', () => {
|
||||
it('should set GRAALVM_HOME for Oracle GraalVM', () => {
|
||||
(distribution as any).setJavaDefault('17.0.5', '/cached/java/path');
|
||||
|
||||
expect(core.exportVariable).toHaveBeenCalledWith(
|
||||
'GRAALVM_HOME',
|
||||
'/cached/java/path'
|
||||
);
|
||||
});
|
||||
|
||||
it('should set GRAALVM_HOME for GraalVM Community', () => {
|
||||
(communityDistribution as any).setJavaDefault(
|
||||
'17.0.5',
|
||||
'/cached/java/path'
|
||||
);
|
||||
|
||||
expect(core.exportVariable).toHaveBeenCalledWith(
|
||||
'GRAALVM_HOME',
|
||||
'/cached/java/path'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('downloadTool', () => {
|
||||
const javaRelease = {
|
||||
version: '17.0.5',
|
||||
@@ -113,20 +204,24 @@ describe('GraalVMDistribution', () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
(tc.downloadTool as jest.Mock).mockResolvedValue('/tmp/archive.tar.gz');
|
||||
(tc.cacheDir as jest.Mock).mockResolvedValue('/cached/java/path');
|
||||
(tc.downloadTool as any).mockResolvedValue('/tmp/archive.tar.gz');
|
||||
(tc.cacheDir as any).mockResolvedValue('/cached/java/path');
|
||||
|
||||
(util.extractJdkFile as jest.Mock).mockResolvedValue('/tmp/extracted');
|
||||
(util.extractJdkFile as any).mockResolvedValue('/tmp/extracted');
|
||||
|
||||
// Mock renameWinArchive - it returns the same path (no renaming)
|
||||
(util.renameWinArchive as jest.Mock).mockImplementation((p: string) => p);
|
||||
(util.renameWinArchive as any).mockImplementation((p: string) => p);
|
||||
|
||||
(util.getDownloadArchiveExtension as jest.Mock).mockReturnValue('tar.gz');
|
||||
(util.getDownloadArchiveExtension as jest.Mock<any>).mockReturnValue(
|
||||
'tar.gz'
|
||||
);
|
||||
|
||||
// Mock fs.existsSync to return true for extracted path
|
||||
(fs.existsSync as jest.Mock).mockReturnValue(true);
|
||||
(fs.existsSync as jest.Mock<any>).mockReturnValue(true);
|
||||
|
||||
(fs.readdirSync as jest.Mock).mockReturnValue(['graalvm-jdk-17.0.5']);
|
||||
(fs.readdirSync as jest.Mock<any>).mockReturnValue([
|
||||
'graalvm-jdk-17.0.5'
|
||||
]);
|
||||
|
||||
jest
|
||||
.spyOn(distribution as any, 'getToolcacheVersionName')
|
||||
@@ -173,7 +268,7 @@ describe('GraalVMDistribution', () => {
|
||||
});
|
||||
|
||||
it('should throw error when extracted path does not exist', async () => {
|
||||
(fs.existsSync as jest.Mock).mockReturnValue(false);
|
||||
(fs.existsSync as jest.Mock<any>).mockReturnValue(false);
|
||||
|
||||
await expect(
|
||||
(distribution as any).downloadTool(javaRelease)
|
||||
@@ -187,8 +282,8 @@ describe('GraalVMDistribution', () => {
|
||||
});
|
||||
|
||||
it('should throw error when extracted directory is empty', async () => {
|
||||
(fs.existsSync as jest.Mock).mockReturnValue(true);
|
||||
(fs.readdirSync as jest.Mock).mockReturnValue([]);
|
||||
(fs.existsSync as jest.Mock<any>).mockReturnValue(true);
|
||||
(fs.readdirSync as jest.Mock<any>).mockReturnValue([]);
|
||||
|
||||
await expect(
|
||||
(distribution as any).downloadTool(javaRelease)
|
||||
@@ -203,7 +298,7 @@ describe('GraalVMDistribution', () => {
|
||||
|
||||
it('should handle download errors', async () => {
|
||||
const downloadError = new Error('Network error during download');
|
||||
(tc.downloadTool as jest.Mock).mockRejectedValue(downloadError);
|
||||
(tc.downloadTool as any).mockRejectedValue(downloadError);
|
||||
|
||||
await expect(
|
||||
(distribution as any).downloadTool(javaRelease)
|
||||
@@ -216,7 +311,7 @@ describe('GraalVMDistribution', () => {
|
||||
|
||||
it('should handle extraction errors', async () => {
|
||||
const extractError = new Error('Failed to extract archive');
|
||||
(util.extractJdkFile as jest.Mock).mockRejectedValue(extractError);
|
||||
(util.extractJdkFile as any).mockRejectedValue(extractError);
|
||||
|
||||
await expect(
|
||||
(distribution as any).downloadTool(javaRelease)
|
||||
@@ -229,8 +324,10 @@ describe('GraalVMDistribution', () => {
|
||||
|
||||
it('should handle different archive extensions', async () => {
|
||||
// Test with a .zip file
|
||||
(util.getDownloadArchiveExtension as jest.Mock).mockReturnValue('zip');
|
||||
(tc.downloadTool as jest.Mock).mockResolvedValue('/tmp/archive.zip');
|
||||
(util.getDownloadArchiveExtension as jest.Mock<any>).mockReturnValue(
|
||||
'zip'
|
||||
);
|
||||
(tc.downloadTool as any).mockResolvedValue('/tmp/archive.zip');
|
||||
|
||||
const zipRelease = {
|
||||
version: '17.0.5',
|
||||
@@ -309,7 +406,7 @@ describe('GraalVMDistribution', () => {
|
||||
it('should construct correct URL for specific version', async () => {
|
||||
const mockResponse = {
|
||||
message: {statusCode: 200}
|
||||
} as http.HttpClientResponse;
|
||||
} as any;
|
||||
mockHttpClient.head.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await (distribution as any).findPackageForDownload(
|
||||
@@ -318,22 +415,35 @@ describe('GraalVMDistribution', () => {
|
||||
|
||||
expect(result).toEqual({
|
||||
url: 'https://download.oracle.com/graalvm/17/archive/graalvm-jdk-17.0.5_linux-x64_bin.tar.gz',
|
||||
version: '17.0.5'
|
||||
version: '17.0.5',
|
||||
checksum: {
|
||||
algorithm: 'sha256',
|
||||
value: 'a'.repeat(64),
|
||||
source:
|
||||
'https://download.oracle.com/graalvm/17/archive/graalvm-jdk-17.0.5_linux-x64_bin.tar.gz.sha256'
|
||||
}
|
||||
});
|
||||
expect(mockHttpClient.head).toHaveBeenCalledWith(result.url);
|
||||
expect(mockHttpClient.get).toHaveBeenCalledWith(`${result.url}.sha256`);
|
||||
});
|
||||
|
||||
it('should construct correct URL for major version (latest)', async () => {
|
||||
const mockResponse = {
|
||||
message: {statusCode: 200}
|
||||
} as http.HttpClientResponse;
|
||||
} as any;
|
||||
mockHttpClient.head.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await (distribution as any).findPackageForDownload('21');
|
||||
|
||||
expect(result).toEqual({
|
||||
url: 'https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz',
|
||||
version: '21'
|
||||
version: '21',
|
||||
checksum: {
|
||||
algorithm: 'sha256',
|
||||
value: 'a'.repeat(64),
|
||||
source:
|
||||
'https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz.sha256'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -351,6 +461,67 @@ describe('GraalVMDistribution', () => {
|
||||
);
|
||||
});
|
||||
|
||||
describe('latest alias', () => {
|
||||
it('resolves the newest major version from the Adoptium API', async () => {
|
||||
const latestDistribution = new GraalVMDistribution({
|
||||
...defaultOptions,
|
||||
version: 'latest'
|
||||
});
|
||||
(latestDistribution as any).http = mockHttpClient;
|
||||
jest
|
||||
.spyOn(latestDistribution, 'getPlatform')
|
||||
.mockReturnValue('linux');
|
||||
mockHttpClient.getJson.mockResolvedValue({
|
||||
statusCode: 200,
|
||||
result: {most_recent_feature_release: 25},
|
||||
headers: {}
|
||||
});
|
||||
mockHttpClient.head.mockResolvedValue({
|
||||
message: {statusCode: 200}
|
||||
});
|
||||
|
||||
const result = await (
|
||||
latestDistribution as any
|
||||
).findPackageForDownload('x');
|
||||
|
||||
expect(result).toEqual({
|
||||
url: 'https://download.oracle.com/graalvm/25/latest/graalvm-jdk-25_linux-x64_bin.tar.gz',
|
||||
version: '25',
|
||||
checksum: {
|
||||
algorithm: 'sha256',
|
||||
value: 'a'.repeat(64),
|
||||
source:
|
||||
'https://download.oracle.com/graalvm/25/latest/graalvm-jdk-25_linux-x64_bin.tar.gz.sha256'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('throws an actionable error when the latest major is not yet available', async () => {
|
||||
const latestDistribution = new GraalVMDistribution({
|
||||
...defaultOptions,
|
||||
version: 'latest'
|
||||
});
|
||||
(latestDistribution as any).http = mockHttpClient;
|
||||
jest
|
||||
.spyOn(latestDistribution, 'getPlatform')
|
||||
.mockReturnValue('linux');
|
||||
mockHttpClient.getJson.mockResolvedValue({
|
||||
statusCode: 200,
|
||||
result: {most_recent_feature_release: 25},
|
||||
headers: {}
|
||||
});
|
||||
mockHttpClient.head.mockResolvedValue({
|
||||
message: {statusCode: 404}
|
||||
});
|
||||
|
||||
await expect(
|
||||
(latestDistribution as any).findPackageForDownload('x')
|
||||
).rejects.toThrow(
|
||||
/is not yet available for the GraalVM distribution/
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw error for JDK versions less than 17', async () => {
|
||||
await expect(
|
||||
(distribution as any).findPackageForDownload('11')
|
||||
@@ -374,7 +545,7 @@ describe('GraalVMDistribution', () => {
|
||||
it('should throw error when file not found (404)', async () => {
|
||||
const mockResponse = {
|
||||
message: {statusCode: 404}
|
||||
} as http.HttpClientResponse;
|
||||
} as any;
|
||||
mockHttpClient.head.mockResolvedValue(mockResponse);
|
||||
|
||||
// Verify the error is thrown with the expected message
|
||||
@@ -395,7 +566,7 @@ describe('GraalVMDistribution', () => {
|
||||
it('should throw error for unauthorized access (401)', async () => {
|
||||
const mockResponse = {
|
||||
message: {statusCode: 401}
|
||||
} as http.HttpClientResponse;
|
||||
} as any;
|
||||
mockHttpClient.head.mockResolvedValue(mockResponse);
|
||||
|
||||
await expect(
|
||||
@@ -408,7 +579,7 @@ describe('GraalVMDistribution', () => {
|
||||
it('should throw error for forbidden access (403)', async () => {
|
||||
const mockResponse = {
|
||||
message: {statusCode: 403}
|
||||
} as http.HttpClientResponse;
|
||||
} as any;
|
||||
mockHttpClient.head.mockResolvedValue(mockResponse);
|
||||
|
||||
await expect(
|
||||
@@ -424,7 +595,7 @@ describe('GraalVMDistribution', () => {
|
||||
statusCode: 500,
|
||||
statusMessage: 'Internal Server Error'
|
||||
}
|
||||
} as http.HttpClientResponse;
|
||||
} as any;
|
||||
mockHttpClient.head.mockResolvedValue(mockResponse);
|
||||
|
||||
await expect(
|
||||
@@ -437,7 +608,7 @@ describe('GraalVMDistribution', () => {
|
||||
it('should throw error for other HTTP errors without status message', async () => {
|
||||
const mockResponse = {
|
||||
message: {statusCode: 500}
|
||||
} as http.HttpClientResponse;
|
||||
} as any;
|
||||
mockHttpClient.head.mockResolvedValue(mockResponse);
|
||||
|
||||
await expect(
|
||||
@@ -493,13 +664,20 @@ describe('GraalVMDistribution', () => {
|
||||
|
||||
expect(result).toEqual({
|
||||
url: 'https://example.com/download/graalvm-jdk-23_linux-x64_bin.tar.gz',
|
||||
version: '23-ea-20240716'
|
||||
version: '23-ea-20240716',
|
||||
checksum: {
|
||||
algorithm: 'sha256',
|
||||
value: 'a'.repeat(64),
|
||||
source:
|
||||
'https://example.com/download/graalvm-jdk-23_linux-x64_bin.tar.gz.sha256'
|
||||
}
|
||||
});
|
||||
|
||||
expect(mockHttpClient.getJson).toHaveBeenCalledWith(
|
||||
'https://api.github.com/repos/graalvm/oracle-graalvm-ea-builds/contents/versions/23-ea.json?ref=main',
|
||||
{Accept: 'application/json'}
|
||||
);
|
||||
expect(mockHttpClient.get).toHaveBeenCalledWith(`${result.url}.sha256`);
|
||||
});
|
||||
|
||||
it('should throw error when no latest EA version found', async () => {
|
||||
@@ -713,7 +891,7 @@ describe('GraalVMDistribution', () => {
|
||||
}
|
||||
];
|
||||
|
||||
let fetchEASpy: jest.SpyInstance;
|
||||
let fetchEASpy: any;
|
||||
|
||||
beforeEach(() => {
|
||||
fetchEASpy = jest.spyOn(distribution as any, 'fetchEAJson');
|
||||
@@ -732,8 +910,15 @@ describe('GraalVMDistribution', () => {
|
||||
expect(fetchEASpy).toHaveBeenCalledWith('23-ea');
|
||||
expect(result).toEqual({
|
||||
url: 'https://example.com/download/graalvm-jdk-23_linux-x64_bin.tar.gz',
|
||||
version: '23-ea-20240716'
|
||||
version: '23-ea-20240716',
|
||||
checksum: {
|
||||
algorithm: 'sha256',
|
||||
value: 'a'.repeat(64),
|
||||
source:
|
||||
'https://example.com/download/graalvm-jdk-23_linux-x64_bin.tar.gz.sha256'
|
||||
}
|
||||
});
|
||||
expect(mockHttpClient.get).toHaveBeenCalledWith(`${result.url}.sha256`);
|
||||
|
||||
// Verify debug logging
|
||||
expect(core.debug).toHaveBeenCalledWith('Searching for EA build: 23-ea');
|
||||
@@ -832,7 +1017,13 @@ describe('GraalVMDistribution', () => {
|
||||
|
||||
expect(result).toEqual({
|
||||
url: 'https://example.com/download/graalvm-jdk-23_linux-aarch64_bin.tar.gz',
|
||||
version: '23-ea-20240716'
|
||||
version: '23-ea-20240716',
|
||||
checksum: {
|
||||
algorithm: 'sha256',
|
||||
value: 'a'.repeat(64),
|
||||
source:
|
||||
'https://example.com/download/graalvm-jdk-23_linux-aarch64_bin.tar.gz.sha256'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -932,7 +1123,7 @@ describe('GraalVMDistribution', () => {
|
||||
|
||||
const mockResponse = {
|
||||
message: {statusCode: 200}
|
||||
} as http.HttpClientResponse;
|
||||
} as any;
|
||||
mockHttpClient.head.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await (distribution as any).findPackageForDownload('17');
|
||||
@@ -960,7 +1151,7 @@ describe('GraalVMDistribution', () => {
|
||||
|
||||
const mockResponse = {
|
||||
message: {statusCode: 200}
|
||||
} as http.HttpClientResponse;
|
||||
} as any;
|
||||
mockHttpClient.head.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await (distribution as any).findPackageForDownload('17');
|
||||
@@ -1007,6 +1198,80 @@ describe('GraalVMDistribution', () => {
|
||||
url: 'https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-21.0.2/graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz',
|
||||
version: '21.0.2'
|
||||
});
|
||||
// The asset had no `digest` field, so no checksum should be attached,
|
||||
// and the checksum sibling-URL fetch path (used by Oracle GraalVM)
|
||||
// must not be consulted for GraalVM Community.
|
||||
expect(result.checksum).toBeUndefined();
|
||||
expect(mockHttpClient.get).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('strips the `sha256:` prefix from a GitHub release asset digest', async () => {
|
||||
const digest = 'd'.repeat(64);
|
||||
mockHttpClient.getJson.mockResolvedValue({
|
||||
result: [
|
||||
{
|
||||
draft: false,
|
||||
prerelease: false,
|
||||
assets: [
|
||||
{
|
||||
name: 'graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz',
|
||||
browser_download_url:
|
||||
'https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-21.0.2/graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz',
|
||||
digest: `sha256:${digest}`
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
statusCode: 200,
|
||||
headers: {}
|
||||
});
|
||||
|
||||
const result = await (
|
||||
communityDistribution as any
|
||||
).findPackageForDownload('21.0.2');
|
||||
|
||||
expect(result.checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: digest,
|
||||
source:
|
||||
'https://api.github.com/repos/graalvm/graalvm-ce-builds/releases?per_page=100'
|
||||
});
|
||||
// The digest came from the release listing itself, so no additional
|
||||
// HTTP request should be made to resolve the checksum.
|
||||
expect(mockHttpClient.get).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('safely skips a missing or malformed release asset digest', async () => {
|
||||
mockHttpClient.getJson.mockResolvedValue({
|
||||
result: [
|
||||
{
|
||||
draft: false,
|
||||
prerelease: false,
|
||||
assets: [
|
||||
{
|
||||
name: 'graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz',
|
||||
browser_download_url:
|
||||
'https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-21.0.2/graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz',
|
||||
digest: 'md5:not-a-sha256-digest'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
statusCode: 200,
|
||||
headers: {}
|
||||
});
|
||||
|
||||
const result = await (
|
||||
communityDistribution as any
|
||||
).findPackageForDownload('21.0.2');
|
||||
|
||||
expect(result.checksum).toBeUndefined();
|
||||
expect(mockHttpClient.get).not.toHaveBeenCalled();
|
||||
expect(core.debug).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'No authoritative sha256 digest is available for graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz'
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('should resolve the latest GraalVM Community release for a major version', async () => {
|
||||
@@ -1049,6 +1314,60 @@ describe('GraalVMDistribution', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('resolves latest to the newest GA across all Community majors without calling Adoptium', async () => {
|
||||
const latestCommunity = new GraalVMCommunityDistribution({
|
||||
...defaultOptions,
|
||||
version: 'latest'
|
||||
});
|
||||
(latestCommunity as any).http = mockHttpClient;
|
||||
jest.spyOn(latestCommunity, 'getPlatform').mockReturnValue('linux');
|
||||
|
||||
mockHttpClient.getJson.mockResolvedValue({
|
||||
result: [
|
||||
{
|
||||
draft: false,
|
||||
prerelease: false,
|
||||
assets: [
|
||||
{
|
||||
name: 'graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz',
|
||||
browser_download_url:
|
||||
'https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-21.0.2/graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
draft: false,
|
||||
prerelease: false,
|
||||
assets: [
|
||||
{
|
||||
name: 'graalvm-community-jdk-24.0.1_linux-x64_bin.tar.gz',
|
||||
browser_download_url:
|
||||
'https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-24.0.1/graalvm-community-jdk-24.0.1_linux-x64_bin.tar.gz'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
statusCode: 200,
|
||||
headers: {}
|
||||
});
|
||||
|
||||
const result = await (latestCommunity as any).findPackageForDownload(
|
||||
'x'
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
url: 'https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-24.0.1/graalvm-community-jdk-24.0.1_linux-x64_bin.tar.gz',
|
||||
version: '24.0.1'
|
||||
});
|
||||
// The Community release list is authoritative, so the Adoptium
|
||||
// most_recent_feature_release endpoint must not be consulted.
|
||||
expect(mockHttpClient.getJson).toHaveBeenCalledTimes(1);
|
||||
expect(mockHttpClient.getJson).toHaveBeenCalledWith(
|
||||
expect.stringContaining('graalvm-ce-builds/releases'),
|
||||
expect.anything()
|
||||
);
|
||||
});
|
||||
|
||||
it('should reject GraalVM Community early access requests', async () => {
|
||||
(communityDistribution as any).stable = false;
|
||||
|
||||
@@ -1084,8 +1403,11 @@ describe('distribution factory', () => {
|
||||
checkLatest: false
|
||||
};
|
||||
|
||||
it('should map graalvm-community to the community installer', () => {
|
||||
const community = getJavaDistribution('graalvm-community', defaultOptions);
|
||||
it('should map graalvm-community to the community installer', async () => {
|
||||
const community = await getJavaDistribution(
|
||||
'graalvm-community',
|
||||
defaultOptions
|
||||
);
|
||||
|
||||
expect(community).toBeInstanceOf(GraalVMCommunityDistribution);
|
||||
});
|
||||
|
||||
@@ -1,14 +1,67 @@
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import https from 'https';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import {JetBrainsDistribution} from '../../src/distributions/jetbrains/installer';
|
||||
import {HttpClient, HttpClientResponse} from '@actions/http-client';
|
||||
import type {IncomingMessage} from 'http';
|
||||
import {Readable} from 'stream';
|
||||
|
||||
import manifestData from '../data/jetbrains.json';
|
||||
import manifestData from '../data/jetbrains.json' with {type: 'json'};
|
||||
import os from 'os';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const {JetBrainsDistribution} =
|
||||
await import('../../src/distributions/jetbrains/installer.js');
|
||||
const {RetryingHttpClient} = await import('../../src/retrying-http-client.js');
|
||||
|
||||
function response(
|
||||
statusCode: number,
|
||||
body = '',
|
||||
headers: IncomingMessage['headers'] = {}
|
||||
): HttpClientResponse {
|
||||
const message = Readable.from([Buffer.from(body)]) as IncomingMessage;
|
||||
message.statusCode = statusCode;
|
||||
message.headers = headers;
|
||||
return new HttpClientResponse(message);
|
||||
}
|
||||
|
||||
describe('getAvailableVersions', () => {
|
||||
let spyHttpClient: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyHttpClient: any;
|
||||
let spyCoreError: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
@@ -19,7 +72,7 @@ describe('getAvailableVersions', () => {
|
||||
});
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -31,11 +84,17 @@ describe('getAvailableVersions', () => {
|
||||
|
||||
it('load available versions', async () => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
spyHttpClient.mockReturnValueOnce({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: manifestData as any
|
||||
});
|
||||
spyHttpClient
|
||||
.mockReturnValueOnce({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: manifestData as any
|
||||
})
|
||||
.mockReturnValue({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: []
|
||||
});
|
||||
|
||||
const distribution = new JetBrainsDistribution({
|
||||
version: '17',
|
||||
@@ -50,9 +109,66 @@ describe('getAvailableVersions', () => {
|
||||
os.platform() === 'win32' ? manifestData.length : manifestData.length + 2;
|
||||
expect(availableVersions.length).toBe(length);
|
||||
}, 10_000);
|
||||
|
||||
it('retries a GitHub rate limit using Retry-After', async () => {
|
||||
spyHttpClient.mockRestore();
|
||||
const sleep = jest.fn(async () => undefined);
|
||||
const requestRaw = jest
|
||||
.spyOn(HttpClient.prototype, 'requestRaw')
|
||||
.mockResolvedValueOnce(response(429, '', {'retry-after': '2'}))
|
||||
.mockResolvedValueOnce(response(200, '[]'))
|
||||
.mockResolvedValueOnce(response(200))
|
||||
.mockResolvedValueOnce(response(200));
|
||||
const distribution = new JetBrainsDistribution({
|
||||
version: '17',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
distribution['http'] = new RetryingHttpClient('test', {
|
||||
sleep,
|
||||
random: () => 0
|
||||
});
|
||||
|
||||
const availableVersions = await distribution['getAvailableVersions']();
|
||||
|
||||
expect(availableVersions).toHaveLength(2);
|
||||
expect(requestRaw).toHaveBeenCalledTimes(4);
|
||||
expect(requestRaw.mock.calls[0][0].options.path).toBe(
|
||||
requestRaw.mock.calls[1][0].options.path
|
||||
);
|
||||
expect(requestRaw.mock.calls[0][0].options.path).toContain(
|
||||
'/repos/JetBrains/JetBrainsRuntime/releases'
|
||||
);
|
||||
expect(sleep).toHaveBeenCalledWith(2000);
|
||||
expect(core.info).toHaveBeenCalledWith(
|
||||
'Request attempt 1 of 4 failed (HTTP 429); retrying in 2000 ms'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findPackageForDownload', () => {
|
||||
let spyHttpClientGet: any;
|
||||
|
||||
const JETBRAINS_CHECKSUM = 'c'.repeat(128);
|
||||
|
||||
beforeEach(() => {
|
||||
// Every resolved release fetches `${url}.checksum` (sha512, GNU
|
||||
// `<hex> <filename>` format); stub it so tests never reach the real
|
||||
// network, except the dedicated 'version %s can be downloaded' test
|
||||
// below which intentionally exercises real HTTPS HEAD requests.
|
||||
spyHttpClientGet = jest
|
||||
.spyOn(HttpClient.prototype, 'get')
|
||||
.mockResolvedValue({
|
||||
message: {statusCode: 200},
|
||||
readBody: async () => `${JETBRAINS_CHECKSUM} jbrsdk.tar.gz\n`
|
||||
} as any);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it.each([
|
||||
['17', '17.0.11+1207.24'],
|
||||
['11.0', '11.0.16+2043.64'],
|
||||
@@ -136,4 +252,72 @@ describe('findPackageForDownload', () => {
|
||||
/No matching version found for SemVer */
|
||||
);
|
||||
});
|
||||
|
||||
it('fetches the authoritative sha512 checksum only for the resolved version', async () => {
|
||||
const distribution = new JetBrainsDistribution({
|
||||
version: '21',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
distribution['getAvailableVersions'] = async () => manifestData as any;
|
||||
|
||||
const result = await distribution['findPackageForDownload']('21');
|
||||
|
||||
expect(result.checksum).toEqual({
|
||||
algorithm: 'sha512',
|
||||
value: JETBRAINS_CHECKSUM,
|
||||
source: `${result.url}.checksum`
|
||||
});
|
||||
// Only the single resolved/winning version's checksum is requested,
|
||||
// not one per candidate considered during version resolution.
|
||||
expect(spyHttpClientGet).toHaveBeenCalledWith(`${result.url}.checksum`);
|
||||
expect(spyHttpClientGet).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('parses only the first whitespace-delimited token from the GNU checksum payload', async () => {
|
||||
spyHttpClientGet.mockResolvedValue({
|
||||
message: {statusCode: 200},
|
||||
readBody: async () => `${JETBRAINS_CHECKSUM} jbrsdk-21.tar.gz\n`
|
||||
} as any);
|
||||
|
||||
const distribution = new JetBrainsDistribution({
|
||||
version: '21',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
distribution['getAvailableVersions'] = async () => manifestData as any;
|
||||
|
||||
const result = await distribution['findPackageForDownload']('21');
|
||||
|
||||
expect(result.checksum?.value).toBe(JETBRAINS_CHECKSUM);
|
||||
});
|
||||
|
||||
it('falls back to a sha256 checksum for older JBR builds that only publish one', async () => {
|
||||
// Older JBR 11 builds (e.g. jbrsdk_nomod-11_0_16-*-b2043.64.tar.gz) publish
|
||||
// a SHA-256 digest at the generic `.checksum` sibling instead of SHA-512.
|
||||
const sha256Checksum = 'a'.repeat(64);
|
||||
spyHttpClientGet.mockResolvedValue({
|
||||
message: {statusCode: 200},
|
||||
readBody: async () =>
|
||||
`${sha256Checksum} jbrsdk_nomod-11_0_16-osx-x64-b2043.64.tar.gz\n`
|
||||
} as any);
|
||||
|
||||
const distribution = new JetBrainsDistribution({
|
||||
version: '21',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
distribution['getAvailableVersions'] = async () => manifestData as any;
|
||||
|
||||
const result = await distribution['findPackageForDownload']('21');
|
||||
|
||||
expect(result.checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: sha256Checksum,
|
||||
source: `${result.url}.checksum`
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
import {KonaDistribution} from '../../src/distributions/kona/installer.js';
|
||||
|
||||
import manifestData from '../data/kona.json' with {type: 'json'};
|
||||
|
||||
function mockDistr(
|
||||
version: string,
|
||||
os: string,
|
||||
arch: string,
|
||||
packageType: string
|
||||
): KonaDistribution {
|
||||
const distribution = new KonaDistribution({
|
||||
version: version,
|
||||
architecture: arch,
|
||||
packageType: packageType,
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
distribution['getOs'] = () => os;
|
||||
distribution['fetchReleaseInfo'] = async () => manifestData;
|
||||
|
||||
return distribution;
|
||||
}
|
||||
|
||||
describe('Check getAvailableReleases', () => {
|
||||
it.each([
|
||||
['8', 'linux', 'aarch64', 'linux-aarch64'],
|
||||
['8.0.20', 'macos', 'x86_64', 'macosx-x86_64'],
|
||||
['11', 'linux', 'x86_64', 'linux-x86_64'],
|
||||
['11.0.25', 'macos', 'aarch64', 'macosx-aarch64'],
|
||||
['17.0.13', 'windows', 'x86_64', 'windows-x86_64'],
|
||||
['21.0.5', 'linux', 'x86_64', 'linux-x86_64'],
|
||||
['25', 'linux', 'aarch64', 'linux-aarch64'],
|
||||
['25.0.3', 'macos', 'x86_64', 'macosx-x86_64']
|
||||
])(
|
||||
'should get releases with the specified version "%s", OS "%s" and arch "%s"',
|
||||
async (
|
||||
version: string,
|
||||
os: string,
|
||||
arch: string,
|
||||
expectedPattern: string
|
||||
) => {
|
||||
const distribution = mockDistr(version, os, arch, 'jdk');
|
||||
|
||||
const releases = await distribution['getAvailableReleases']();
|
||||
expect(releases).not.toBeNull();
|
||||
expect(releases.length).toBe(5);
|
||||
releases.forEach(release =>
|
||||
expect(release.downloadUrl).toContain(expectedPattern)
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('Check findPackageForDownload', () => {
|
||||
it.each([
|
||||
[
|
||||
'8',
|
||||
'linux',
|
||||
'aarch64',
|
||||
'https://github.com/Tencent/TencentKona-8/releases/download/8.0.20-GA/TencentKona8.0.20.b1_jdk_linux-aarch64_8u432.tar.gz'
|
||||
],
|
||||
[
|
||||
'8.0.20',
|
||||
'linux',
|
||||
'x86_64',
|
||||
'https://github.com/Tencent/TencentKona-8/releases/download/8.0.20-GA/TencentKona8.0.20.b1_jdk_linux-x86_64_8u432.tar.gz'
|
||||
],
|
||||
[
|
||||
'8.0.20',
|
||||
'macos',
|
||||
'aarch64',
|
||||
'https://github.com/Tencent/TencentKona-8/releases/download/8.0.20-GA/TencentKona8.0.20.b1_jdk_macosx-aarch64_8u432_notarized.tar.gz'
|
||||
],
|
||||
[
|
||||
'8.0.20',
|
||||
'macos',
|
||||
'x86_64',
|
||||
'https://github.com/Tencent/TencentKona-8/releases/download/8.0.20-GA/TencentKona8.0.20.b1_jdk_macosx-x86_64_8u432_notarized.tar.gz'
|
||||
],
|
||||
[
|
||||
'8.0.20',
|
||||
'windows',
|
||||
'x86_64',
|
||||
'https://github.com/Tencent/TencentKona-8/releases/download/8.0.20-GA/TencentKona8.0.20.b1_jdk_windows-x86_64_8u432_signed.zip'
|
||||
],
|
||||
|
||||
[
|
||||
'11',
|
||||
'linux',
|
||||
'aarch64',
|
||||
'https://github.com/Tencent/TencentKona-11/releases/download/kona11.0.25/TencentKona-11.0.25.b1-jdk_linux-aarch64.tar.gz'
|
||||
],
|
||||
[
|
||||
'11.0.25',
|
||||
'linux',
|
||||
'x86_64',
|
||||
'https://github.com/Tencent/TencentKona-11/releases/download/kona11.0.25/TencentKona-11.0.25.b1-jdk_linux-x86_64.tar.gz'
|
||||
],
|
||||
[
|
||||
'11.0.25',
|
||||
'macos',
|
||||
'aarch64',
|
||||
'https://github.com/Tencent/TencentKona-11/releases/download/kona11.0.25/TencentKona-11.0.25.b1_jdk_macosx-aarch64_notarized.tar.gz'
|
||||
],
|
||||
[
|
||||
'11.0.25',
|
||||
'macos',
|
||||
'x86_64',
|
||||
'https://github.com/Tencent/TencentKona-11/releases/download/kona11.0.25/TencentKona-11.0.25.b1_jdk_macosx-x86_64_notarized.tar.gz'
|
||||
],
|
||||
[
|
||||
'11.0.25',
|
||||
'windows',
|
||||
'x86_64',
|
||||
'https://github.com/Tencent/TencentKona-11/releases/download/kona11.0.25/TencentKona-11.0.25.b1_jdk_windows-x86_64_signed.zip'
|
||||
],
|
||||
|
||||
[
|
||||
'17',
|
||||
'linux',
|
||||
'aarch64',
|
||||
'https://github.com/Tencent/TencentKona-17/releases/download/TencentKona-17.0.13/TencentKona-17.0.13.b1-jdk_linux-aarch64.tar.gz'
|
||||
],
|
||||
[
|
||||
'17.0.13',
|
||||
'linux',
|
||||
'x86_64',
|
||||
'https://github.com/Tencent/TencentKona-17/releases/download/TencentKona-17.0.13/TencentKona-17.0.13.b1-jdk_linux-x86_64.tar.gz'
|
||||
],
|
||||
[
|
||||
'17.0.13',
|
||||
'macos',
|
||||
'aarch64',
|
||||
'https://github.com/Tencent/TencentKona-17/releases/download/TencentKona-17.0.13/TencentKona-17.0.13.b1_jdk_macosx-aarch64_notarized.tar.gz'
|
||||
],
|
||||
[
|
||||
'17.0.13',
|
||||
'macos',
|
||||
'x86_64',
|
||||
'https://github.com/Tencent/TencentKona-17/releases/download/TencentKona-17.0.13/TencentKona-17.0.13.b1_jdk_macosx-x86_64_notarized.tar.gz'
|
||||
],
|
||||
[
|
||||
'17.0.13',
|
||||
'windows',
|
||||
'x86_64',
|
||||
'https://github.com/Tencent/TencentKona-17/releases/download/TencentKona-17.0.13/TencentKona-17.0.13.b1_jdk_windows-x86_64_signed.zip'
|
||||
],
|
||||
|
||||
[
|
||||
'21',
|
||||
'linux',
|
||||
'aarch64',
|
||||
'https://github.com/Tencent/TencentKona-21/releases/download/TencentKona-21.0.5/TencentKona-21.0.5.b1-jdk_linux-aarch64.tar.gz'
|
||||
],
|
||||
[
|
||||
'21.0.5',
|
||||
'linux',
|
||||
'x86_64',
|
||||
'https://github.com/Tencent/TencentKona-21/releases/download/TencentKona-21.0.5/TencentKona-21.0.5.b1-jdk_linux-x86_64.tar.gz'
|
||||
],
|
||||
[
|
||||
'21.0.5',
|
||||
'macos',
|
||||
'aarch64',
|
||||
'https://github.com/Tencent/TencentKona-21/releases/download/TencentKona-21.0.5/TencentKona-21.0.5.b1_jdk_macosx-aarch64_notarized.tar.gz'
|
||||
],
|
||||
[
|
||||
'21.0.5',
|
||||
'macos',
|
||||
'x86_64',
|
||||
'https://github.com/Tencent/TencentKona-21/releases/download/TencentKona-21.0.5/TencentKona-21.0.5.b1_jdk_macosx-x86_64_notarized.tar.gz'
|
||||
],
|
||||
[
|
||||
'21.0.5',
|
||||
'windows',
|
||||
'x86_64',
|
||||
'https://github.com/Tencent/TencentKona-21/releases/download/TencentKona-21.0.5/TencentKona-21.0.5.b1_jdk_windows-x86_64_signed.zip'
|
||||
],
|
||||
|
||||
[
|
||||
'25',
|
||||
'linux',
|
||||
'aarch64',
|
||||
'https://github.com/Tencent/TencentKona-25/releases/download/TencentKona-25.0.3/TencentKona-25.0.3.b1-jdk_linux-aarch64.tar.gz'
|
||||
],
|
||||
[
|
||||
'25.0.3',
|
||||
'linux',
|
||||
'x86_64',
|
||||
'https://github.com/Tencent/TencentKona-25/releases/download/TencentKona-25.0.3/TencentKona-25.0.3.b1-jdk_linux-x86_64.tar.gz'
|
||||
],
|
||||
[
|
||||
'25.0.3',
|
||||
'macos',
|
||||
'aarch64',
|
||||
'https://github.com/Tencent/TencentKona-25/releases/download/TencentKona-25.0.3/TencentKona-25.0.3.b1_jdk_macosx-aarch64_notarized.tar.gz'
|
||||
],
|
||||
[
|
||||
'25.0.3',
|
||||
'macos',
|
||||
'x86_64',
|
||||
'https://github.com/Tencent/TencentKona-25/releases/download/TencentKona-25.0.3/TencentKona-25.0.3.b1_jdk_macosx-x86_64_notarized.tar.gz'
|
||||
],
|
||||
[
|
||||
'25.0.3',
|
||||
'windows',
|
||||
'x86_64',
|
||||
'https://github.com/Tencent/TencentKona-25/releases/download/TencentKona-25.0.3/TencentKona-25.0.3.b1_jdk_windows-x86_64_signed.zip'
|
||||
]
|
||||
])(
|
||||
'should return the download URL with the specified version "%s", OS "%s" and arch "%s"',
|
||||
async (version: string, os: string, arch: string, expectedUrl: string) => {
|
||||
const distribution = mockDistr(version, os, arch, 'jdk');
|
||||
|
||||
const availableRelease =
|
||||
await distribution['findPackageForDownload'](version);
|
||||
expect(availableRelease).not.toBeNull();
|
||||
expect(availableRelease.url).toBe(expectedUrl);
|
||||
if (availableRelease.checksum) {
|
||||
expect(availableRelease.checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: expect.stringMatching(/^[a-f0-9]{64}$/),
|
||||
source: 'https://tencent.github.io/konajdk/releases/kona-v1.json'
|
||||
});
|
||||
} else {
|
||||
expect(version).toBe('8.0.20');
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('No release is found', () => {
|
||||
it.each([
|
||||
['8', 'linux', 'x86'],
|
||||
['8.0.0', 'linux', 'x86_64'],
|
||||
['11', 'linux', 'ppc64'],
|
||||
['17', 'solaris', 'x86_64'],
|
||||
['17', 'windows', 'aarch64'],
|
||||
['22', 'macos', 'x86_64']
|
||||
])(
|
||||
`should throw an error due to no release with the specified version "%s", os "%s" and arch "%s"`,
|
||||
async (version: string, os: string, arch: string) => {
|
||||
const distribution = mockDistr(version, os, arch, 'jdk');
|
||||
|
||||
await expect(
|
||||
distribution['findPackageForDownload'](version)
|
||||
).rejects.toThrow(
|
||||
`No Kona release for the specified version "${version}" on OS "${os}" and arch "${arch}".`
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('The package type must be jdk', () => {
|
||||
it('should throw an error due to the specified package type is not jdk', async () => {
|
||||
const version = '8.0.20';
|
||||
const os = 'linux';
|
||||
const arch = 'x86_64';
|
||||
const distribution = mockDistr(version, os, arch, 'jre');
|
||||
|
||||
await expect(
|
||||
distribution['findPackageForDownload'](version)
|
||||
).rejects.toThrow('Kona provides jdk only');
|
||||
});
|
||||
});
|
||||
@@ -1,17 +1,56 @@
|
||||
import {LibericaDistributions} from '../../src/distributions/liberica/installer';
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import type {
|
||||
ArchitectureOptions,
|
||||
LibericaVersion
|
||||
} from '../../src/distributions/liberica/models';
|
||||
} from '../../src/distributions/liberica/models.js';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import os from 'os';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import manifestData from '../data/liberica.json';
|
||||
import manifestData from '../data/liberica.json' with {type: 'json'};
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const {LibericaDistributions} =
|
||||
await import('../../src/distributions/liberica/installer.js');
|
||||
|
||||
describe('getAvailableVersions', () => {
|
||||
let spyHttpClient: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyHttpClient: any;
|
||||
let spyCoreError: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
@@ -22,7 +61,7 @@ describe('getAvailableVersions', () => {
|
||||
});
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -184,7 +223,7 @@ describe('getArchitectureOptions', () => {
|
||||
});
|
||||
|
||||
describe('findPackageForDownload', () => {
|
||||
let distribution: LibericaDistributions;
|
||||
let distribution: InstanceType<typeof LibericaDistributions>;
|
||||
|
||||
beforeEach(() => {
|
||||
distribution = new LibericaDistributions({
|
||||
|
||||
@@ -1,17 +1,56 @@
|
||||
import {LibericaDistributions} from '../../src/distributions/liberica/installer';
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import type {
|
||||
ArchitectureOptions,
|
||||
LibericaVersion
|
||||
} from '../../src/distributions/liberica/models';
|
||||
} from '../../src/distributions/liberica/models.js';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import os from 'os';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import manifestData from '../data/liberica-linux.json';
|
||||
import manifestData from '../data/liberica-linux.json' with {type: 'json'};
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const {LibericaDistributions} =
|
||||
await import('../../src/distributions/liberica/installer.js');
|
||||
|
||||
describe('getAvailableVersions', () => {
|
||||
let spyHttpClient: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyHttpClient: any;
|
||||
let spyCoreError: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
@@ -22,7 +61,7 @@ describe('getAvailableVersions', () => {
|
||||
});
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -184,7 +223,7 @@ describe('getArchitectureOptions', () => {
|
||||
});
|
||||
|
||||
describe('findPackageForDownload', () => {
|
||||
let distribution: LibericaDistributions;
|
||||
let distribution: InstanceType<typeof LibericaDistributions>;
|
||||
|
||||
beforeEach(() => {
|
||||
distribution = new LibericaDistributions({
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
import {jest, describe, it, expect, beforeEach, afterEach} from '@jest/globals';
|
||||
import type {
|
||||
ArchitectureOptions,
|
||||
NikVersion
|
||||
} from '../../src/distributions/liberica-nik/models.js';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
|
||||
import manifestData from '../data/liberica-nik.json' with {type: 'json'};
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const {LibericaNikDistributions} =
|
||||
await import('../../src/distributions/liberica-nik/installer.js');
|
||||
|
||||
const ADDITIONAL_PARAMS =
|
||||
'&installation-type=archive&fields=downloadUrl%2Cversion%2Ccomponents%2Ccomponent%2Cembedded';
|
||||
|
||||
describe('getAvailableVersions', () => {
|
||||
let spyHttpClient: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
spyHttpClient.mockReturnValue({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: manifestData as NikVersion[]
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
jest.clearAllMocks();
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it.each([
|
||||
[
|
||||
{version: '21', architecture: 'x64', packageType: 'jdk'},
|
||||
'bundle-type=standard&bitness=64&arch=x86&build-type=all'
|
||||
],
|
||||
[
|
||||
{version: '21-ea', architecture: 'x64', packageType: 'jdk'},
|
||||
'bundle-type=standard&bitness=64&arch=x86&build-type=ea'
|
||||
],
|
||||
[
|
||||
{version: '21', architecture: 'aarch64', packageType: 'jdk'},
|
||||
'bundle-type=standard&bitness=64&arch=arm&build-type=all'
|
||||
],
|
||||
[
|
||||
{version: '21', architecture: 'x64', packageType: 'jdk+fx'},
|
||||
'bundle-type=full&bitness=64&arch=x86&build-type=all'
|
||||
]
|
||||
])('build correct url for %s -> %s', async (input, urlParams) => {
|
||||
const distribution = new LibericaNikDistributions({
|
||||
...input,
|
||||
checkLatest: false
|
||||
});
|
||||
distribution['getPlatformOption'] = () => 'linux';
|
||||
const buildUrl = `https://api.bell-sw.com/v1/nik/releases?os=linux&${urlParams}${ADDITIONAL_PARAMS}`;
|
||||
|
||||
await distribution['getAvailableVersions']();
|
||||
|
||||
expect(spyHttpClient.mock.calls).toHaveLength(1);
|
||||
expect(spyHttpClient.mock.calls[0][0]).toBe(buildUrl);
|
||||
});
|
||||
|
||||
it('load available versions', async () => {
|
||||
const distribution = new LibericaNikDistributions({
|
||||
version: '21',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
const availableVersions = await distribution['getAvailableVersions']();
|
||||
expect(availableVersions).toEqual(manifestData);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getArchitectureOptions', () => {
|
||||
it.each([
|
||||
['x64', {bitness: '64', arch: 'x86'}],
|
||||
['aarch64', {bitness: '64', arch: 'arm'}]
|
||||
] as [string, ArchitectureOptions][])(
|
||||
'parse architecture %s -> %s',
|
||||
(input, expected) => {
|
||||
const distributions = new LibericaNikDistributions({
|
||||
architecture: input,
|
||||
checkLatest: false,
|
||||
packageType: 'jdk',
|
||||
version: '21'
|
||||
});
|
||||
|
||||
expect(distributions['getArchitectureOptions']()).toEqual(expected);
|
||||
}
|
||||
);
|
||||
|
||||
it.each(['x86', 'armv7', 's390x'])('not support architecture %s', input => {
|
||||
const distributions = new LibericaNikDistributions({
|
||||
architecture: input,
|
||||
checkLatest: false,
|
||||
packageType: 'jdk',
|
||||
version: '21'
|
||||
});
|
||||
|
||||
expect(() => distributions['getArchitectureOptions']()).toThrow(
|
||||
/Architecture '\w+' is not supported\. Supported architectures: .*/
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findPackageForDownload', () => {
|
||||
let distribution: InstanceType<typeof LibericaNikDistributions>;
|
||||
|
||||
beforeEach(() => {
|
||||
distribution = new LibericaNikDistributions({
|
||||
version: '',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
distribution['getAvailableVersions'] = async () => manifestData;
|
||||
});
|
||||
|
||||
// The user's java-version resolves against the embedded JDK version, not
|
||||
// NIK's own GraalVM version.
|
||||
it.each([
|
||||
['21', '21.0.11+12'],
|
||||
['17', '17.0.19+12'],
|
||||
['25', '25.0.3+12'],
|
||||
['11', '11.0.22+12'],
|
||||
['21.0.2', '21.0.2+14'],
|
||||
['23', '23.0.2+9'],
|
||||
['20.x', '20.0.2+10'],
|
||||
['25.0.1', '25.0.1+16']
|
||||
])('version is %s -> %s', async (input, expected) => {
|
||||
const result = await distribution['findPackageForDownload'](input);
|
||||
expect(result.version).toBe(expected);
|
||||
});
|
||||
|
||||
it('should throw an error', async () => {
|
||||
await expect(distribution['findPackageForDownload']('7')).rejects.toThrow(
|
||||
/No matching version found for SemVer/
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getPlatformOption', () => {
|
||||
const distributions = new LibericaNikDistributions({
|
||||
architecture: 'x64',
|
||||
version: '21',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
it.each([
|
||||
['linux', 'linux'],
|
||||
['darwin', 'macos'],
|
||||
['win32', 'windows'],
|
||||
['cygwin', 'windows']
|
||||
])('os version %s -> %s', (input, expected) => {
|
||||
const actual = distributions['getPlatformOption'](input as NodeJS.Platform);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it.each(['sunos', 'aix', 'android', 'freebsd'])(
|
||||
'not support os version %s',
|
||||
input => {
|
||||
expect(() =>
|
||||
distributions['getPlatformOption'](input as NodeJS.Platform)
|
||||
).toThrow(/Platform '\w+' is not supported\. Supported platforms: .+/);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('convertVersionToSemver', () => {
|
||||
const distributions = new LibericaNikDistributions({
|
||||
architecture: 'x64',
|
||||
version: '21',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
it.each([
|
||||
['25.0.1+16', '25.0.1+16'],
|
||||
['21+37', '21.0.0+37'],
|
||||
['23+38', '23.0.0+38'],
|
||||
['11.0.15.1+2', '11.0.15+1.2'],
|
||||
['17.0.5', '17.0.5']
|
||||
])('%s -> %s', (input, expected) => {
|
||||
const actual = distributions['convertVersionToSemver'](input);
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@@ -1,17 +1,56 @@
|
||||
import {LibericaDistributions} from '../../src/distributions/liberica/installer';
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import type {
|
||||
ArchitectureOptions,
|
||||
LibericaVersion
|
||||
} from '../../src/distributions/liberica/models';
|
||||
} from '../../src/distributions/liberica/models.js';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import os from 'os';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import manifestData from '../data/liberica-windows.json';
|
||||
import manifestData from '../data/liberica-windows.json' with {type: 'json'};
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const {LibericaDistributions} =
|
||||
await import('../../src/distributions/liberica/installer.js');
|
||||
|
||||
describe('getAvailableVersions', () => {
|
||||
let spyHttpClient: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyHttpClient: any;
|
||||
let spyCoreError: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
@@ -21,7 +60,7 @@ describe('getAvailableVersions', () => {
|
||||
result: manifestData as LibericaVersion[]
|
||||
});
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -183,7 +222,7 @@ describe('getArchitectureOptions', () => {
|
||||
});
|
||||
|
||||
describe('findPackageForDownload', () => {
|
||||
let distribution: LibericaDistributions;
|
||||
let distribution: InstanceType<typeof LibericaDistributions>;
|
||||
|
||||
beforeEach(() => {
|
||||
distribution = new LibericaDistributions({
|
||||
|
||||
@@ -1,37 +1,101 @@
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import * as util from '../../src/util';
|
||||
|
||||
import {LocalDistribution} from '../../src/distributions/local/installer';
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('@actions/tool-cache', () => ({
|
||||
find: jest.fn(),
|
||||
findAllVersions: jest.fn(),
|
||||
downloadTool: jest.fn(),
|
||||
extractZip: jest.fn(),
|
||||
extractTar: jest.fn(),
|
||||
extract7z: jest.fn(),
|
||||
extractXar: jest.fn(),
|
||||
cacheDir: jest.fn(),
|
||||
cacheFile: jest.fn(),
|
||||
getManifestFromRepo: jest.fn(),
|
||||
findFromManifest: jest.fn(),
|
||||
evaluateVersions: jest.fn()
|
||||
}));
|
||||
|
||||
const real_util_module = await import('../../src/util.js');
|
||||
jest.unstable_mockModule('../../src/util.js', () => ({
|
||||
...real_util_module,
|
||||
extractJdkFile: jest.fn(),
|
||||
getDownloadArchiveExtension: jest.fn(),
|
||||
getToolcachePath: jest.fn(),
|
||||
isJobStatusSuccess: jest.fn(),
|
||||
renameWinArchive: jest.fn(),
|
||||
isVersionSatisfies: real_util_module.isVersionSatisfies,
|
||||
getTempDir: real_util_module.getTempDir
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const tc = await import('@actions/tool-cache');
|
||||
const util = await import('../../src/util.js');
|
||||
const {LocalDistribution} =
|
||||
await import('../../src/distributions/local/installer.js');
|
||||
|
||||
describe('setupJava', () => {
|
||||
const actualJavaVersion = '11.1.10';
|
||||
const javaPath = path.join('Java_jdkfile_jdk', actualJavaVersion, 'x86');
|
||||
|
||||
let mockJavaBase: LocalDistribution;
|
||||
let mockJavaBase: InstanceType<typeof LocalDistribution>;
|
||||
|
||||
let spyGetToolcachePath: jest.SpyInstance;
|
||||
let spyTcCacheDir: jest.SpyInstance;
|
||||
let spyTcFindAllVersions: jest.SpyInstance;
|
||||
let spyCoreDebug: jest.SpyInstance;
|
||||
let spyCoreInfo: jest.SpyInstance;
|
||||
let spyCoreExportVariable: jest.SpyInstance;
|
||||
let spyCoreAddPath: jest.SpyInstance;
|
||||
let spyCoreSetOutput: jest.SpyInstance;
|
||||
let spyFsStat: jest.SpyInstance;
|
||||
let spyFsReadDir: jest.SpyInstance;
|
||||
let spyUtilsExtractJdkFile: jest.SpyInstance;
|
||||
let spyPathResolve: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyGetToolcachePath: any;
|
||||
let spyTcCacheDir: any;
|
||||
let spyTcFindAllVersions: any;
|
||||
let spyCoreDebug: any;
|
||||
let spyCoreInfo: any;
|
||||
let spyCoreExportVariable: any;
|
||||
let spyCoreAddPath: any;
|
||||
let spyCoreSetOutput: any;
|
||||
let spyFsStat: any;
|
||||
let spyFsReadDir: any;
|
||||
let spyUtilsExtractJdkFile: any;
|
||||
let spyPathResolve: any;
|
||||
let spyCoreError: any;
|
||||
const expectedJdkFile = 'JavaLocalJdkFile';
|
||||
|
||||
beforeEach(() => {
|
||||
spyGetToolcachePath = jest.spyOn(util, 'getToolcachePath');
|
||||
spyGetToolcachePath = util.getToolcachePath as jest.Mock;
|
||||
spyGetToolcachePath.mockImplementation(
|
||||
(toolname: string, javaVersion: string, architecture: string) => {
|
||||
const semverVersion = new semver.Range(javaVersion);
|
||||
@@ -49,7 +113,7 @@ describe('setupJava', () => {
|
||||
}
|
||||
);
|
||||
|
||||
spyTcCacheDir = jest.spyOn(tc, 'cacheDir');
|
||||
spyTcCacheDir = tc.cacheDir as jest.Mock;
|
||||
spyTcCacheDir.mockImplementation(
|
||||
(
|
||||
archivePath: string,
|
||||
@@ -59,23 +123,23 @@ describe('setupJava', () => {
|
||||
) => path.join(toolcacheFolderName, version, architecture)
|
||||
);
|
||||
|
||||
spyTcFindAllVersions = jest.spyOn(tc, 'findAllVersions');
|
||||
spyTcFindAllVersions = tc.findAllVersions as jest.Mock;
|
||||
spyTcFindAllVersions.mockReturnValue([actualJavaVersion]);
|
||||
|
||||
// Spy on core methods
|
||||
spyCoreDebug = jest.spyOn(core, 'debug');
|
||||
spyCoreDebug = core.debug as jest.Mock;
|
||||
spyCoreDebug.mockImplementation(() => undefined);
|
||||
|
||||
spyCoreInfo = jest.spyOn(core, 'info');
|
||||
spyCoreInfo = core.info as jest.Mock;
|
||||
spyCoreInfo.mockImplementation(() => undefined);
|
||||
|
||||
spyCoreAddPath = jest.spyOn(core, 'addPath');
|
||||
spyCoreAddPath = core.addPath as jest.Mock;
|
||||
spyCoreAddPath.mockImplementation(() => undefined);
|
||||
|
||||
spyCoreExportVariable = jest.spyOn(core, 'exportVariable');
|
||||
spyCoreExportVariable = core.exportVariable as jest.Mock;
|
||||
spyCoreExportVariable.mockImplementation(() => undefined);
|
||||
|
||||
spyCoreSetOutput = jest.spyOn(core, 'setOutput');
|
||||
spyCoreSetOutput = core.setOutput as jest.Mock;
|
||||
spyCoreSetOutput.mockImplementation(() => undefined);
|
||||
|
||||
// Spy on fs methods
|
||||
@@ -88,7 +152,7 @@ describe('setupJava', () => {
|
||||
});
|
||||
|
||||
// Spy on util methods
|
||||
spyUtilsExtractJdkFile = jest.spyOn(util, 'extractJdkFile');
|
||||
spyUtilsExtractJdkFile = util.extractJdkFile as jest.Mock;
|
||||
spyUtilsExtractJdkFile.mockImplementation(() => 'some/random/path/');
|
||||
|
||||
// Spy on path methods
|
||||
@@ -96,7 +160,7 @@ describe('setupJava', () => {
|
||||
spyPathResolve.mockImplementation((path: string) => path);
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -106,6 +170,20 @@ describe('setupJava', () => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('throws for the latest alias since jdkfile has no version list', async () => {
|
||||
const inputs = {
|
||||
version: 'latest',
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
};
|
||||
|
||||
mockJavaBase = new LocalDistribution(inputs, expectedJdkFile);
|
||||
await expect(mockJavaBase.setupJava()).rejects.toThrow(
|
||||
"The 'latest' version alias is not supported for the 'jdkfile' distribution. Please specify a concrete version."
|
||||
);
|
||||
});
|
||||
|
||||
it('java is resolved from toolcache, jdkfile is untouched', async () => {
|
||||
const inputs = {
|
||||
version: actualJavaVersion,
|
||||
@@ -130,6 +208,29 @@ describe('setupJava', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('java is unpacked from jdkfile when force-download is enabled', async () => {
|
||||
const inputs = {
|
||||
version: actualJavaVersion,
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false,
|
||||
forceDownload: true
|
||||
};
|
||||
|
||||
mockJavaBase = new LocalDistribution(inputs, expectedJdkFile);
|
||||
await expect(mockJavaBase.setupJava()).resolves.toEqual({
|
||||
version: actualJavaVersion,
|
||||
path: javaPath
|
||||
});
|
||||
|
||||
expect(spyGetToolcachePath).not.toHaveBeenCalled();
|
||||
expect(spyUtilsExtractJdkFile).toHaveBeenCalledWith(expectedJdkFile);
|
||||
expect(spyTcCacheDir).toHaveBeenCalled();
|
||||
expect(spyCoreInfo).not.toHaveBeenCalledWith(
|
||||
`Resolved Java ${actualJavaVersion} from tool-cache`
|
||||
);
|
||||
});
|
||||
|
||||
it("java is resolved from toolcache, jdkfile doesn't exist", async () => {
|
||||
const inputs = {
|
||||
version: actualJavaVersion,
|
||||
|
||||
@@ -1,23 +1,118 @@
|
||||
import {
|
||||
MicrosoftDistributions,
|
||||
MICROSOFT_PUBLIC_KEY
|
||||
} from '../../src/distributions/microsoft/installer';
|
||||
import os from 'os';
|
||||
import data from '../data/microsoft.json';
|
||||
import * as httpm from '@actions/http-client';
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as gpg from '../../src/gpg';
|
||||
import * as util from '../../src/util';
|
||||
import fs from 'fs';
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import data from '../data/microsoft.json' with {type: 'json'};
|
||||
|
||||
const mockOsArch = jest.fn(() => 'x64');
|
||||
const mockOsPlatform = jest.fn(() => 'linux');
|
||||
|
||||
const real_os_module = await import('os');
|
||||
jest.unstable_mockModule('os', () => ({
|
||||
...real_os_module,
|
||||
default: {
|
||||
...real_os_module.default,
|
||||
arch: mockOsArch,
|
||||
platform: mockOsPlatform,
|
||||
homedir: real_os_module.default.homedir
|
||||
},
|
||||
arch: mockOsArch,
|
||||
platform: mockOsPlatform
|
||||
}));
|
||||
|
||||
const real_fs_module = await import('fs');
|
||||
const mockReaddirSync = jest.fn();
|
||||
jest.unstable_mockModule('fs', () => ({
|
||||
...real_fs_module,
|
||||
default: {
|
||||
...real_fs_module.default,
|
||||
readdirSync: mockReaddirSync
|
||||
},
|
||||
readdirSync: mockReaddirSync
|
||||
}));
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
const real_tc_module = await import('@actions/tool-cache');
|
||||
jest.unstable_mockModule('@actions/tool-cache', () => ({
|
||||
...real_tc_module,
|
||||
downloadTool: jest.fn(),
|
||||
cacheDir: jest.fn(),
|
||||
cacheFile: jest.fn()
|
||||
}));
|
||||
|
||||
const real_util_module = await import('../../src/util.js');
|
||||
jest.unstable_mockModule('../../src/util.js', () => ({
|
||||
...real_util_module,
|
||||
extractJdkFile: jest.fn(),
|
||||
getDownloadArchiveExtension: jest.fn(),
|
||||
getToolcachePath: jest.fn(),
|
||||
isJobStatusSuccess: jest.fn(),
|
||||
renameWinArchive: jest.fn(),
|
||||
isVersionSatisfies: real_util_module.isVersionSatisfies,
|
||||
getTempDir: real_util_module.getTempDir
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../src/gpg.js', () => ({
|
||||
importKey: jest.fn(),
|
||||
deleteKey: jest.fn(),
|
||||
verifyPackageSignature: jest.fn()
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const gpg = await import('../../src/gpg.js');
|
||||
const tc = await import('@actions/tool-cache');
|
||||
const os = (await import('os')).default;
|
||||
const fs = (await import('fs')).default;
|
||||
const {MicrosoftDistributions, MICROSOFT_PUBLIC_KEY} =
|
||||
await import('../../src/distributions/microsoft/installer.js');
|
||||
const util = await import('../../src/util.js');
|
||||
|
||||
describe('findPackageForDownload', () => {
|
||||
let distribution: MicrosoftDistributions;
|
||||
let spyGetManifestFromRepo: jest.SpyInstance;
|
||||
let spyDebug: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let distribution: InstanceType<typeof MicrosoftDistributions>;
|
||||
let spyGetManifestFromRepo: any;
|
||||
let spyHttpClientGet: any;
|
||||
let spyDebug: any;
|
||||
let spyCoreError: any;
|
||||
|
||||
const MICROSOFT_CHECKSUM = 'b'.repeat(64);
|
||||
|
||||
beforeEach(() => {
|
||||
mockOsArch.mockReturnValue('x64');
|
||||
mockOsPlatform.mockReturnValue(process.platform);
|
||||
|
||||
distribution = new MicrosoftDistributions({
|
||||
version: '',
|
||||
architecture: 'x64',
|
||||
@@ -25,18 +120,27 @@ describe('findPackageForDownload', () => {
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
spyGetManifestFromRepo = jest.spyOn(httpm.HttpClient.prototype, 'getJson');
|
||||
spyGetManifestFromRepo = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
spyGetManifestFromRepo.mockReturnValue({
|
||||
result: data,
|
||||
statusCode: 200,
|
||||
headers: {}
|
||||
});
|
||||
|
||||
spyDebug = jest.spyOn(core, 'debug');
|
||||
// Every resolved release fetches `${download_url}.sha256sum.txt`; stub
|
||||
// it with a GNU-style `<hex> <filename>` payload so tests never reach
|
||||
// the real network.
|
||||
spyHttpClientGet = jest.spyOn(HttpClient.prototype, 'get');
|
||||
spyHttpClientGet.mockResolvedValue({
|
||||
message: {statusCode: 200},
|
||||
readBody: async () => `${MICROSOFT_CHECKSUM} microsoft-jdk.tar.gz\n`
|
||||
});
|
||||
|
||||
spyDebug = core.debug as jest.Mock;
|
||||
spyDebug.mockImplementation(() => {});
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -118,10 +222,8 @@ describe('findPackageForDownload', () => {
|
||||
])(
|
||||
'defaults to os.arch(): %s mapped to distro arch: %s',
|
||||
async (osArch: string, distroArch: string) => {
|
||||
jest
|
||||
.spyOn(os, 'arch')
|
||||
.mockReturnValue(osArch as ReturnType<typeof os.arch>);
|
||||
jest.spyOn(os, 'platform').mockReturnValue('darwin');
|
||||
mockOsArch.mockReturnValue(osArch);
|
||||
mockOsPlatform.mockReturnValue('darwin');
|
||||
|
||||
const version = '17';
|
||||
const distro = new MicrosoftDistributions({
|
||||
@@ -144,10 +246,8 @@ describe('findPackageForDownload', () => {
|
||||
])(
|
||||
'defaults to os.arch(): %s mapped to distro arch: %s',
|
||||
async (osArch: string, distroArch: string) => {
|
||||
jest
|
||||
.spyOn(os, 'arch')
|
||||
.mockReturnValue(osArch as ReturnType<typeof os.arch>);
|
||||
jest.spyOn(os, 'platform').mockReturnValue('linux');
|
||||
mockOsArch.mockReturnValue(osArch);
|
||||
mockOsPlatform.mockReturnValue('linux');
|
||||
|
||||
const version = '17';
|
||||
const distro = new MicrosoftDistributions({
|
||||
@@ -170,10 +270,8 @@ describe('findPackageForDownload', () => {
|
||||
])(
|
||||
'defaults to os.arch(): %s mapped to distro arch: %s',
|
||||
async (osArch: string, distroArch: string) => {
|
||||
jest
|
||||
.spyOn(os, 'arch')
|
||||
.mockReturnValue(osArch as ReturnType<typeof os.arch>);
|
||||
jest.spyOn(os, 'platform').mockReturnValue('win32');
|
||||
mockOsArch.mockReturnValue(osArch);
|
||||
mockOsPlatform.mockReturnValue('win32');
|
||||
|
||||
const version = '17';
|
||||
const distro = new MicrosoftDistributions({
|
||||
@@ -217,7 +315,7 @@ describe('findPackageForDownload', () => {
|
||||
statusCode: 200,
|
||||
headers: {}
|
||||
});
|
||||
jest.spyOn(os, 'platform').mockReturnValue('linux');
|
||||
mockOsPlatform.mockReturnValue('linux');
|
||||
|
||||
const result = await distribution['findPackageForDownload']('17.0.10');
|
||||
|
||||
@@ -225,19 +323,45 @@ describe('findPackageForDownload', () => {
|
||||
'https://example.test/jdk.tar.gz.custom.sig'
|
||||
);
|
||||
});
|
||||
|
||||
it('fetches the authoritative sha256 checksum from the GNU-style sibling file', async () => {
|
||||
mockOsPlatform.mockReturnValue(process.platform);
|
||||
|
||||
const result = await distribution['findPackageForDownload']('17.0.7');
|
||||
|
||||
expect(result.checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: MICROSOFT_CHECKSUM,
|
||||
source: `${result.url}.sha256sum.txt`
|
||||
});
|
||||
expect(spyHttpClientGet).toHaveBeenCalledWith(
|
||||
`${result.url}.sha256sum.txt`
|
||||
);
|
||||
expect(spyHttpClientGet).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('parses only the first whitespace-delimited token from the GNU checksum payload', async () => {
|
||||
spyHttpClientGet.mockResolvedValue({
|
||||
message: {statusCode: 200},
|
||||
readBody: async () =>
|
||||
`${MICROSOFT_CHECKSUM} microsoft-jdk-17.0.7-linux-x64.tar.gz\n`
|
||||
});
|
||||
|
||||
const result = await distribution['findPackageForDownload']('17.0.7');
|
||||
|
||||
expect(result.checksum?.value).toBe(MICROSOFT_CHECKSUM);
|
||||
});
|
||||
});
|
||||
|
||||
describe('downloadTool', () => {
|
||||
let spyDownloadTool: jest.SpyInstance;
|
||||
let spyExtractJdkFile: jest.SpyInstance;
|
||||
let spyCacheDir: jest.SpyInstance;
|
||||
let spyVerifySignature: jest.SpyInstance;
|
||||
let distribution: MicrosoftDistributions;
|
||||
let spyDownloadTool: any;
|
||||
let spyExtractJdkFile: any;
|
||||
let spyCacheDir: any;
|
||||
let spyVerifySignature: any;
|
||||
let distribution: InstanceType<typeof MicrosoftDistributions>;
|
||||
|
||||
beforeEach(() => {
|
||||
jest
|
||||
.spyOn(os, 'platform')
|
||||
.mockReturnValue(process.platform as ReturnType<typeof os.platform>);
|
||||
mockOsPlatform.mockReturnValue(process.platform);
|
||||
|
||||
distribution = new MicrosoftDistributions({
|
||||
version: '17',
|
||||
@@ -246,27 +370,27 @@ describe('downloadTool', () => {
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
spyDownloadTool = jest.spyOn(tc, 'downloadTool');
|
||||
spyDownloadTool = tc.downloadTool as jest.Mock;
|
||||
spyDownloadTool.mockImplementation(async () => {
|
||||
return '/tmp/jdk.tar.gz';
|
||||
});
|
||||
|
||||
spyExtractJdkFile = jest.spyOn(util, 'extractJdkFile');
|
||||
spyExtractJdkFile = util.extractJdkFile as jest.Mock;
|
||||
spyExtractJdkFile.mockImplementation(async () => {
|
||||
return '/tmp/unpacked';
|
||||
});
|
||||
|
||||
jest.spyOn(fs, 'readdirSync').mockReturnValue(['jdk'] as any);
|
||||
spyCacheDir = jest.spyOn(tc, 'cacheDir');
|
||||
mockReaddirSync.mockReturnValue(['jdk'] as any);
|
||||
spyCacheDir = tc.cacheDir as jest.Mock;
|
||||
spyCacheDir.mockImplementation(async () => {
|
||||
return '/tmp/cached';
|
||||
});
|
||||
|
||||
jest
|
||||
.spyOn(util, 'renameWinArchive')
|
||||
.mockImplementation((archivePath: string) => `${archivePath}.zip`);
|
||||
(util.renameWinArchive as jest.Mock<any>).mockImplementation(
|
||||
(archivePath: string) => `${archivePath}.zip`
|
||||
);
|
||||
|
||||
spyVerifySignature = jest.spyOn(gpg, 'verifyPackageSignature');
|
||||
spyVerifySignature = gpg.verifyPackageSignature as jest.Mock;
|
||||
spyVerifySignature.mockImplementation(async () => {});
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
import {afterEach, beforeEach, describe, expect, it, jest} from '@jest/globals';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((value: string) => value),
|
||||
toWin32Path: jest.fn((value: string) => value),
|
||||
toPosixPath: jest.fn((value: string) => value)
|
||||
}));
|
||||
|
||||
const {OpenJdkDistribution} =
|
||||
await import('../../src/distributions/openjdk/installer.js');
|
||||
const {getJavaDistribution} =
|
||||
await import('../../src/distributions/distribution-factory.js');
|
||||
|
||||
const homePage = `
|
||||
<a href="/26/">JDK 26</a>
|
||||
<a href="/27/">JDK
|
||||
27</a>
|
||||
`;
|
||||
const currentPage = `
|
||||
<a href="https://download.java.net/java/GA/jdk26.0.2/hash/10/GPL/openjdk-26.0.2_linux-x64_bin.tar.gz">tar.gz</a>
|
||||
<a href="https://download.java.net/java/GA/jdk26.0.2/hash/10/GPL/openjdk-26.0.2_linux-aarch64_bin.tar.gz">tar.gz</a>
|
||||
`;
|
||||
const earlyAccessPage = `
|
||||
<a href="https://download.java.net/java/early_access/jdk27/32/GPL/openjdk-27-ea+32_linux-x64_bin.tar.gz">tar.gz</a>
|
||||
`;
|
||||
const archivePage = `
|
||||
<a href="https://download.java.net/java/GA/jdk26.0.1/hash/8/GPL/openjdk-26.0.1_linux-x64_bin.tar.gz">tar.gz</a>
|
||||
<a href="https://download.java.net/java/GA/jdk25/hash/36/GPL/openjdk-25_linux-x64_bin.tar.gz">tar.gz</a>
|
||||
<a href="https://download.java.net/java/GA/jdk18.0.1.1/hash/2/GPL/openjdk-18.0.1.1_linux-x64_bin.tar.gz">tar.gz</a>
|
||||
<th>9.0.4 (build 9.0.4+11)</th>
|
||||
<a href="https://download.java.net/java/GA/jdk9/9.0.4/binaries/openjdk-9.0.4_linux-x64_bin.tar.gz">tar.gz</a>
|
||||
`;
|
||||
const GA_CHECKSUM = 'c'.repeat(64);
|
||||
const EA_CHECKSUM = 'd'.repeat(64);
|
||||
const checksumPages: Record<string, string> = {
|
||||
'https://download.java.net/java/GA/jdk26.0.2/hash/10/GPL/openjdk-26.0.2_linux-x64_bin.tar.gz.sha256':
|
||||
GA_CHECKSUM,
|
||||
'https://download.java.net/java/early_access/jdk27/32/GPL/openjdk-27-ea+32_linux-x64_bin.tar.gz.sha256':
|
||||
EA_CHECKSUM
|
||||
};
|
||||
|
||||
function createDistribution(
|
||||
version = '26',
|
||||
architecture = 'x64',
|
||||
packageType = 'jdk',
|
||||
useFixturePlatform = true
|
||||
) {
|
||||
const distribution = new OpenJdkDistribution({
|
||||
version,
|
||||
architecture,
|
||||
packageType,
|
||||
checkLatest: false
|
||||
});
|
||||
if (useFixturePlatform) {
|
||||
distribution['getPlatform'] = jest.fn(() => 'linux');
|
||||
}
|
||||
return distribution;
|
||||
}
|
||||
|
||||
describe('OpenJdkDistribution', () => {
|
||||
let getSpy: jest.SpiedFunction<HttpClient['get']>;
|
||||
|
||||
beforeEach(() => {
|
||||
getSpy = jest
|
||||
.spyOn(HttpClient.prototype, 'get')
|
||||
.mockImplementation(async url => {
|
||||
const pages: Record<string, string> = {
|
||||
'https://jdk.java.net/': homePage,
|
||||
'https://jdk.java.net/26/': currentPage,
|
||||
'https://jdk.java.net/27/': earlyAccessPage,
|
||||
'https://jdk.java.net/archive/': archivePage
|
||||
};
|
||||
if (url in pages) {
|
||||
return {
|
||||
message: {statusCode: 200},
|
||||
readBody: async () => pages[url]
|
||||
} as Awaited<ReturnType<HttpClient['get']>>;
|
||||
}
|
||||
// Any other GET is a `${archiveUrl}.sha256` checksum sibling request.
|
||||
return {
|
||||
message: {statusCode: 200},
|
||||
readBody: async () => checksumPages[url] ?? 'e'.repeat(64)
|
||||
} as Awaited<ReturnType<HttpClient['get']>>;
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('resolves the newest matching GA release', async () => {
|
||||
const result = await createDistribution()['findPackageForDownload']('26');
|
||||
|
||||
expect(result).toEqual({
|
||||
version: '26.0.2+10',
|
||||
url: 'https://download.java.net/java/GA/jdk26.0.2/hash/10/GPL/openjdk-26.0.2_linux-x64_bin.tar.gz',
|
||||
checksum: {
|
||||
algorithm: 'sha256',
|
||||
value: GA_CHECKSUM,
|
||||
source:
|
||||
'https://download.java.net/java/GA/jdk26.0.2/hash/10/GPL/openjdk-26.0.2_linux-x64_bin.tar.gz.sha256'
|
||||
}
|
||||
});
|
||||
expect(getSpy).toHaveBeenCalledWith(`${result.url}.sha256`);
|
||||
});
|
||||
|
||||
it('resolves an archived GA release', async () => {
|
||||
const result =
|
||||
await createDistribution('26.0.1')['findPackageForDownload']('26.0.1');
|
||||
|
||||
expect(result.version).toBe('26.0.1+8');
|
||||
expect(result.url).toContain('/openjdk-26.0.1_linux-x64_bin.tar.gz');
|
||||
});
|
||||
|
||||
it('resolves an exact GA build', async () => {
|
||||
const result =
|
||||
await createDistribution('26.0.2+10')['findPackageForDownload'](
|
||||
'26.0.2+10'
|
||||
);
|
||||
|
||||
expect(result.version).toBe('26.0.2+10');
|
||||
});
|
||||
|
||||
it('resolves an exact build from a legacy archive heading', async () => {
|
||||
const result =
|
||||
await createDistribution('9.0.4+11')['findPackageForDownload'](
|
||||
'9.0.4+11'
|
||||
);
|
||||
|
||||
expect(result.version).toBe('9.0.4+11');
|
||||
expect(result.url).toContain('/binaries/openjdk-9.0.4_linux-x64_bin');
|
||||
});
|
||||
|
||||
it('resolves a four-field Java version', async () => {
|
||||
const result =
|
||||
await createDistribution('18.0.1.1')['findPackageForDownload'](
|
||||
'18.0.1+1'
|
||||
);
|
||||
|
||||
expect(result.version).toBe('18.0.1+1');
|
||||
expect(result.url).toContain('/openjdk-18.0.1.1_linux-x64_bin.tar.gz');
|
||||
});
|
||||
|
||||
it('resolves an early-access release without requesting the archive', async () => {
|
||||
const result =
|
||||
await createDistribution('27-ea')['findPackageForDownload']('27');
|
||||
|
||||
expect(result).toEqual({
|
||||
version: '27.0.0+32',
|
||||
url: 'https://download.java.net/java/early_access/jdk27/32/GPL/openjdk-27-ea+32_linux-x64_bin.tar.gz',
|
||||
checksum: {
|
||||
algorithm: 'sha256',
|
||||
value: EA_CHECKSUM,
|
||||
source:
|
||||
'https://download.java.net/java/early_access/jdk27/32/GPL/openjdk-27-ea+32_linux-x64_bin.tar.gz.sha256'
|
||||
}
|
||||
});
|
||||
expect(getSpy).not.toHaveBeenCalledWith('https://jdk.java.net/archive/');
|
||||
expect(getSpy).toHaveBeenCalledWith(`${result.url}.sha256`);
|
||||
});
|
||||
|
||||
it('reports available versions when no release matches', async () => {
|
||||
await expect(
|
||||
createDistribution()['findPackageForDownload']('24')
|
||||
).rejects.toThrow(
|
||||
"No matching version found for SemVer '24'.\nDistribution: Oracle OpenJDK"
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
['jre', 'Oracle OpenJDK provides only the `jdk` package type'],
|
||||
['jdk+fx', 'Oracle OpenJDK provides only the `jdk` package type']
|
||||
])('rejects the %s package type', async (packageType, message) => {
|
||||
await expect(
|
||||
createDistribution('26', 'x64', packageType)['findPackageForDownload'](
|
||||
'26'
|
||||
)
|
||||
).rejects.toThrow(message);
|
||||
});
|
||||
|
||||
it('rejects unsupported architectures', async () => {
|
||||
await expect(
|
||||
createDistribution('26', 'x86')['findPackageForDownload']('26')
|
||||
).rejects.toThrow('Unsupported architecture: x86');
|
||||
});
|
||||
|
||||
it('maps supported platforms', () => {
|
||||
const distribution = createDistribution('26', 'x64', 'jdk', false);
|
||||
|
||||
expect(distribution['getPlatform']('linux')).toBe('linux');
|
||||
expect(distribution['getPlatform']('darwin')).toBe('macos');
|
||||
expect(distribution['getPlatform']('win32')).toBe('windows');
|
||||
expect(() => distribution['getPlatform']('freebsd')).toThrow(
|
||||
"Platform 'freebsd' is not supported"
|
||||
);
|
||||
});
|
||||
|
||||
it('parses legacy platform names and archive formats', () => {
|
||||
const distribution = createDistribution();
|
||||
const macRelease = distribution['parseReleases'](
|
||||
'<a href="https://download.java.net/java/GA/jdk16/hash/7/GPL/openjdk-16_osx-x64_bin.tar.gz">tar.gz</a>',
|
||||
'macos',
|
||||
'x64'
|
||||
);
|
||||
const windowsRelease = distribution['parseReleases'](
|
||||
'<a href="https://download.java.net/java/GA/jdk10/hash/13/openjdk-10.0.2_windows-x64_bin.tar.gz">tar.gz</a>',
|
||||
'windows',
|
||||
'x64'
|
||||
);
|
||||
|
||||
expect(macRelease[0].version).toBe('16.0.0+7');
|
||||
expect(windowsRelease[0].version).toBe('10.0.2+13');
|
||||
expect(windowsRelease[0].url.endsWith('.tar.gz')).toBe(true);
|
||||
});
|
||||
|
||||
it('is registered in the distribution factory', async () => {
|
||||
const distribution = await getJavaDistribution('oracle-openjdk', {
|
||||
version: '26',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
expect(distribution).toBeInstanceOf(OpenJdkDistribution);
|
||||
});
|
||||
});
|
||||
@@ -1,14 +1,56 @@
|
||||
import {OracleDistribution} from '../../src/distributions/oracle/installer';
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import os from 'os';
|
||||
import * as core from '@actions/core';
|
||||
import {getDownloadArchiveExtension} from '../../src/util';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const {OracleDistribution} =
|
||||
await import('../../src/distributions/oracle/installer.js');
|
||||
const {getDownloadArchiveExtension} = await import('../../src/util.js');
|
||||
|
||||
describe('findPackageForDownload', () => {
|
||||
let distribution: OracleDistribution;
|
||||
let spyDebug: jest.SpyInstance;
|
||||
let spyHttpClient: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let distribution: InstanceType<typeof OracleDistribution>;
|
||||
let spyDebug: any;
|
||||
let spyHttpClient: any;
|
||||
let spyHttpClientGet: any;
|
||||
let spyCoreError: any;
|
||||
|
||||
const ORACLE_CHECKSUM = 'f'.repeat(64);
|
||||
|
||||
beforeEach(() => {
|
||||
distribution = new OracleDistribution({
|
||||
@@ -18,12 +60,20 @@ describe('findPackageForDownload', () => {
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
spyDebug = jest.spyOn(core, 'debug');
|
||||
spyDebug = core.debug as jest.Mock;
|
||||
spyDebug.mockImplementation(() => {});
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
|
||||
// Every resolved release fetches its `${url}.sha256` sibling checksum;
|
||||
// stub it so tests never reach the real network.
|
||||
spyHttpClientGet = jest.spyOn(HttpClient.prototype, 'get');
|
||||
spyHttpClientGet.mockResolvedValue({
|
||||
message: {statusCode: 200},
|
||||
readBody: async () => ORACLE_CHECKSUM
|
||||
});
|
||||
});
|
||||
|
||||
it.each([
|
||||
@@ -94,6 +144,23 @@ describe('findPackageForDownload', () => {
|
||||
expect(result.url).toBe(url);
|
||||
});
|
||||
|
||||
it('fetches the authoritative sha256 checksum for the resolved archive', async () => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'head');
|
||||
spyHttpClient.mockResolvedValue({message: {statusCode: 200}});
|
||||
|
||||
const result = await distribution['findPackageForDownload']('21');
|
||||
|
||||
jest.restoreAllMocks();
|
||||
|
||||
expect(result.checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: ORACLE_CHECKSUM,
|
||||
source: `${result.url}.sha256`
|
||||
});
|
||||
expect(spyHttpClientGet).toHaveBeenCalledWith(`${result.url}.sha256`);
|
||||
expect(spyHttpClientGet).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it.each([
|
||||
['amd64', 'x64'],
|
||||
['arm64', 'aarch64']
|
||||
@@ -135,3 +202,63 @@ describe('findPackageForDownload', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('findPackageForDownload with latest', () => {
|
||||
let spyHttpClientHead: any;
|
||||
let spyHttpClientGetJson: any;
|
||||
|
||||
beforeEach(() => {
|
||||
(core.debug as jest.Mock).mockImplementation(() => {});
|
||||
(core.error as jest.Mock).mockImplementation(() => {});
|
||||
spyHttpClientGetJson = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
spyHttpClientGetJson.mockResolvedValue({
|
||||
statusCode: 200,
|
||||
result: {most_recent_feature_release: 25},
|
||||
headers: {}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('resolves the newest major version from the Adoptium API', async () => {
|
||||
spyHttpClientHead = jest.spyOn(HttpClient.prototype, 'head');
|
||||
spyHttpClientHead.mockResolvedValue({message: {statusCode: 200}});
|
||||
jest.spyOn(HttpClient.prototype, 'get').mockResolvedValue({
|
||||
message: {statusCode: 200},
|
||||
readBody: async () => 'f'.repeat(64)
|
||||
} as any);
|
||||
|
||||
const distribution = new OracleDistribution({
|
||||
version: 'latest',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
const result = await distribution['findPackageForDownload']('x');
|
||||
const osType = distribution.getPlatform();
|
||||
const archiveType = getDownloadArchiveExtension();
|
||||
|
||||
expect(result.version).toBe('25');
|
||||
expect(result.url).toBe(
|
||||
`https://download.oracle.com/java/25/latest/jdk-25_${osType}-x64_bin.${archiveType}`
|
||||
);
|
||||
});
|
||||
|
||||
it('throws an actionable error when the latest major is not yet available', async () => {
|
||||
spyHttpClientHead = jest.spyOn(HttpClient.prototype, 'head');
|
||||
spyHttpClientHead.mockResolvedValue({message: {statusCode: 404}});
|
||||
|
||||
const distribution = new OracleDistribution({
|
||||
version: 'latest',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
|
||||
await expect(distribution['findPackageForDownload']('x')).rejects.toThrow(
|
||||
/is not yet available for the Oracle JDK distribution/
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,61 @@
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import {SapMachineDistribution} from '../../src/distributions/sapmachine/installer';
|
||||
import * as utils from '../../src/util';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import manifestData from '../data/sapmachine.json';
|
||||
import manifestData from '../data/sapmachine.json' with {type: 'json'};
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
const real_util_module = await import('../../src/util.js');
|
||||
jest.unstable_mockModule('../../src/util.js', () => ({
|
||||
...real_util_module,
|
||||
getDownloadArchiveExtension: jest.fn()
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const {SapMachineDistribution} =
|
||||
await import('../../src/distributions/sapmachine/installer.js');
|
||||
const utils = await import('../../src/util.js');
|
||||
|
||||
describe('getAvailableVersions', () => {
|
||||
let spyHttpClient: jest.SpyInstance;
|
||||
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyHttpClient: any;
|
||||
let spyHttpGet: any;
|
||||
let spyUtilGetDownloadArchiveExtension: any;
|
||||
let spyCoreError: any;
|
||||
const archiveChecksum = 'f'.repeat(64);
|
||||
|
||||
beforeEach(() => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
@@ -17,15 +64,18 @@ describe('getAvailableVersions', () => {
|
||||
headers: {},
|
||||
result: manifestData
|
||||
});
|
||||
spyHttpGet = jest.spyOn(HttpClient.prototype, 'get');
|
||||
spyHttpGet.mockResolvedValue({
|
||||
message: {statusCode: 200},
|
||||
readBody: async () => `${archiveChecksum} archive`
|
||||
});
|
||||
|
||||
spyUtilGetDownloadArchiveExtension = jest.spyOn(
|
||||
utils,
|
||||
'getDownloadArchiveExtension'
|
||||
);
|
||||
spyUtilGetDownloadArchiveExtension =
|
||||
utils.getDownloadArchiveExtension as jest.Mock<any>;
|
||||
spyUtilGetDownloadArchiveExtension.mockReturnValue('tar.gz');
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -36,7 +86,7 @@ describe('getAvailableVersions', () => {
|
||||
});
|
||||
|
||||
const mockPlatform = (
|
||||
distribution: SapMachineDistribution,
|
||||
distribution: InstanceType<typeof SapMachineDistribution>,
|
||||
platform: string
|
||||
) => {
|
||||
distribution['getPlatformOption'] = () => platform;
|
||||
@@ -239,9 +289,31 @@ describe('getAvailableVersions', () => {
|
||||
await distribution['findPackageForDownload'](normalizedVersion);
|
||||
expect(availableVersion).not.toBeNull();
|
||||
expect(availableVersion.url).toBe(expectedLink);
|
||||
expect(availableVersion.checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: archiveChecksum,
|
||||
source: expectedLink.replace(/\.(?:tar\.gz|zip)$/, '.sha256.txt')
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
it('uses the checksum published beside the selected EA archive', async () => {
|
||||
const distribution = new SapMachineDistribution({
|
||||
version: '21-ea',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
mockPlatform(distribution, 'linux');
|
||||
|
||||
const release = await distribution['findPackageForDownload']('21');
|
||||
|
||||
expect(spyHttpGet).toHaveBeenCalledWith(
|
||||
release.url.replace(/\.(?:tar\.gz|zip)$/, '.sha256.txt')
|
||||
);
|
||||
expect(release.checksum?.value).toBe(archiveChecksum);
|
||||
});
|
||||
|
||||
it.each([
|
||||
['8', 'linux', 'x64'],
|
||||
['8', 'macos', 'aarch64'],
|
||||
|
||||
@@ -1,15 +1,53 @@
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import type {JavaInstallerOptions} from '../../src/distributions/base-models.js';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
|
||||
import {JavaInstallerOptions} from '../../src/distributions/base-models';
|
||||
import {SemeruDistribution} from '../../src/distributions/semeru/installer';
|
||||
import manifestData from '../data/semeru.json' with {type: 'json'};
|
||||
|
||||
import manifestData from '../data/semeru.json';
|
||||
import * as core from '@actions/core';
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const {SemeruDistribution} =
|
||||
await import('../../src/distributions/semeru/installer.js');
|
||||
|
||||
describe('getAvailableVersions', () => {
|
||||
let spyHttpClient: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyCoreWarning: jest.SpyInstance;
|
||||
let spyHttpClient: any;
|
||||
let spyCoreError: any;
|
||||
let spyCoreWarning: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
@@ -19,9 +57,9 @@ describe('getAvailableVersions', () => {
|
||||
result: []
|
||||
});
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
spyCoreWarning = jest.spyOn(core, 'warning');
|
||||
spyCoreWarning = core.warning as jest.Mock;
|
||||
spyCoreWarning.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -170,6 +208,14 @@ describe('findPackageForDownload', () => {
|
||||
distribution['getAvailableVersions'] = async () => manifestData as any;
|
||||
const resolvedVersion = await distribution['findPackageForDownload'](input);
|
||||
expect(resolvedVersion.version).toBe(expected);
|
||||
const vendorPackage = (manifestData as any[]).find(
|
||||
item => item.version_data.semver === expected
|
||||
).binaries[0].package;
|
||||
expect(resolvedVersion.checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: vendorPackage.checksum,
|
||||
source: vendorPackage.checksum_link
|
||||
});
|
||||
});
|
||||
|
||||
it('version is found but binaries list is empty', async () => {
|
||||
|
||||
@@ -1,23 +1,93 @@
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import type {JavaInstallerOptions} from '../../src/distributions/base-models.js';
|
||||
import type {TemurinImplementation as TemurinImplementationType} from '../../src/distributions/temurin/installer.js';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import {
|
||||
TemurinDistribution,
|
||||
TemurinImplementation,
|
||||
ADOPTIUM_PUBLIC_KEY
|
||||
} from '../../src/distributions/temurin/installer';
|
||||
import {JavaInstallerOptions} from '../../src/distributions/base-models';
|
||||
import * as util from '../../src/util';
|
||||
import * as gpg from '../../src/gpg';
|
||||
import path from 'path';
|
||||
|
||||
import manifestData from '../data/temurin.json';
|
||||
import * as core from '@actions/core';
|
||||
import manifestData from '../data/temurin.json' with {type: 'json'};
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('@actions/tool-cache', () => ({
|
||||
find: jest.fn(),
|
||||
findAllVersions: jest.fn(),
|
||||
downloadTool: jest.fn(),
|
||||
extractZip: jest.fn(),
|
||||
extractTar: jest.fn(),
|
||||
extract7z: jest.fn(),
|
||||
extractXar: jest.fn(),
|
||||
cacheDir: jest.fn(),
|
||||
cacheFile: jest.fn(),
|
||||
getManifestFromRepo: jest.fn(),
|
||||
findFromManifest: jest.fn(),
|
||||
evaluateVersions: jest.fn()
|
||||
}));
|
||||
|
||||
const real_util_module = await import('../../src/util.js');
|
||||
jest.unstable_mockModule('../../src/util.js', () => ({
|
||||
...real_util_module,
|
||||
extractJdkFile: jest.fn(),
|
||||
getDownloadArchiveExtension: jest.fn(),
|
||||
getToolcachePath: jest.fn(),
|
||||
isJobStatusSuccess: jest.fn(),
|
||||
renameWinArchive: jest.fn(),
|
||||
isVersionSatisfies: real_util_module.isVersionSatisfies,
|
||||
getTempDir: real_util_module.getTempDir
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../src/gpg.js', () => ({
|
||||
importKey: jest.fn(),
|
||||
deleteKey: jest.fn(),
|
||||
verifyPackageSignature: jest.fn()
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const gpg = await import('../../src/gpg.js');
|
||||
const tc = await import('@actions/tool-cache');
|
||||
const {TemurinDistribution, TemurinImplementation, ADOPTIUM_PUBLIC_KEY} =
|
||||
await import('../../src/distributions/temurin/installer.js');
|
||||
const util = await import('../../src/util.js');
|
||||
|
||||
describe('getAvailableVersions', () => {
|
||||
let spyHttpClient: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyCoreWarning: jest.SpyInstance;
|
||||
let spyHttpClient: any;
|
||||
let spyCoreError: any;
|
||||
let spyCoreWarning: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
@@ -27,9 +97,9 @@ describe('getAvailableVersions', () => {
|
||||
result: []
|
||||
});
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
spyCoreWarning = jest.spyOn(core, 'warning');
|
||||
spyCoreWarning = core.warning as jest.Mock;
|
||||
spyCoreWarning.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -50,6 +120,16 @@ describe('getAvailableVersions', () => {
|
||||
TemurinImplementation.Hotspot,
|
||||
'os=mac&architecture=x64&image_type=jdk&release_type=ga&jvm_impl=hotspot&page_size=20&page=0'
|
||||
],
|
||||
[
|
||||
{
|
||||
version: '25',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk+jmods',
|
||||
checkLatest: false
|
||||
},
|
||||
TemurinImplementation.Hotspot,
|
||||
'os=mac&architecture=x64&image_type=jdk&release_type=ga&jvm_impl=hotspot&page_size=20&page=0'
|
||||
],
|
||||
[
|
||||
{
|
||||
version: '16',
|
||||
@@ -84,7 +164,7 @@ describe('getAvailableVersions', () => {
|
||||
'build correct url for %s',
|
||||
async (
|
||||
installerOptions: JavaInstallerOptions,
|
||||
impl: TemurinImplementation,
|
||||
impl: TemurinImplementationType,
|
||||
expectedParameters
|
||||
) => {
|
||||
const distribution = new TemurinDistribution(installerOptions, impl);
|
||||
@@ -100,6 +180,27 @@ describe('getAvailableVersions', () => {
|
||||
}
|
||||
);
|
||||
|
||||
it('requests the JMOD image type', async () => {
|
||||
const distribution = new TemurinDistribution(
|
||||
{
|
||||
version: '25',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk+jmods',
|
||||
checkLatest: false
|
||||
},
|
||||
TemurinImplementation.Hotspot
|
||||
);
|
||||
distribution['getPlatformOption'] = () => 'linux';
|
||||
|
||||
await distribution['getAvailableVersions']('jmods');
|
||||
|
||||
expect(spyHttpClient).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'os=linux&architecture=x64&image_type=jmods&release_type=ga'
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('load available versions', async () => {
|
||||
const nextPageUrl =
|
||||
'https://api.adoptium.net/v3/assets/version/%5B1.0,100.0%5D?page=1&page_size=20';
|
||||
@@ -160,10 +261,19 @@ describe('getAvailableVersions', () => {
|
||||
|
||||
it.each([
|
||||
[TemurinImplementation.Hotspot, 'jdk', 'Java_Temurin-Hotspot_jdk'],
|
||||
[TemurinImplementation.Hotspot, 'jre', 'Java_Temurin-Hotspot_jre']
|
||||
[TemurinImplementation.Hotspot, 'jre', 'Java_Temurin-Hotspot_jre'],
|
||||
[
|
||||
TemurinImplementation.Hotspot,
|
||||
'jdk+jmods',
|
||||
'Java_Temurin-Hotspot_jdk+jmods'
|
||||
]
|
||||
])(
|
||||
'find right toolchain folder',
|
||||
(impl: TemurinImplementation, packageType: string, expected: string) => {
|
||||
(
|
||||
impl: TemurinImplementationType,
|
||||
packageType: string,
|
||||
expected: string
|
||||
) => {
|
||||
const distribution = new TemurinDistribution(
|
||||
{
|
||||
version: '8',
|
||||
@@ -181,6 +291,7 @@ describe('getAvailableVersions', () => {
|
||||
|
||||
it.each([
|
||||
['amd64', 'x64'],
|
||||
['arm', 'arm'],
|
||||
['arm64', 'aarch64']
|
||||
])(
|
||||
'defaults to os.arch(): %s mapped to distro arch: %s',
|
||||
@@ -237,6 +348,32 @@ describe('findPackageForDownload', () => {
|
||||
const resolvedVersion = await distribution['findPackageForDownload'](input);
|
||||
expect(resolvedVersion.version).toBe(expected);
|
||||
expect(resolvedVersion.signatureUrl).toBeDefined();
|
||||
const vendorPackage = (manifestData as any[]).find(
|
||||
item => item.version_data.semver === expected
|
||||
).binaries[0].package;
|
||||
expect(resolvedVersion.checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: vendorPackage.checksum,
|
||||
source: vendorPackage.checksum_link
|
||||
});
|
||||
});
|
||||
|
||||
it('version "latest" is normalized to the newest available version', async () => {
|
||||
const distribution = new TemurinDistribution(
|
||||
{
|
||||
version: 'latest',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
TemurinImplementation.Hotspot
|
||||
);
|
||||
distribution['getAvailableVersions'] = async () => manifestData as any;
|
||||
// normalizeVersion turns `latest` into the wildcard carried on `this.version`
|
||||
const resolvedVersion = await distribution['findPackageForDownload'](
|
||||
distribution['version']
|
||||
);
|
||||
expect(resolvedVersion.version).toBe('16.0.2+7');
|
||||
});
|
||||
|
||||
it('version is found but binaries list is empty', async () => {
|
||||
@@ -289,26 +426,29 @@ describe('findPackageForDownload', () => {
|
||||
});
|
||||
|
||||
describe('downloadTool', () => {
|
||||
let spyDownloadTool: jest.SpyInstance;
|
||||
let spyVerifySignature: jest.SpyInstance;
|
||||
let spyExtractJdkFile: jest.SpyInstance;
|
||||
let spyCacheDir: jest.SpyInstance;
|
||||
let spyReadDirSync: jest.SpyInstance;
|
||||
let spyRenameWinArchive: jest.SpyInstance;
|
||||
let spyDownloadTool: any;
|
||||
let spyVerifySignature: any;
|
||||
let spyExtractJdkFile: any;
|
||||
let spyCacheDir: any;
|
||||
let spyReadDirSync: any;
|
||||
let spyRenameWinArchive: any;
|
||||
let spyCopySync: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyDownloadTool = jest.spyOn(tc, 'downloadTool');
|
||||
spyDownloadTool = tc.downloadTool as jest.Mock;
|
||||
spyDownloadTool.mockResolvedValue('/tmp/jdk.tar.gz');
|
||||
spyVerifySignature = jest.spyOn(gpg, 'verifyPackageSignature');
|
||||
spyVerifySignature = gpg.verifyPackageSignature as jest.Mock;
|
||||
spyVerifySignature.mockResolvedValue(undefined);
|
||||
spyExtractJdkFile = jest.spyOn(util, 'extractJdkFile');
|
||||
spyExtractJdkFile = util.extractJdkFile as jest.Mock;
|
||||
spyExtractJdkFile.mockResolvedValue('/tmp/extracted');
|
||||
spyCacheDir = jest.spyOn(tc, 'cacheDir');
|
||||
spyCacheDir = tc.cacheDir as jest.Mock;
|
||||
spyCacheDir.mockResolvedValue('/tmp/toolcache');
|
||||
spyReadDirSync = jest.spyOn(fs, 'readdirSync');
|
||||
spyReadDirSync.mockReturnValue(['jdk-17'] as any);
|
||||
spyRenameWinArchive = jest.spyOn(util, 'renameWinArchive');
|
||||
spyRenameWinArchive = util.renameWinArchive as jest.Mock;
|
||||
spyRenameWinArchive.mockReturnValue('/tmp/jdk.tar.gz.zip');
|
||||
spyCopySync = jest.spyOn(fs, 'cpSync');
|
||||
spyCopySync.mockImplementation(() => undefined);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -342,6 +482,60 @@ describe('downloadTool', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('downloads and adds matching JMODs to the JDK', async () => {
|
||||
spyDownloadTool
|
||||
.mockResolvedValueOnce('/tmp/jdk.tar.gz')
|
||||
.mockResolvedValueOnce('/tmp/jmods.tar.gz');
|
||||
spyExtractJdkFile
|
||||
.mockResolvedValueOnce('/tmp/extracted')
|
||||
.mockResolvedValueOnce('/tmp/extracted-jmods');
|
||||
spyReadDirSync
|
||||
.mockReturnValueOnce(['jdk-25'] as any)
|
||||
.mockReturnValueOnce(['jdk-25-jmods'] as any);
|
||||
jest.spyOn(fs, 'existsSync').mockReturnValue(false);
|
||||
|
||||
const distribution = new TemurinDistribution(
|
||||
{
|
||||
version: '25',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk+jmods',
|
||||
checkLatest: false
|
||||
},
|
||||
TemurinImplementation.Hotspot
|
||||
);
|
||||
distribution['resolvePackage'] = jest.fn().mockResolvedValue({
|
||||
version: '25.0.3+9',
|
||||
url: 'https://example.com/jmods.tar.gz'
|
||||
});
|
||||
|
||||
await distribution['downloadTool']({
|
||||
version: '25.0.3+9',
|
||||
url: 'https://example.com/jdk.tar.gz'
|
||||
});
|
||||
|
||||
expect(distribution['resolvePackage']).toHaveBeenCalledWith(
|
||||
'25.0.3+9',
|
||||
'jmods'
|
||||
);
|
||||
expect(spyDownloadTool).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
'https://example.com/jmods.tar.gz'
|
||||
);
|
||||
expect(spyCopySync).toHaveBeenCalledWith(
|
||||
path.join('/tmp/extracted-jmods', 'jdk-25-jmods'),
|
||||
process.platform === 'darwin'
|
||||
? path.join('/tmp/extracted', 'jdk-25', 'Contents', 'Home', 'jmods')
|
||||
: path.join('/tmp/extracted', 'jdk-25', 'jmods'),
|
||||
{recursive: true}
|
||||
);
|
||||
expect(spyCacheDir).toHaveBeenCalledWith(
|
||||
path.join('/tmp/extracted', 'jdk-25'),
|
||||
'Java_Temurin-Hotspot_jdk+jmods',
|
||||
'25.0.3-9',
|
||||
'x64'
|
||||
);
|
||||
});
|
||||
|
||||
it('fails when signature is missing and verification is enabled', async () => {
|
||||
const distribution = new TemurinDistribution(
|
||||
{
|
||||
|
||||
@@ -1,33 +1,75 @@
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import type {IZuluVersions} from '../../src/distributions/zulu/models.js';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import {ZuluDistribution} from '../../src/distributions/zulu/installer';
|
||||
import {IZuluVersions} from '../../src/distributions/zulu/models';
|
||||
import * as utils from '../../src/util';
|
||||
import os from 'os';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import manifestData from '../data/zulu-releases-default.json';
|
||||
import manifestData from '../data/zulu-releases-default.json' with {type: 'json'};
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
const real_util_module = await import('../../src/util.js');
|
||||
jest.unstable_mockModule('../../src/util.js', () => ({
|
||||
...real_util_module,
|
||||
getDownloadArchiveExtension: jest.fn()
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const {ZuluDistribution} =
|
||||
await import('../../src/distributions/zulu/installer.js');
|
||||
const utils = await import('../../src/util.js');
|
||||
|
||||
describe('getAvailableVersions', () => {
|
||||
let spyHttpClient: jest.SpyInstance;
|
||||
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyHttpClient: any;
|
||||
let spyCoreError: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
spyHttpClient.mockReturnValue({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: manifestData as IZuluVersions[]
|
||||
result: [] as IZuluVersions[]
|
||||
});
|
||||
|
||||
spyUtilGetDownloadArchiveExtension = jest.spyOn(
|
||||
utils,
|
||||
'getDownloadArchiveExtension'
|
||||
(utils.getDownloadArchiveExtension as jest.Mock<any>).mockReturnValue(
|
||||
'tar.gz'
|
||||
);
|
||||
spyUtilGetDownloadArchiveExtension.mockReturnValue('tar.gz');
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -45,7 +87,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=macos&ext=tar.gz&bundle_type=jdk&javafx=false&arch=x86&hw_bitness=32&release_status=ga'
|
||||
'?os=macos&archive_type=tar.gz&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=i686&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -54,7 +96,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=macos&ext=tar.gz&bundle_type=jdk&javafx=false&arch=x86&hw_bitness=32&release_status=ea'
|
||||
'?os=macos&archive_type=tar.gz&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=i686&release_status=ea&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -63,7 +105,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=macos&ext=tar.gz&bundle_type=jdk&javafx=false&arch=x86&hw_bitness=64&release_status=ga'
|
||||
'?os=macos&archive_type=tar.gz&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=x64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -72,7 +114,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jre',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=macos&ext=tar.gz&bundle_type=jre&javafx=false&arch=x86&hw_bitness=64&release_status=ga'
|
||||
'?os=macos&archive_type=tar.gz&java_package_type=jre&javafx_bundled=false&crac_supported=false&arch=x64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -81,7 +123,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk+fx',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=macos&ext=tar.gz&bundle_type=jdk&javafx=true&arch=x86&hw_bitness=64&release_status=ga&features=fx'
|
||||
'?os=macos&archive_type=tar.gz&java_package_type=jdk&javafx_bundled=true&crac_supported=false&arch=x64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -90,7 +132,16 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jre+fx',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=macos&ext=tar.gz&bundle_type=jre&javafx=true&arch=x86&hw_bitness=64&release_status=ga&features=fx'
|
||||
'?os=macos&archive_type=tar.gz&java_package_type=jre&javafx_bundled=true&crac_supported=false&arch=x64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
version: '8',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk+crac',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=macos&archive_type=tar.gz&java_package_type=jdk&javafx_bundled=false&crac_supported=true&arch=x64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -99,7 +150,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=macos&ext=tar.gz&bundle_type=jdk&javafx=false&arch=arm&hw_bitness=64&release_status=ga'
|
||||
'?os=macos&archive_type=tar.gz&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=aarch64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -108,12 +159,12 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=macos&ext=tar.gz&bundle_type=jdk&javafx=false&arch=arm&hw_bitness=&release_status=ga'
|
||||
'?os=macos&archive_type=tar.gz&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=arm&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
]
|
||||
])('build correct url for %s -> %s', async (input, parsedUrl) => {
|
||||
const distribution = new ZuluDistribution(input);
|
||||
distribution['getPlatformOption'] = () => 'macos';
|
||||
const buildUrl = `https://api.azul.com/zulu/download/community/v1.0/bundles/${parsedUrl}`;
|
||||
const buildUrl = `https://api.azul.com/metadata/v1/zulu/packages/${parsedUrl}`;
|
||||
|
||||
await distribution['getAvailableVersions']();
|
||||
|
||||
@@ -121,16 +172,12 @@ describe('getAvailableVersions', () => {
|
||||
expect(spyHttpClient.mock.calls[0][0]).toBe(buildUrl);
|
||||
});
|
||||
|
||||
type DistroArch = {
|
||||
bitness: string;
|
||||
arch: string;
|
||||
};
|
||||
it.each([
|
||||
['amd64', {bitness: '64', arch: 'x86'}],
|
||||
['arm64', {bitness: '64', arch: 'arm'}]
|
||||
['amd64', 'x64'],
|
||||
['arm64', 'aarch64']
|
||||
])(
|
||||
'defaults to os.arch(): %s mapped to distro arch: %s',
|
||||
async (osArch: string, distroArch: DistroArch) => {
|
||||
async (osArch: string, distroArch: string) => {
|
||||
jest
|
||||
.spyOn(os, 'arch')
|
||||
.mockReturnValue(osArch as ReturnType<typeof os.arch>);
|
||||
@@ -142,7 +189,7 @@ describe('getAvailableVersions', () => {
|
||||
checkLatest: false
|
||||
});
|
||||
distribution['getPlatformOption'] = () => 'macos';
|
||||
const buildUrl = `https://api.azul.com/zulu/download/community/v1.0/bundles/?os=macos&ext=tar.gz&bundle_type=jdk&javafx=false&arch=${distroArch.arch}&hw_bitness=${distroArch.bitness}&release_status=ga`;
|
||||
const buildUrl = `https://api.azul.com/metadata/v1/zulu/packages/?os=macos&archive_type=tar.gz&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=${distroArch}&release_status=ga&availability_types=ca&page=1&page_size=100`;
|
||||
|
||||
await distribution['getAvailableVersions']();
|
||||
|
||||
@@ -152,6 +199,18 @@ describe('getAvailableVersions', () => {
|
||||
);
|
||||
|
||||
it('load available versions', async () => {
|
||||
spyHttpClient
|
||||
.mockReturnValueOnce({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: manifestData as IZuluVersions[]
|
||||
})
|
||||
.mockReturnValueOnce({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: [] as IZuluVersions[]
|
||||
});
|
||||
|
||||
const distribution = new ZuluDistribution({
|
||||
version: '11',
|
||||
architecture: 'x86',
|
||||
@@ -165,10 +224,11 @@ describe('getAvailableVersions', () => {
|
||||
|
||||
describe('getArchitectureOptions', () => {
|
||||
it.each([
|
||||
[{architecture: 'x64'}, {arch: 'x86', hw_bitness: '64', abi: ''}],
|
||||
[{architecture: 'x86'}, {arch: 'x86', hw_bitness: '32', abi: ''}],
|
||||
[{architecture: 'x32'}, {arch: 'x32', hw_bitness: '', abi: ''}],
|
||||
[{architecture: 'arm'}, {arch: 'arm', hw_bitness: '', abi: ''}]
|
||||
[{architecture: 'x64'}, 'x64'],
|
||||
[{architecture: 'x86'}, 'i686'],
|
||||
[{architecture: 'aarch64'}, 'aarch64'],
|
||||
[{architecture: 'arm64'}, 'aarch64'],
|
||||
[{architecture: 'arm'}, 'arm']
|
||||
])('%s -> %s', (input, expected) => {
|
||||
const distribution = new ZuluDistribution({
|
||||
version: '11',
|
||||
@@ -176,11 +236,31 @@ describe('getArchitectureOptions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
expect(distribution['getArchitectureOptions']()).toEqual(expected);
|
||||
expect(distribution['getArchitectureOptions']()).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findPackageForDownload', () => {
|
||||
let spyPackageDetails: any;
|
||||
|
||||
const ZULU_CHECKSUM = 'a'.repeat(64);
|
||||
|
||||
beforeEach(() => {
|
||||
// The resolved winning package fetches sha256_hash from the Azul
|
||||
// package-details endpoint; stub it so tests never reach the real
|
||||
// network.
|
||||
spyPackageDetails = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
spyPackageDetails.mockResolvedValue({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: {sha256_hash: ZULU_CHECKSUM}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it.each([
|
||||
['8', '8.0.282+8'],
|
||||
['11.x', '11.0.10+9'],
|
||||
@@ -219,6 +299,38 @@ describe('findPackageForDownload', () => {
|
||||
expect(result.url).toBe(
|
||||
'https://cdn.azul.com/zulu/bin/zulu11.35.15-ca-jdk11.0.5-macosx_x64.tar.gz'
|
||||
);
|
||||
expect(result.checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: ZULU_CHECKSUM,
|
||||
source: 'https://api.azul.com/metadata/v1/zulu/packages/test-uuid-10933'
|
||||
});
|
||||
// Only the winning package's UUID triggers a details request.
|
||||
expect(spyPackageDetails).toHaveBeenCalledWith(
|
||||
'https://api.azul.com/metadata/v1/zulu/packages/test-uuid-10933'
|
||||
);
|
||||
expect(spyPackageDetails).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('skips checksum verification when sha256_hash is missing or malformed', async () => {
|
||||
spyPackageDetails.mockResolvedValue({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: {sha256_hash: 'not-a-valid-digest'}
|
||||
});
|
||||
|
||||
const distribution = new ZuluDistribution({
|
||||
version: '',
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
distribution['getAvailableVersions'] = async () => manifestData;
|
||||
const result = await distribution['findPackageForDownload']('11.0.5');
|
||||
|
||||
expect(result.checksum).toBeUndefined();
|
||||
expect(core.debug).toHaveBeenCalledWith(
|
||||
expect.stringContaining('No authoritative sha256 checksum')
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error', async () => {
|
||||
|
||||
@@ -1,34 +1,77 @@
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import type {IZuluVersions} from '../../src/distributions/zulu/models.js';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import * as semver from 'semver';
|
||||
import {ZuluDistribution} from '../../src/distributions/zulu/installer';
|
||||
import {IZuluVersions} from '../../src/distributions/zulu/models';
|
||||
import * as utils from '../../src/util';
|
||||
import os from 'os';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import manifestData from '../data/zulu-linux.json';
|
||||
import manifestData from '../data/zulu-linux.json' with {type: 'json'};
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
const real_util_module = await import('../../src/util.js');
|
||||
jest.unstable_mockModule('../../src/util.js', () => ({
|
||||
...real_util_module,
|
||||
getDownloadArchiveExtension: jest.fn()
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const {ZuluDistribution} =
|
||||
await import('../../src/distributions/zulu/installer.js');
|
||||
const utils = await import('../../src/util.js');
|
||||
|
||||
describe('getAvailableVersions', () => {
|
||||
let spyHttpClient: jest.SpyInstance;
|
||||
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyHttpClient: any;
|
||||
let spyUtilGetDownloadArchiveExtension: any;
|
||||
let spyCoreError: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
spyHttpClient.mockReturnValue({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: manifestData as IZuluVersions[]
|
||||
result: [] as IZuluVersions[]
|
||||
});
|
||||
|
||||
spyUtilGetDownloadArchiveExtension = jest.spyOn(
|
||||
utils,
|
||||
'getDownloadArchiveExtension'
|
||||
);
|
||||
spyUtilGetDownloadArchiveExtension =
|
||||
utils.getDownloadArchiveExtension as jest.Mock<any>;
|
||||
spyUtilGetDownloadArchiveExtension.mockReturnValue('zip');
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -46,7 +89,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=linux&ext=zip&bundle_type=jdk&javafx=false&arch=x86&hw_bitness=32&release_status=ga'
|
||||
'?os=linux_glibc&archive_type=zip&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=i686&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -55,7 +98,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=linux&ext=zip&bundle_type=jdk&javafx=false&arch=x86&hw_bitness=32&release_status=ea'
|
||||
'?os=linux_glibc&archive_type=zip&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=i686&release_status=ea&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -64,7 +107,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=linux&ext=zip&bundle_type=jdk&javafx=false&arch=x86&hw_bitness=64&release_status=ga'
|
||||
'?os=linux_glibc&archive_type=zip&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=x64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -73,7 +116,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jre',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=linux&ext=zip&bundle_type=jre&javafx=false&arch=x86&hw_bitness=64&release_status=ga'
|
||||
'?os=linux_glibc&archive_type=zip&java_package_type=jre&javafx_bundled=false&crac_supported=false&arch=x64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -82,7 +125,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk+fx',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=linux&ext=zip&bundle_type=jdk&javafx=true&arch=x86&hw_bitness=64&release_status=ga&features=fx'
|
||||
'?os=linux_glibc&archive_type=zip&java_package_type=jdk&javafx_bundled=true&crac_supported=false&arch=x64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -91,7 +134,16 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jre+fx',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=linux&ext=zip&bundle_type=jre&javafx=true&arch=x86&hw_bitness=64&release_status=ga&features=fx'
|
||||
'?os=linux_glibc&archive_type=zip&java_package_type=jre&javafx_bundled=true&crac_supported=false&arch=x64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
version: '8',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk+crac',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=linux_glibc&archive_type=zip&java_package_type=jdk&javafx_bundled=false&crac_supported=true&arch=x64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -100,7 +152,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=linux&ext=zip&bundle_type=jdk&javafx=false&arch=arm&hw_bitness=64&release_status=ga'
|
||||
'?os=linux_glibc&archive_type=zip&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=aarch64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -109,12 +161,12 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=linux&ext=zip&bundle_type=jdk&javafx=false&arch=arm&hw_bitness=&release_status=ga'
|
||||
'?os=linux_glibc&archive_type=zip&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=arm&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
]
|
||||
])('build correct url for %s -> %s', async (input, parsedUrl) => {
|
||||
const distribution = new ZuluDistribution(input);
|
||||
distribution['getPlatformOption'] = () => 'linux';
|
||||
const buildUrl = `https://api.azul.com/zulu/download/community/v1.0/bundles/${parsedUrl}`;
|
||||
distribution['getPlatformOption'] = () => 'linux_glibc';
|
||||
const buildUrl = `https://api.azul.com/metadata/v1/zulu/packages/${parsedUrl}`;
|
||||
|
||||
await distribution['getAvailableVersions']();
|
||||
|
||||
@@ -122,16 +174,12 @@ describe('getAvailableVersions', () => {
|
||||
expect(spyHttpClient.mock.calls[0][0]).toBe(buildUrl);
|
||||
});
|
||||
|
||||
type DistroArch = {
|
||||
bitness: string;
|
||||
arch: string;
|
||||
};
|
||||
it.each([
|
||||
['amd64', {bitness: '64', arch: 'x86'}],
|
||||
['arm64', {bitness: '64', arch: 'arm'}]
|
||||
['amd64', 'x64'],
|
||||
['arm64', 'aarch64']
|
||||
])(
|
||||
'defaults to os.arch(): %s mapped to distro arch: %s',
|
||||
async (osArch: string, distroArch: DistroArch) => {
|
||||
async (osArch: string, distroArch: string) => {
|
||||
jest
|
||||
.spyOn(os, 'arch')
|
||||
.mockReturnValue(osArch as ReturnType<typeof os.arch>);
|
||||
@@ -142,10 +190,10 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
distribution['getPlatformOption'] = () => 'linux';
|
||||
distribution['getPlatformOption'] = () => 'linux_glibc';
|
||||
// Override extension for linux default arch case to match util behavior
|
||||
spyUtilGetDownloadArchiveExtension.mockReturnValue('tar.gz');
|
||||
const buildUrl = `https://api.azul.com/zulu/download/community/v1.0/bundles/?os=linux&ext=tar.gz&bundle_type=jdk&javafx=false&arch=${distroArch.arch}&hw_bitness=${distroArch.bitness}&release_status=ga`;
|
||||
const buildUrl = `https://api.azul.com/metadata/v1/zulu/packages/?os=linux_glibc&archive_type=tar.gz&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=${distroArch}&release_status=ga&availability_types=ca&page=1&page_size=100`;
|
||||
|
||||
await distribution['getAvailableVersions']();
|
||||
|
||||
@@ -155,6 +203,18 @@ describe('getAvailableVersions', () => {
|
||||
);
|
||||
|
||||
it('load available versions', async () => {
|
||||
spyHttpClient
|
||||
.mockReturnValueOnce({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: manifestData as IZuluVersions[]
|
||||
})
|
||||
.mockReturnValueOnce({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: [] as IZuluVersions[]
|
||||
});
|
||||
|
||||
const distribution = new ZuluDistribution({
|
||||
version: '11',
|
||||
architecture: 'x86',
|
||||
@@ -168,10 +228,11 @@ describe('getAvailableVersions', () => {
|
||||
|
||||
describe('getArchitectureOptions', () => {
|
||||
it.each([
|
||||
[{architecture: 'x64'}, {arch: 'x86', hw_bitness: '64', abi: ''}],
|
||||
[{architecture: 'x86'}, {arch: 'x86', hw_bitness: '32', abi: ''}],
|
||||
[{architecture: 'x32'}, {arch: 'x32', hw_bitness: '', abi: ''}],
|
||||
[{architecture: 'arm'}, {arch: 'arm', hw_bitness: '', abi: ''}]
|
||||
[{architecture: 'x64'}, 'x64'],
|
||||
[{architecture: 'x86'}, 'i686'],
|
||||
[{architecture: 'aarch64'}, 'aarch64'],
|
||||
[{architecture: 'arm64'}, 'aarch64'],
|
||||
[{architecture: 'arm'}, 'arm']
|
||||
])('%s -> %s', (input, expected) => {
|
||||
const distribution = new ZuluDistribution({
|
||||
version: '11',
|
||||
@@ -179,11 +240,31 @@ describe('getArchitectureOptions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
expect(distribution['getArchitectureOptions']()).toEqual(expected);
|
||||
expect(distribution['getArchitectureOptions']()).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findPackageForDownload', () => {
|
||||
let spyPackageDetails: any;
|
||||
|
||||
const ZULU_CHECKSUM = 'a'.repeat(64);
|
||||
|
||||
beforeEach(() => {
|
||||
// The resolved winning package fetches sha256_hash from the Azul
|
||||
// package-details endpoint; stub it so tests never reach the real
|
||||
// network.
|
||||
spyPackageDetails = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
spyPackageDetails.mockResolvedValue({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: {sha256_hash: ZULU_CHECKSUM}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it.each([
|
||||
['8', '8.0.282+8'],
|
||||
['11.x', '11.0.10+9'],
|
||||
@@ -222,6 +303,38 @@ describe('findPackageForDownload', () => {
|
||||
expect(result.url).toBe(
|
||||
'https://cdn.azul.com/zulu/bin/zulu21.32.17-ca-jdk21.0.2-linux_aarch64.tar.gz'
|
||||
);
|
||||
expect(result.checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: ZULU_CHECKSUM,
|
||||
source: 'https://api.azul.com/metadata/v1/zulu/packages/test-uuid-12447'
|
||||
});
|
||||
// Only the winning package's UUID triggers a details request.
|
||||
expect(spyPackageDetails).toHaveBeenCalledWith(
|
||||
'https://api.azul.com/metadata/v1/zulu/packages/test-uuid-12447'
|
||||
);
|
||||
expect(spyPackageDetails).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('skips checksum verification when sha256_hash is missing or malformed', async () => {
|
||||
spyPackageDetails.mockResolvedValue({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: {}
|
||||
});
|
||||
|
||||
const distribution = new ZuluDistribution({
|
||||
version: '',
|
||||
architecture: 'arm64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
distribution['getAvailableVersions'] = async () => manifestData;
|
||||
const result = await distribution['findPackageForDownload']('21.0.2');
|
||||
|
||||
expect(result.checksum).toBeUndefined();
|
||||
expect(core.debug).toHaveBeenCalledWith(
|
||||
expect.stringContaining('No authoritative sha256 checksum')
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error', async () => {
|
||||
|
||||
@@ -1,34 +1,76 @@
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import type {IZuluVersions} from '../../src/distributions/zulu/models.js';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
import * as semver from 'semver';
|
||||
import {ZuluDistribution} from '../../src/distributions/zulu/installer';
|
||||
import {IZuluVersions} from '../../src/distributions/zulu/models';
|
||||
import * as utils from '../../src/util';
|
||||
import os from 'os';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import manifestData from '../data/zulu-windows.json';
|
||||
import manifestData from '../data/zulu-windows.json' with {type: 'json'};
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((p: string) => p),
|
||||
toWin32Path: jest.fn((p: string) => p),
|
||||
toPosixPath: jest.fn((p: string) => p)
|
||||
}));
|
||||
|
||||
const real_util_module = await import('../../src/util.js');
|
||||
jest.unstable_mockModule('../../src/util.js', () => ({
|
||||
...real_util_module,
|
||||
getDownloadArchiveExtension: jest.fn()
|
||||
}));
|
||||
|
||||
// Dynamic imports after mocking
|
||||
const core = await import('@actions/core');
|
||||
const {ZuluDistribution} =
|
||||
await import('../../src/distributions/zulu/installer.js');
|
||||
const utils = await import('../../src/util.js');
|
||||
|
||||
describe('getAvailableVersions', () => {
|
||||
let spyHttpClient: jest.SpyInstance;
|
||||
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
|
||||
let spyCoreError: jest.SpyInstance;
|
||||
let spyHttpClient: any;
|
||||
let spyCoreError: any;
|
||||
|
||||
beforeEach(() => {
|
||||
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
spyHttpClient.mockReturnValue({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: manifestData as IZuluVersions[]
|
||||
result: [] as IZuluVersions[]
|
||||
});
|
||||
|
||||
spyUtilGetDownloadArchiveExtension = jest.spyOn(
|
||||
utils,
|
||||
'getDownloadArchiveExtension'
|
||||
(utils.getDownloadArchiveExtension as jest.Mock<any>).mockReturnValue(
|
||||
'zip'
|
||||
);
|
||||
spyUtilGetDownloadArchiveExtension.mockReturnValue('zip');
|
||||
|
||||
// Mock core.error to suppress error logs
|
||||
spyCoreError = jest.spyOn(core, 'error');
|
||||
spyCoreError = core.error as jest.Mock;
|
||||
spyCoreError.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
@@ -46,7 +88,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=windows&ext=zip&bundle_type=jdk&javafx=false&arch=x86&hw_bitness=32&release_status=ga'
|
||||
'?os=windows&archive_type=zip&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=i686&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -55,7 +97,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=windows&ext=zip&bundle_type=jdk&javafx=false&arch=x86&hw_bitness=32&release_status=ea'
|
||||
'?os=windows&archive_type=zip&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=i686&release_status=ea&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -64,7 +106,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=windows&ext=zip&bundle_type=jdk&javafx=false&arch=x86&hw_bitness=64&release_status=ga'
|
||||
'?os=windows&archive_type=zip&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=x64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -73,7 +115,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jre',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=windows&ext=zip&bundle_type=jre&javafx=false&arch=x86&hw_bitness=64&release_status=ga'
|
||||
'?os=windows&archive_type=zip&java_package_type=jre&javafx_bundled=false&crac_supported=false&arch=x64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -82,7 +124,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk+fx',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=windows&ext=zip&bundle_type=jdk&javafx=true&arch=x86&hw_bitness=64&release_status=ga&features=fx'
|
||||
'?os=windows&archive_type=zip&java_package_type=jdk&javafx_bundled=true&crac_supported=false&arch=x64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -91,7 +133,16 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jre+fx',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=windows&ext=zip&bundle_type=jre&javafx=true&arch=x86&hw_bitness=64&release_status=ga&features=fx'
|
||||
'?os=windows&archive_type=zip&java_package_type=jre&javafx_bundled=true&crac_supported=false&arch=x64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
version: '8',
|
||||
architecture: 'x64',
|
||||
packageType: 'jdk+crac',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=windows&archive_type=zip&java_package_type=jdk&javafx_bundled=false&crac_supported=true&arch=x64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -100,7 +151,7 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=windows&ext=zip&bundle_type=jdk&javafx=false&arch=arm&hw_bitness=64&release_status=ga'
|
||||
'?os=windows&archive_type=zip&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=aarch64&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
],
|
||||
[
|
||||
{
|
||||
@@ -109,12 +160,12 @@ describe('getAvailableVersions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
},
|
||||
'?os=windows&ext=zip&bundle_type=jdk&javafx=false&arch=arm&hw_bitness=&release_status=ga'
|
||||
'?os=windows&archive_type=zip&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=arm&release_status=ga&availability_types=ca&page=1&page_size=100'
|
||||
]
|
||||
])('build correct url for %s -> %s', async (input, parsedUrl) => {
|
||||
const distribution = new ZuluDistribution(input);
|
||||
distribution['getPlatformOption'] = () => 'windows';
|
||||
const buildUrl = `https://api.azul.com/zulu/download/community/v1.0/bundles/${parsedUrl}`;
|
||||
const buildUrl = `https://api.azul.com/metadata/v1/zulu/packages/${parsedUrl}`;
|
||||
|
||||
await distribution['getAvailableVersions']();
|
||||
|
||||
@@ -122,16 +173,12 @@ describe('getAvailableVersions', () => {
|
||||
expect(spyHttpClient.mock.calls[0][0]).toBe(buildUrl);
|
||||
});
|
||||
|
||||
type DistroArch = {
|
||||
bitness: string;
|
||||
arch: string;
|
||||
};
|
||||
it.each([
|
||||
['amd64', {bitness: '64', arch: 'x86'}],
|
||||
['arm64', {bitness: '64', arch: 'arm'}]
|
||||
['amd64', 'x64'],
|
||||
['arm64', 'aarch64']
|
||||
])(
|
||||
'defaults to os.arch(): %s mapped to distro arch: %s',
|
||||
async (osArch: string, distroArch: DistroArch) => {
|
||||
async (osArch: string, distroArch: string) => {
|
||||
jest
|
||||
.spyOn(os, 'arch')
|
||||
.mockReturnValue(osArch as ReturnType<typeof os.arch>);
|
||||
@@ -143,7 +190,7 @@ describe('getAvailableVersions', () => {
|
||||
checkLatest: false
|
||||
});
|
||||
distribution['getPlatformOption'] = () => 'windows';
|
||||
const buildUrl = `https://api.azul.com/zulu/download/community/v1.0/bundles/?os=windows&ext=zip&bundle_type=jdk&javafx=false&arch=${distroArch.arch}&hw_bitness=${distroArch.bitness}&release_status=ga`;
|
||||
const buildUrl = `https://api.azul.com/metadata/v1/zulu/packages/?os=windows&archive_type=zip&java_package_type=jdk&javafx_bundled=false&crac_supported=false&arch=${distroArch}&release_status=ga&availability_types=ca&page=1&page_size=100`;
|
||||
|
||||
await distribution['getAvailableVersions']();
|
||||
|
||||
@@ -153,6 +200,18 @@ describe('getAvailableVersions', () => {
|
||||
);
|
||||
|
||||
it('load available versions', async () => {
|
||||
spyHttpClient
|
||||
.mockReturnValueOnce({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: manifestData as IZuluVersions[]
|
||||
})
|
||||
.mockReturnValueOnce({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: [] as IZuluVersions[]
|
||||
});
|
||||
|
||||
const distribution = new ZuluDistribution({
|
||||
version: '11',
|
||||
architecture: 'x86',
|
||||
@@ -166,10 +225,11 @@ describe('getAvailableVersions', () => {
|
||||
|
||||
describe('getArchitectureOptions', () => {
|
||||
it.each([
|
||||
[{architecture: 'x64'}, {arch: 'x86', hw_bitness: '64', abi: ''}],
|
||||
[{architecture: 'x86'}, {arch: 'x86', hw_bitness: '32', abi: ''}],
|
||||
[{architecture: 'x32'}, {arch: 'x32', hw_bitness: '', abi: ''}],
|
||||
[{architecture: 'arm'}, {arch: 'arm', hw_bitness: '', abi: ''}]
|
||||
[{architecture: 'x64'}, 'x64'],
|
||||
[{architecture: 'x86'}, 'i686'],
|
||||
[{architecture: 'aarch64'}, 'aarch64'],
|
||||
[{architecture: 'arm64'}, 'aarch64'],
|
||||
[{architecture: 'arm'}, 'arm']
|
||||
])('%s -> %s', (input, expected) => {
|
||||
const distribution = new ZuluDistribution({
|
||||
version: '11',
|
||||
@@ -177,11 +237,31 @@ describe('getArchitectureOptions', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
expect(distribution['getArchitectureOptions']()).toEqual(expected);
|
||||
expect(distribution['getArchitectureOptions']()).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findPackageForDownload', () => {
|
||||
let spyPackageDetails: any;
|
||||
|
||||
const ZULU_CHECKSUM = 'a'.repeat(64);
|
||||
|
||||
beforeEach(() => {
|
||||
// The resolved winning package fetches sha256_hash from the Azul
|
||||
// package-details endpoint; stub it so tests never reach the real
|
||||
// network.
|
||||
spyPackageDetails = jest.spyOn(HttpClient.prototype, 'getJson');
|
||||
spyPackageDetails.mockResolvedValue({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: {sha256_hash: ZULU_CHECKSUM}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it.each([
|
||||
['8', '8.0.282+8'],
|
||||
['11.x', '11.0.10+9'],
|
||||
@@ -220,6 +300,38 @@ describe('findPackageForDownload', () => {
|
||||
expect(result.url).toBe(
|
||||
'https://cdn.azul.com/zulu/bin/zulu17.48.15-ca-jdk17.0.10-windows_aarch64.zip'
|
||||
);
|
||||
expect(result.checksum).toEqual({
|
||||
algorithm: 'sha256',
|
||||
value: ZULU_CHECKSUM,
|
||||
source: 'https://api.azul.com/metadata/v1/zulu/packages/test-uuid-12446'
|
||||
});
|
||||
// Only the winning package's UUID triggers a details request.
|
||||
expect(spyPackageDetails).toHaveBeenCalledWith(
|
||||
'https://api.azul.com/metadata/v1/zulu/packages/test-uuid-12446'
|
||||
);
|
||||
expect(spyPackageDetails).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('skips checksum verification when sha256_hash is missing or malformed', async () => {
|
||||
spyPackageDetails.mockResolvedValue({
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
result: {sha256_hash: '123'}
|
||||
});
|
||||
|
||||
const distribution = new ZuluDistribution({
|
||||
version: '',
|
||||
architecture: 'arm64',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false
|
||||
});
|
||||
distribution['getAvailableVersions'] = async () => manifestData;
|
||||
const result = await distribution['findPackageForDownload']('17.0.10');
|
||||
|
||||
expect(result.checksum).toBeUndefined();
|
||||
expect(core.debug).toHaveBeenCalledWith(
|
||||
expect.stringContaining('No authoritative sha256 checksum')
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error', async () => {
|
||||
|
||||
+25
-14
@@ -1,20 +1,29 @@
|
||||
import {
|
||||
jest,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterAll,
|
||||
afterEach
|
||||
} from '@jest/globals';
|
||||
import {fileURLToPath} from 'url';
|
||||
import * as path from 'path';
|
||||
import * as io from '@actions/io';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as gpg from '../src/gpg';
|
||||
|
||||
jest.mock('@actions/exec', () => {
|
||||
return {
|
||||
exec: jest.fn()
|
||||
};
|
||||
});
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
jest.mock('@actions/tool-cache', () => {
|
||||
return {
|
||||
downloadTool: jest.fn()
|
||||
};
|
||||
});
|
||||
jest.unstable_mockModule('@actions/exec', () => ({
|
||||
exec: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('@actions/tool-cache', () => ({
|
||||
downloadTool: jest.fn()
|
||||
}));
|
||||
|
||||
const exec = await import('@actions/exec');
|
||||
const tc = await import('@actions/tool-cache');
|
||||
const gpg = await import('../src/gpg.js');
|
||||
|
||||
const tempDir = path.join(__dirname, 'runner', 'temp');
|
||||
process.env['RUNNER_TEMP'] = tempDir;
|
||||
@@ -92,7 +101,9 @@ describe('gpg tests', () => {
|
||||
it('imports bundled key and verifies package', async () => {
|
||||
const publicKeyContent =
|
||||
'-----BEGIN PGP PUBLIC KEY BLOCK-----\ntest\n-----END PGP PUBLIC KEY BLOCK-----';
|
||||
(tc.downloadTool as jest.Mock).mockResolvedValue('/tmp/jdk.tar.gz.sig');
|
||||
(tc.downloadTool as jest.Mock<any>).mockResolvedValue(
|
||||
'/tmp/jdk.tar.gz.sig'
|
||||
);
|
||||
await gpg.verifyPackageSignature(
|
||||
'/tmp/jdk.tar.gz',
|
||||
'https://example.com/jdk.tar.gz.sig',
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import {
|
||||
JAVA_PACKAGE_CAPABILITIES,
|
||||
JavaDistribution
|
||||
} from '../src/distributions/package-types.js';
|
||||
|
||||
const repositoryRoot = process.cwd();
|
||||
const readRepositoryFile = (filePath: string) =>
|
||||
fs.readFileSync(path.join(repositoryRoot, filePath), 'utf8');
|
||||
const allPackageTypes = [
|
||||
...new Set(Object.values(JAVA_PACKAGE_CAPABILITIES).flat())
|
||||
];
|
||||
|
||||
describe('java-package published contract', () => {
|
||||
it.each(['action.yml', 'README.md'])(
|
||||
'documents every supported package type in %s',
|
||||
filePath => {
|
||||
const content = readRepositoryFile(filePath);
|
||||
const contractLine =
|
||||
filePath === 'action.yml'
|
||||
? content.match(/ {2}java-package:\n(?: {4}.+\n)+/)?.[0]
|
||||
: content
|
||||
.split('\n')
|
||||
.find(line => line.includes('- `java-package`:'));
|
||||
|
||||
expect(contractLine).toBeDefined();
|
||||
for (const packageType of allPackageTypes) {
|
||||
expect(contractLine).toContain(`\`${packageType}\``);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
it.each(Object.entries(JAVA_PACKAGE_CAPABILITIES))(
|
||||
'keeps the advanced compatibility table aligned for %s',
|
||||
(distributionName, packageTypes) => {
|
||||
const advancedUsage = readRepositoryFile('docs/advanced-usage.md');
|
||||
const compatibilityTable = advancedUsage.slice(
|
||||
advancedUsage.indexOf('### Package compatibility')
|
||||
);
|
||||
const compatibilityRow = compatibilityTable
|
||||
.split('\n')
|
||||
.find(
|
||||
line =>
|
||||
line.startsWith('|') && line.includes(`\`${distributionName}\``)
|
||||
);
|
||||
|
||||
expect(compatibilityRow).toBeDefined();
|
||||
for (const packageType of packageTypes) {
|
||||
expect(compatibilityRow).toContain(`\`${packageType}\``);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
it('only exercises supported distribution/package combinations in E2E', () => {
|
||||
const workflow = readRepositoryFile('.github/workflows/e2e-versions.yml');
|
||||
const defaultMatrix = workflow.match(
|
||||
/distribution:\s*\n\s*\[([^\]]+)\]\s*\n\s*java-package:\s*\['([^']+)'\]/
|
||||
);
|
||||
expect(defaultMatrix).not.toBeNull();
|
||||
|
||||
const defaultDistributions = [
|
||||
...defaultMatrix![1].matchAll(/'([^']+)'/g)
|
||||
].map(match => match[1]);
|
||||
const defaultPackage = defaultMatrix![2];
|
||||
for (const distributionName of defaultDistributions) {
|
||||
expect(supportedPackagesFor(distributionName)).toContain(defaultPackage);
|
||||
}
|
||||
|
||||
const includedPackages = workflow.matchAll(
|
||||
/- distribution: '([^']+)'\s*\n\s*java-package: ([^\s]+)/g
|
||||
);
|
||||
for (const match of includedPackages) {
|
||||
const [, distributionName, packageType] = match;
|
||||
expect(supportedPackagesFor(distributionName)).toContain(packageType);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function supportedPackagesFor(distributionName: string): readonly string[] {
|
||||
return JAVA_PACKAGE_CAPABILITIES[distributionName as JavaDistribution] ?? [];
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import {
|
||||
JAVA_PLATFORM_CAPABILITIES,
|
||||
normalizeArchitecture,
|
||||
validateJavaPlatform
|
||||
} from '../src/distributions/platform-types.js';
|
||||
import {JavaDistribution} from '../src/distributions/package-types.js';
|
||||
|
||||
describe('Java platform capabilities', () => {
|
||||
it('declares a capability for every distribution', () => {
|
||||
expect(Object.keys(JAVA_PLATFORM_CAPABILITIES).sort()).toEqual(
|
||||
Object.values(JavaDistribution).sort()
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
['x64', 'x64'],
|
||||
['amd64', 'x64'],
|
||||
['x86', 'x86'],
|
||||
['ia32', 'x86'],
|
||||
['arm', 'armv7'],
|
||||
['aarch64', 'aarch64'],
|
||||
['arm64', 'aarch64'],
|
||||
['ppc64le', 'ppc64le'],
|
||||
['s390x', 's390x']
|
||||
])('normalizes architecture %s to %s', (input, expected) => {
|
||||
expect(normalizeArchitecture(input)).toBe(expected);
|
||||
});
|
||||
|
||||
it('uses the normalized architecture for validation', () => {
|
||||
expect(validateJavaPlatform('microsoft', 'linux', 'arm64', '25')).toBe(
|
||||
'aarch64'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects OS-specific restrictions with a consistent diagnostic', () => {
|
||||
expect(() =>
|
||||
validateJavaPlatform('oracle', 'win32', 'arm64', '21')
|
||||
).toThrow(
|
||||
"Distribution 'oracle' does not support operating system 'windows' with architecture 'aarch64' for Java version '21'. Supported combinations: linux (x64, aarch64); macos (x64, aarch64); windows (x64)."
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects version-dependent architecture restrictions', () => {
|
||||
expect(() =>
|
||||
validateJavaPlatform('corretto', 'linux', 'x86', '17')
|
||||
).toThrow(/x86 \(<12\)/);
|
||||
expect(() =>
|
||||
validateJavaPlatform('corretto', 'linux', 'x86', '17.0.2.8.1')
|
||||
).toThrow(/x86 \(<12\)/);
|
||||
expect(validateJavaPlatform('corretto', 'linux', 'x86', '11')).toBe('x86');
|
||||
});
|
||||
|
||||
it.each(['corretto', 'kona'])(
|
||||
'rejects Windows aarch64 for %s',
|
||||
distributionName => {
|
||||
expect(() =>
|
||||
validateJavaPlatform(distributionName, 'win32', 'arm64', '21')
|
||||
).toThrow(/does not support operating system 'windows'/);
|
||||
}
|
||||
);
|
||||
|
||||
it('keeps Adopt HotSpot aliases aligned with the Temurin-first resolver', () => {
|
||||
expect(validateJavaPlatform('adopt', 'darwin', 'arm64', '21')).toBe(
|
||||
'aarch64'
|
||||
);
|
||||
expect(validateJavaPlatform('adopt-hotspot', 'win32', 'arm64', '21')).toBe(
|
||||
'aarch64'
|
||||
);
|
||||
expect(() =>
|
||||
validateJavaPlatform('adopt-openj9', 'darwin', 'arm64', '16')
|
||||
).toThrow(/does not support operating system 'macos'/);
|
||||
});
|
||||
|
||||
it('allows local archives on any platform and architecture', () => {
|
||||
expect(validateJavaPlatform('jdkfile', 'aix', 'mips64', '21')).toBe(
|
||||
'mips64'
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps the documented architecture contract aligned', () => {
|
||||
const repositoryRoot = process.cwd();
|
||||
const readRepositoryFile = (filePath: string) =>
|
||||
fs.readFileSync(path.join(repositoryRoot, filePath), 'utf8');
|
||||
|
||||
for (const filePath of ['action.yml', 'README.md']) {
|
||||
const content = readRepositoryFile(filePath);
|
||||
for (const architecture of [
|
||||
'x86',
|
||||
'x64',
|
||||
'armv7',
|
||||
'aarch64',
|
||||
'ppc64le',
|
||||
'ppc64',
|
||||
's390x'
|
||||
]) {
|
||||
expect(content).toContain(architecture);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it.each(Object.entries(JAVA_PLATFORM_CAPABILITIES))(
|
||||
'keeps the advanced compatibility table aligned for %s',
|
||||
(distributionName, capability) => {
|
||||
const advancedUsage = fs.readFileSync(
|
||||
path.join(process.cwd(), 'docs/advanced-usage.md'),
|
||||
'utf8'
|
||||
);
|
||||
const compatibilityTable = advancedUsage.slice(
|
||||
advancedUsage.indexOf('## Platform and architecture compatibility')
|
||||
);
|
||||
const compatibilityRow = compatibilityTable
|
||||
.split('\n')
|
||||
.find(
|
||||
line =>
|
||||
line.startsWith('|') && line.includes(`\`${distributionName}\``)
|
||||
);
|
||||
|
||||
expect(compatibilityRow).toBeDefined();
|
||||
if (!('platforms' in capability)) {
|
||||
expect(compatibilityRow).toContain('Any');
|
||||
return;
|
||||
}
|
||||
|
||||
const architectures = new Set(
|
||||
Object.values(capability.platforms)
|
||||
.flat()
|
||||
.map(item => (typeof item === 'string' ? item : item.architecture))
|
||||
);
|
||||
for (const architecture of architectures) {
|
||||
expect(compatibilityRow).toContain(`\`${architecture}\``);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -1,42 +1,68 @@
|
||||
import * as core from '@actions/core';
|
||||
import {afterEach, beforeEach, describe, expect, it, jest} from '@jest/globals';
|
||||
|
||||
import {configureMavenArgs} from '../src/maven-args';
|
||||
import {
|
||||
const mockGetInput = jest.fn<(...args: any[]) => any>();
|
||||
const mockExportVariable = jest.fn<(...args: any[]) => any>();
|
||||
const mockInfo = jest.fn<(...args: any[]) => any>();
|
||||
const mockDebug = jest.fn<(...args: any[]) => any>();
|
||||
const mockWarning = jest.fn<(...args: any[]) => any>();
|
||||
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
getInput: mockGetInput,
|
||||
exportVariable: mockExportVariable,
|
||||
info: mockInfo,
|
||||
debug: mockDebug,
|
||||
warning: mockWarning,
|
||||
setSecret: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn(),
|
||||
isDebug: jest.fn(),
|
||||
setCommandEcho: jest.fn(),
|
||||
getIDToken: jest.fn(),
|
||||
ExitCode: {Success: 0, Failure: 1},
|
||||
summary: {},
|
||||
markdownSummary: {},
|
||||
platform: {},
|
||||
toPosixPath: jest.fn(),
|
||||
toWin32Path: jest.fn(),
|
||||
toPlatformPath: jest.fn()
|
||||
}));
|
||||
|
||||
const {configureMavenArgs} = await import('../src/maven-args.js');
|
||||
const {
|
||||
INPUT_SHOW_DOWNLOAD_PROGRESS,
|
||||
MAVEN_ARGS_ENV,
|
||||
MAVEN_NO_TRANSFER_PROGRESS_FLAG
|
||||
} from '../src/constants';
|
||||
} = await import('../src/constants.js');
|
||||
|
||||
describe('configureMavenArgs', () => {
|
||||
let inputs: Record<string, string>;
|
||||
let spyGetInput: jest.SpyInstance;
|
||||
let spyExportVariable: jest.SpyInstance;
|
||||
let spyInfo: jest.SpyInstance;
|
||||
let spyDebug: jest.SpyInstance;
|
||||
const originalMavenArgs = process.env[MAVEN_ARGS_ENV];
|
||||
|
||||
beforeEach(() => {
|
||||
inputs = {};
|
||||
|
||||
spyGetInput = jest.spyOn(core, 'getInput');
|
||||
spyGetInput.mockImplementation((name: string) => inputs[name] ?? '');
|
||||
|
||||
spyExportVariable = jest.spyOn(core, 'exportVariable');
|
||||
spyExportVariable.mockImplementation((name: string, value: string) => {
|
||||
mockGetInput.mockImplementation((name: string) => inputs[name] ?? '');
|
||||
mockExportVariable.mockImplementation((name: string, value: string) => {
|
||||
process.env[name] = value;
|
||||
});
|
||||
|
||||
spyInfo = jest.spyOn(core, 'info');
|
||||
spyInfo.mockImplementation(() => undefined);
|
||||
|
||||
spyDebug = jest.spyOn(core, 'debug');
|
||||
spyDebug.mockImplementation(() => undefined);
|
||||
mockInfo.mockImplementation(() => undefined);
|
||||
mockDebug.mockImplementation(() => undefined);
|
||||
|
||||
delete process.env[MAVEN_ARGS_ENV];
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
jest.resetAllMocks();
|
||||
if (originalMavenArgs === undefined) {
|
||||
delete process.env[MAVEN_ARGS_ENV];
|
||||
} else {
|
||||
@@ -47,7 +73,7 @@ describe('configureMavenArgs', () => {
|
||||
it('sets MAVEN_ARGS with -ntp by default', () => {
|
||||
configureMavenArgs();
|
||||
|
||||
expect(spyExportVariable).toHaveBeenCalledWith(
|
||||
expect(mockExportVariable).toHaveBeenCalledWith(
|
||||
MAVEN_ARGS_ENV,
|
||||
MAVEN_NO_TRANSFER_PROGRESS_FLAG
|
||||
);
|
||||
@@ -59,7 +85,7 @@ describe('configureMavenArgs', () => {
|
||||
|
||||
configureMavenArgs();
|
||||
|
||||
expect(spyExportVariable).not.toHaveBeenCalled();
|
||||
expect(mockExportVariable).not.toHaveBeenCalled();
|
||||
expect(process.env[MAVEN_ARGS_ENV]).toBeUndefined();
|
||||
});
|
||||
|
||||
@@ -68,7 +94,7 @@ describe('configureMavenArgs', () => {
|
||||
|
||||
configureMavenArgs();
|
||||
|
||||
expect(spyExportVariable).toHaveBeenCalledWith(
|
||||
expect(mockExportVariable).toHaveBeenCalledWith(
|
||||
MAVEN_ARGS_ENV,
|
||||
`-B -Dstyle.color=always ${MAVEN_NO_TRANSFER_PROGRESS_FLAG}`
|
||||
);
|
||||
@@ -79,7 +105,7 @@ describe('configureMavenArgs', () => {
|
||||
|
||||
configureMavenArgs();
|
||||
|
||||
expect(spyExportVariable).not.toHaveBeenCalled();
|
||||
expect(mockExportVariable).not.toHaveBeenCalled();
|
||||
expect(process.env[MAVEN_ARGS_ENV]).toBe('-B -ntp');
|
||||
});
|
||||
|
||||
@@ -88,7 +114,7 @@ describe('configureMavenArgs', () => {
|
||||
|
||||
configureMavenArgs();
|
||||
|
||||
expect(spyExportVariable).not.toHaveBeenCalled();
|
||||
expect(mockExportVariable).not.toHaveBeenCalled();
|
||||
expect(process.env[MAVEN_ARGS_ENV]).toBe('--no-transfer-progress -B');
|
||||
});
|
||||
|
||||
@@ -98,7 +124,7 @@ describe('configureMavenArgs', () => {
|
||||
|
||||
configureMavenArgs();
|
||||
|
||||
expect(spyExportVariable).not.toHaveBeenCalled();
|
||||
expect(mockExportVariable).not.toHaveBeenCalled();
|
||||
expect(process.env[MAVEN_ARGS_ENV]).toBe('-B');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import {afterEach, beforeEach, describe, expect, it, jest} from '@jest/globals';
|
||||
|
||||
const mockGetInput = jest.fn<(...args: any[]) => any>();
|
||||
const mockInfo = jest.fn<(...args: any[]) => any>();
|
||||
const mockDebug = jest.fn<(...args: any[]) => any>();
|
||||
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
getInput: mockGetInput,
|
||||
info: mockInfo,
|
||||
debug: mockDebug,
|
||||
warning: jest.fn(),
|
||||
setSecret: jest.fn()
|
||||
}));
|
||||
|
||||
const {configureProblemMatcher} = await import('../src/problem-matcher.js');
|
||||
const {INPUT_PROBLEM_MATCHER} = await import('../src/constants.js');
|
||||
|
||||
describe('configureProblemMatcher', () => {
|
||||
let inputs: Record<string, string>;
|
||||
|
||||
beforeEach(() => {
|
||||
inputs = {};
|
||||
mockGetInput.mockImplementation((name: string) => inputs[name] ?? '');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('registers the Java problem matcher by default', () => {
|
||||
configureProblemMatcher('/matchers/java.json');
|
||||
|
||||
expect(mockInfo).toHaveBeenCalledWith('##[add-matcher]/matchers/java.json');
|
||||
});
|
||||
|
||||
it('does not register the Java problem matcher when disabled', () => {
|
||||
inputs[INPUT_PROBLEM_MATCHER] = 'false';
|
||||
|
||||
configureProblemMatcher('/matchers/java.json');
|
||||
|
||||
expect(mockInfo).not.toHaveBeenCalled();
|
||||
expect(mockDebug).toHaveBeenCalledWith('Java problem matcher is disabled');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,251 @@
|
||||
import {jest, describe, it, expect, beforeEach, afterEach} from '@jest/globals';
|
||||
import type {IncomingMessage} from 'http';
|
||||
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn()
|
||||
}));
|
||||
|
||||
const core = await import('@actions/core');
|
||||
const httpm = await import('@actions/http-client');
|
||||
const {RetryingHttpClient, isRetryableNetworkError, parseRetryAfter} =
|
||||
await import('../src/retrying-http-client.js');
|
||||
|
||||
function response(
|
||||
statusCode: number,
|
||||
retryAfter?: string
|
||||
): httpm.HttpClientResponse {
|
||||
return {
|
||||
message: {
|
||||
statusCode,
|
||||
headers: retryAfter ? {'retry-after': retryAfter} : {}
|
||||
} as IncomingMessage,
|
||||
readBody: jest.fn(async () => '')
|
||||
} as unknown as httpm.HttpClientResponse;
|
||||
}
|
||||
|
||||
describe('RetryingHttpClient', () => {
|
||||
let request: ReturnType<typeof jest.spyOn>;
|
||||
let sleep: jest.Mock<(delayMs: number) => Promise<void>>;
|
||||
|
||||
beforeEach(() => {
|
||||
request = jest.spyOn(httpm.HttpClient.prototype, 'request');
|
||||
sleep = jest.fn(async () => undefined);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('uses exponential backoff with jitter for retryable responses', async () => {
|
||||
request
|
||||
.mockResolvedValueOnce(response(503))
|
||||
.mockResolvedValueOnce(response(502))
|
||||
.mockResolvedValueOnce(response(200));
|
||||
const client = new RetryingHttpClient('test', {
|
||||
sleep,
|
||||
random: () => 0,
|
||||
baseDelayMs: 1000,
|
||||
maxDelayMs: 10000
|
||||
});
|
||||
|
||||
await expect(client.get('https://example.com')).resolves.toBeDefined();
|
||||
|
||||
expect(request).toHaveBeenCalledTimes(3);
|
||||
expect(sleep).toHaveBeenNthCalledWith(1, 500);
|
||||
expect(sleep).toHaveBeenNthCalledWith(2, 1000);
|
||||
expect(core.info).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
'Request attempt 1 of 4 failed (HTTP 503); retrying in 500 ms'
|
||||
);
|
||||
expect(core.info).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
'Request attempt 2 of 4 failed (HTTP 502); retrying in 1000 ms'
|
||||
);
|
||||
});
|
||||
|
||||
it('honors Retry-After delta-seconds over the client delay', async () => {
|
||||
request
|
||||
.mockResolvedValueOnce(response(429, '3'))
|
||||
.mockResolvedValueOnce(response(200));
|
||||
const client = new RetryingHttpClient('test', {
|
||||
sleep,
|
||||
random: () => 0
|
||||
});
|
||||
|
||||
await client.get('https://example.com');
|
||||
|
||||
expect(sleep).toHaveBeenCalledWith(3000);
|
||||
});
|
||||
|
||||
it('honors Retry-After HTTP dates over the client delay', async () => {
|
||||
const now = Date.parse('2026-07-29T00:00:00Z');
|
||||
request
|
||||
.mockResolvedValueOnce(response(503, new Date(now + 5000).toUTCString()))
|
||||
.mockResolvedValueOnce(response(200));
|
||||
const client = new RetryingHttpClient('test', {
|
||||
sleep,
|
||||
random: () => 0,
|
||||
now: () => now
|
||||
});
|
||||
|
||||
await client.get('https://example.com');
|
||||
|
||||
expect(sleep).toHaveBeenCalledWith(5000);
|
||||
});
|
||||
|
||||
it('caps Retry-After at the configured maximum delay', async () => {
|
||||
request
|
||||
.mockResolvedValueOnce(response(429, '60'))
|
||||
.mockResolvedValueOnce(response(200));
|
||||
const client = new RetryingHttpClient('test', {
|
||||
sleep,
|
||||
random: () => 0,
|
||||
maxDelayMs: 10000
|
||||
});
|
||||
|
||||
await client.get('https://example.com');
|
||||
|
||||
expect(sleep).toHaveBeenCalledWith(10000);
|
||||
});
|
||||
|
||||
it.each([429, 502, 503, 504, 522])(
|
||||
'retries HTTP %s responses',
|
||||
async statusCode => {
|
||||
request
|
||||
.mockResolvedValueOnce(response(statusCode))
|
||||
.mockResolvedValueOnce(response(200));
|
||||
const client = new RetryingHttpClient('test', {
|
||||
sleep,
|
||||
random: () => 0
|
||||
});
|
||||
|
||||
await client.get('https://example.com');
|
||||
|
||||
expect(request).toHaveBeenCalledTimes(2);
|
||||
}
|
||||
);
|
||||
|
||||
it.each(['ETIMEDOUT', 'ECONNRESET', 'ENOTFOUND', 'ECONNREFUSED'])(
|
||||
'retries network errors with code %s',
|
||||
async code => {
|
||||
request
|
||||
.mockRejectedValueOnce(Object.assign(new Error(code), {code}))
|
||||
.mockResolvedValueOnce(response(200));
|
||||
const client = new RetryingHttpClient('test', {
|
||||
sleep,
|
||||
random: () => 0
|
||||
});
|
||||
|
||||
await client.get('https://example.com');
|
||||
|
||||
expect(request).toHaveBeenCalledTimes(2);
|
||||
}
|
||||
);
|
||||
|
||||
it('retries retryable aggregate network errors', async () => {
|
||||
const aggregateError = Object.assign(new Error('connection failed'), {
|
||||
errors: [Object.assign(new Error('timed out'), {code: 'ETIMEDOUT'})]
|
||||
});
|
||||
request
|
||||
.mockRejectedValueOnce(aggregateError)
|
||||
.mockResolvedValueOnce(response(200));
|
||||
const client = new RetryingHttpClient('test', {
|
||||
sleep,
|
||||
random: () => 0
|
||||
});
|
||||
|
||||
await client.get('https://example.com');
|
||||
|
||||
expect(request).toHaveBeenCalledTimes(2);
|
||||
expect(sleep).toHaveBeenCalledWith(500);
|
||||
});
|
||||
|
||||
it('does not retry non-retryable responses or network errors', async () => {
|
||||
request.mockResolvedValueOnce(response(500));
|
||||
const client = new RetryingHttpClient('test', {sleep});
|
||||
|
||||
await expect(client.get('https://example.com')).resolves.toBeDefined();
|
||||
expect(request).toHaveBeenCalledTimes(1);
|
||||
expect(sleep).not.toHaveBeenCalled();
|
||||
|
||||
request.mockRejectedValueOnce(
|
||||
Object.assign(new Error('certificate failed'), {code: 'CERT_HAS_EXPIRED'})
|
||||
);
|
||||
await expect(client.get('https://example.com')).rejects.toThrow(
|
||||
'certificate failed'
|
||||
);
|
||||
expect(request).toHaveBeenCalledTimes(2);
|
||||
expect(sleep).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('stops after the configured total attempt count', async () => {
|
||||
request
|
||||
.mockResolvedValueOnce(response(503))
|
||||
.mockResolvedValueOnce(response(503));
|
||||
const client = new RetryingHttpClient('test', {
|
||||
maxAttempts: 2,
|
||||
sleep,
|
||||
random: () => 0
|
||||
});
|
||||
|
||||
const finalResponse = await client.get('https://example.com');
|
||||
|
||||
expect(finalResponse.message.statusCode).toBe(503);
|
||||
expect(request).toHaveBeenCalledTimes(2);
|
||||
expect(sleep).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('propagates the final network error after exhausting attempts', async () => {
|
||||
const finalError = Object.assign(new Error('still unavailable'), {
|
||||
code: 'ECONNREFUSED'
|
||||
});
|
||||
request
|
||||
.mockRejectedValueOnce(
|
||||
Object.assign(new Error('unavailable'), {code: 'ECONNREFUSED'})
|
||||
)
|
||||
.mockRejectedValueOnce(finalError);
|
||||
const client = new RetryingHttpClient('test', {
|
||||
maxAttempts: 2,
|
||||
sleep,
|
||||
random: () => 0
|
||||
});
|
||||
|
||||
await expect(client.get('https://example.com')).rejects.toBe(finalError);
|
||||
|
||||
expect(request).toHaveBeenCalledTimes(2);
|
||||
expect(sleep).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('does not retry write requests', async () => {
|
||||
request.mockResolvedValueOnce(response(503));
|
||||
const client = new RetryingHttpClient('test', {sleep});
|
||||
|
||||
await client.post('https://example.com', '{}');
|
||||
|
||||
expect(request).toHaveBeenCalledTimes(1);
|
||||
expect(sleep).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('retry classification', () => {
|
||||
it('parses valid Retry-After values and ignores invalid or past values', () => {
|
||||
const now = Date.parse('2026-07-29T00:00:00Z');
|
||||
|
||||
expect(parseRetryAfter('7', now)).toBe(7000);
|
||||
expect(parseRetryAfter(new Date(now + 3000).toUTCString(), now)).toBe(3000);
|
||||
expect(parseRetryAfter(new Date(now - 3000).toUTCString(), now)).toBe(
|
||||
undefined
|
||||
);
|
||||
expect(parseRetryAfter('not-a-date', now)).toBe(undefined);
|
||||
});
|
||||
|
||||
it('recognizes direct and nested retryable network error codes', () => {
|
||||
expect(isRetryableNetworkError({code: 'ECONNRESET'})).toBe(true);
|
||||
expect(
|
||||
isRetryableNetworkError({errors: [{code: 'ENOTFOUND'}, {code: 'OTHER'}]})
|
||||
).toBe(true);
|
||||
expect(isRetryableNetworkError({code: 'CERT_HAS_EXPIRED'})).toBe(false);
|
||||
expect(isRetryableNetworkError(new Error('unknown'))).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,118 @@
|
||||
import {jest, describe, it, expect, beforeEach} from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
notice: jest.fn(),
|
||||
setFailed: jest.fn(),
|
||||
setOutput: jest.fn(),
|
||||
getInput: jest.fn(),
|
||||
getBooleanInput: jest.fn(),
|
||||
getMultilineInput: jest.fn(),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn(),
|
||||
setSecret: jest.fn(),
|
||||
isDebug: jest.fn(() => false),
|
||||
startGroup: jest.fn(),
|
||||
endGroup: jest.fn(),
|
||||
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
|
||||
toPlatformPath: jest.fn((value: string) => value),
|
||||
toWin32Path: jest.fn((value: string) => value),
|
||||
toPosixPath: jest.fn((value: string) => value)
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('fs', () => ({
|
||||
default: {
|
||||
readFileSync: jest.fn()
|
||||
}
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../src/util.js', () => ({
|
||||
getBooleanInput: jest.fn(),
|
||||
getVersionFromFileContent: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../src/toolchains.js', () => ({
|
||||
validateToolchainIds: jest.fn(),
|
||||
configureToolchains: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule(
|
||||
'../src/distributions/distribution-factory.js',
|
||||
() => ({
|
||||
getJavaDistribution: jest.fn()
|
||||
})
|
||||
);
|
||||
|
||||
jest.unstable_mockModule('../src/auth.js', () => ({
|
||||
configureAuthentication: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../src/maven-args.js', () => ({
|
||||
configureMavenArgs: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../src/problem-matcher.js', () => ({
|
||||
configureProblemMatcher: jest.fn()
|
||||
}));
|
||||
|
||||
// These modules should never be imported when `cache` input is empty.
|
||||
jest.unstable_mockModule('../src/cache-feature.js', () => {
|
||||
throw new Error('cache-feature module should not be loaded');
|
||||
});
|
||||
jest.unstable_mockModule('../src/cache.js', () => {
|
||||
throw new Error('cache module should not be loaded');
|
||||
});
|
||||
|
||||
const core = await import('@actions/core');
|
||||
const util = await import('../src/util.js');
|
||||
const toolchains = await import('../src/toolchains.js');
|
||||
const factory = await import('../src/distributions/distribution-factory.js');
|
||||
const {run} = await import('../src/setup-java.js');
|
||||
|
||||
describe('setup-java conditional module loading', () => {
|
||||
const inputs = new Map<string, string>();
|
||||
const multilineInputs = new Map<string, string[]>();
|
||||
const booleanInputs = new Map<string, boolean>();
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
inputs.clear();
|
||||
multilineInputs.clear();
|
||||
booleanInputs.clear();
|
||||
|
||||
(core.getInput as jest.Mock).mockImplementation((name: unknown) => {
|
||||
return inputs.get(name as string) ?? '';
|
||||
});
|
||||
(core.getMultilineInput as jest.Mock).mockImplementation(
|
||||
(name: unknown) => {
|
||||
return multilineInputs.get(name as string) ?? [];
|
||||
}
|
||||
);
|
||||
(util.getBooleanInput as jest.Mock).mockImplementation(
|
||||
(name: unknown, defaultValue: unknown) => {
|
||||
return booleanInputs.get(name as string) ?? defaultValue;
|
||||
}
|
||||
);
|
||||
(toolchains.configureToolchains as jest.Mock).mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
it('does not import cache modules when cache input is not provided', async () => {
|
||||
inputs.set('distribution', 'temurin');
|
||||
multilineInputs.set('java-version', ['21']);
|
||||
(factory.getJavaDistribution as jest.Mock).mockResolvedValue({
|
||||
setupJava: jest.fn(async () => ({
|
||||
version: '21.0.4+7',
|
||||
path: '/opt/java/21'
|
||||
}))
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user