Compare commits

...

65 Commits

Author SHA1 Message Date
6191f55d32 Rename v2-preview to v2 in docs and tests 2021-04-05 13:04:51 +03:00
b53500dabc Merge "v2-preview" branch into "main" (#150)
* actions/setup-java@v2 - Support different distributions (#132)

* Implement support for custom vendors in setup-java

* minor improvements

* minor refactoring

* Add unit tests and e2e tests

* Update documentation for setup-java@v2 release

* minor improvements

* regenerate dist

* fix comments

* resolve comments

* resolve comments

* fix tests

* Update README.md

Co-authored-by: George Adams <george.adams@microsoft.com>

* Apply suggestions from code review

Co-authored-by: Konrad Pabjan <konradpabjan@github.com>

* fix minor nitpicks

* handle 4th digit

* pull latest main

* Update README.md

* rename adoptium to adopt

* rename adoptium to adopt

* rename adoptium to adopt

* Update README.md

* make java-version and distribution required for action

* update readme

* fix tests

* fix e2e tests

Co-authored-by: George Adams <george.adams@microsoft.com>
Co-authored-by: Konrad Pabjan <konradpabjan@github.com>

* Add "overwrite-settings" input parameter (#136)

* add overwrite-settings parameter

* fix e2e tests

* print debug

* fix e2e tests

* add comment

* remove comment

* Add "Contents/Home" postfix on macOS if provider creates it (#139)

* Update e2e-versions.yml

* Update e2e-versions.yml

* implement fix

* Update e2e-versions.yml

* Update installer.ts

* fix filter logic

* Update e2e-versions.yml

* remove extra logic

* Update e2e-versions.yml

* Add check-latest flag (#141)

* add changes for check-latest

* run prerelease script

* resolving comments

* fixing tests

* fix spelling

* improve core.info messages

* run format

* run prerelease

* change version to fix test

* resolve comment for check-latest

* Update README.md

* added hosted tool cache section

* Apply suggestions from code review

Co-authored-by: Maxim Lobanov <v-malob@microsoft.com>
Co-authored-by: Konrad Pabjan <konradpabjan@github.com>

* Avoid "+" sign in Java path in v2-preview (#145)

* try to handle _ versions

* more logs

* more debug

* test 1

* more fixes

* fix typo

* Update e2e-versions.yml

* add unit-tests

* remove debug info from tests

* debug pre-cached versions

* change e2e tests to ubuntu-latest

* update npm licenses

Co-authored-by: George Adams <george.adams@microsoft.com>
Co-authored-by: Konrad Pabjan <konradpabjan@github.com>
Co-authored-by: Dmitry Shibanov <dmitry-shibanov@github.com>
2021-04-05 13:02:27 +03:00
ebb424f2cb Beatify "main" warning about breaking changes (#144)
* add warning

* Update src/setup-java.ts

Co-authored-by: Konrad Pabjan <konradpabjan@github.com>

* Update index.js

Co-authored-by: Konrad Pabjan <konradpabjan@github.com>
2021-03-22 12:05:47 +03:00
9c7940b9c6 Add breaking change warning to 'main' branch (#138)
* add warning

* Update src/setup-java.ts

Co-authored-by: Konrad Pabjan <konradpabjan@github.com>

Co-authored-by: Konrad Pabjan <konradpabjan@github.com>
2021-03-22 11:06:35 +03:00
fc62ccaa4f V2 setup-java ADR (#97)
* V2 setup-java initial ADR

* Update ADR

* Misc fixes

* Clarifications around default behavior and new input

* PR feedback
2021-03-08 12:38:33 -05:00
e73e96a93b Merge pull request #131 from actions/v-malob/update-codeowners
Add @actions/virtual-environments-owners to CODEOWNERS file
2021-03-05 09:36:36 +03:00
ea31b1d738 Update CODEOWNERS 2021-03-04 21:22:42 +03:00
ff0054dfbf Merge pull request #123 from dmitry-shibanov/fix-documentation-for-gpg-import-export
Fix documentation for GPG
2021-02-17 11:13:48 +03:00
81290cdb8c change imported to exported 2021-02-16 18:12:46 +03:00
546dae7e87 Merge pull request #122 from dmitry-shibanov/update-docs-for-maven-and-gpg
Add notes about maven extra configuration and gpg key.
2021-02-15 12:03:32 +03:00
4d656d0138 work on resolving comments 2021-02-15 10:22:04 +03:00
719bcb4f94 resolve comments 2021-02-12 16:16:23 +03:00
661c4c13b4 update docs to notes about maven and gpg 2021-02-12 12:26:52 +03:00
2fac83dd2d Merge pull request #121 from dmitry-shibanov/restrict-blank-issues
Restrict blank issues
2021-02-10 17:30:29 +03:00
fbe6d87076 add bug to labels 2021-02-10 16:58:41 +03:00
371353f882 fix label creation 2021-02-10 12:49:56 +03:00
5222f725dd restrict create blank issue 2021-02-10 12:08:43 +03:00
089d28c90b Merge pull request #119 from vsafonkin/v-vlsafo/issue-pr-templates
Add issue and pull request templates
2021-02-05 11:24:44 +03:00
552366fa8e Add issue and pr templates 2021-02-05 09:44:08 +03:00
61c9e3a719 CODEOWNERS needs the org name for teams (#118) 2020-12-07 15:59:00 -05:00
e3619375bd Create CODEOWNERS (#115) 2020-11-25 16:09:07 -05:00
d202f5dbf7 Swap to Environment Files (#104)
* Add Licensed workflow and config files

* Manually validate dependencies

* Swap to Environment Files
2020-09-30 15:51:22 +02:00
11790a2d66 Add Licensed To Help Verify Prod Licenses (#88)
* Add Licensed workflow and config files

* Manually validate dependencies

* Ignore Generated Files in Git PR's

* update contributing.md
2020-09-23 23:23:32 +02:00
8bb50d97d6 Move contributor doc 2020-08-24 14:35:19 +02:00
fe06bcdc44 Remove old dist/index.js file (#96)
* Remove old dist/index.js file

* Misc fixes
2020-08-24 14:19:47 +02:00
d34a7e45c8 Architecture Support (#95)
* Quick fix for 32-bit architecture support.

* Validate arch at input

Co-authored-by: Émile Grégoire <eg@emilegregoire.ca>
2020-08-24 12:35:41 +02:00
3019d15cad Add Third Party Licenses (#87) 2020-08-10 18:22:52 +02:00
1253a7eed4 Merge pull request #81 from actions/dependabot/npm_and_yarn/lodash-4.17.19
Bump lodash from 4.17.15 to 4.17.19
2020-07-22 10:44:06 +02:00
1277492cb9 Merge pull request #63 from jaredpetersen/master
Added support for GPG signing
2020-07-22 10:39:43 +02:00
38e0c8bd18 improved cleanup error message 2020-07-17 21:23:13 -06:00
77d6565ede Bump lodash from 4.17.15 to 4.17.19
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-18 00:05:35 +00:00
ac9630fb91 cleaned up description for how the private key is stored
Co-authored-by: Yashwanth Anantharaju <yaananth@users.noreply.github.com>
2020-07-17 16:34:33 -06:00
36bb906fe0 removed test timeout 2020-07-16 19:12:25 -06:00
012c21ec81 fixed gpg passhprase default 2020-07-15 21:29:50 -06:00
4d8dc69fc8 fixing defaults 2020-07-15 21:15:27 -06:00
2d0e474aa9 removed unecessary set secret -- it's an environment variable not a literal 2020-07-15 20:27:28 -06:00
034b7a7488 forgot to run build 2020-07-15 20:19:14 -06:00
91d166793d added blurb about private key file and cleanup for hosted runners 2020-07-15 20:16:31 -06:00
7f2382879a addressed most of the feedback 2020-07-15 19:53:39 -06:00
01f44229d4 Merge remote-tracking branch 'upstream/master' 2020-06-23 20:54:13 -07:00
d920b7da5f Merge pull request #78 from aibaars/patch-1
Normalize extendedJavaHome environment variable
2020-06-22 11:04:01 +02:00
88965601fb Keep old environment variable for backwards compatibility 2020-06-17 21:37:10 +02:00
655cb05195 Add comment explaining why the environment variable should be normalized 2020-06-17 19:37:01 +02:00
81bfa641b0 Normalize extendedJavaHome environment variable
The extendedJavaHome environment variable contains `.` symbols in the version. This causes the environment variable to be ignored by the action runner. It's best to replace those and other non standard symbols with and underscore.

For reference:
> Environment variable names used by the utilities in the Shell and Utilities volume of IEEE Std 1003.1-2001 consist solely of uppercase letters, digits, and the '_' (underscore) from the characters defined in Portable Character Set .
2020-06-17 18:17:42 +02:00
6e1616c588 Merge pull request #66 from tbroyer/outputs
Add output parameters for the tool path and version
2020-05-27 13:31:58 +02:00
457d7a4579 Add output parameters for the tool path and version
This allows calling the action multiple times in the
same job and retrieving the path and/or version in
other steps.

Fixes #65
2020-05-27 09:04:20 +02:00
e494666ae9 fixed setSecret 2020-05-22 21:30:38 -07:00
d94db22179 Added support for GPG 2020-05-15 23:40:06 -07:00
4003c04fbc Delete lint-yaml.yml 2020-05-11 20:09:41 +02:00
9c7b108c73 Merge pull request #58 from actions/dependabot/npm_and_yarn/actions/http-client-1.0.8
Bump @actions/http-client from 1.0.6 to 1.0.8
2020-05-11 20:08:10 +02:00
505c9972aa Bump @actions/http-client from 1.0.6 to 1.0.8
Bumps [@actions/http-client](https://github.com/actions/http-client) from 1.0.6 to 1.0.8.
- [Release notes](https://github.com/actions/http-client/releases)
- [Changelog](https://github.com/actions/http-client/blob/master/RELEASES.md)
- [Commits](https://github.com/actions/http-client/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2020-04-29 18:00:13 +00:00
5c87b70ffe Merge pull request #52 from actions/dependabot/npm_and_yarn/acorn-5.7.4
Bump acorn from 5.7.3 to 5.7.4
2020-03-19 17:22:10 +01:00
ea8ea84c9e Bump acorn from 5.7.3 to 5.7.4
Bumps [acorn](https://github.com/acornjs/acorn) from 5.7.3 to 5.7.4.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/5.7.3...5.7.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-03-16 11:25:52 +00:00
6dc4d4a3ed Merge pull request #41 from foo-actions/master
Update REAME and action.yml to describe java-version syntax options
2020-02-12 09:58:10 -05:00
5ef3a8d61b Merge pull request #49 from ericsciple/users/ericsciple/m166proxy
standardize workflow test pattern
2020-02-12 09:47:44 -05:00
60cf21b5e7 standardize workflow test pattern 2020-02-11 19:38:16 -05:00
f63b906f27 Merge pull request #48 from ericsciple/users/ericsciple/m166retry
add retries and error handling
2020-02-11 17:56:38 -05:00
9c4f82dc57 add retries and error handling 2020-02-11 16:37:51 -05:00
623089a937 Merge pull request #46 from dakale/http-proxy-support
http proxy support
2020-02-11 15:48:53 -05:00
ec103c0d1a Remove debugging step 2020-02-06 15:48:29 -05:00
90c448a85d Update packages to support http_proxy 2020-02-06 15:44:54 -05:00
63d68602dd Merge pull request #45 from scordio/actions-checkout_version
Update examples to use actions/checkout@v2
2020-02-03 20:12:39 -05:00
351c3fb96f Update examples to use actions/checkout@v2 2020-01-31 01:52:07 +01:00
f6b96adea7 Update README and action.yml to describe java-version syntax 2020-01-09 00:49:07 -08:00
c74a6f8415 Update README and action.yml to describe java-version syntax 2020-01-09 00:45:37 -08:00
78 changed files with 59662 additions and 3401 deletions

1
.gitattributes vendored
View File

@ -1,2 +1,3 @@
dist/index.js -diff -merge
dist/index.js linguist-generated=true
.licenses/** -diff linguist-generated=true

2
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1,2 @@
* @actions/actions-service
* @actions/virtual-environments-owners

32
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,32 @@
---
name: Bug report
about: Create a bug report
title: ''
labels: bug, needs triage
assignees: ''
---
**Description:**
A clear and concise description of what the bug is.
**Task version:**
Specify the task version
**Platform:**
- [ ] Ubuntu
- [ ] macOS
- [ ] Windows
**Runner type:**
- [ ] Hosted
- [ ] Self-hosted
**Repro steps:**
A description with steps to reproduce the issue. If your have a public example or repo to share, please provide the link.
**Expected behavior:**
A description of what you expected to happen.
**Actual behavior:**
A description of what is actually happening.

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1 @@
blank_issues_enabled: false

View File

@ -0,0 +1,16 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature request, needs triage
assignees: ''
---
**Description:**
Describe your proposal.
**Justification:**
Justification or a use case for your proposal.
**Are you willing to submit a PR?**
<!--- We accept contributions! -->

9
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,9 @@
**Description:**
Describe your changes.
**Related issue:**
Add link to the related issue.
**Check list:**
- [ ] Mark if documentation changes are required.
- [ ] Mark if tests were added or updated to cover the changes.

33
.github/workflows/build.yml vendored Executable file
View File

@ -0,0 +1,33 @@
name: Build Action
on:
push:
branches:
- main
- releases/*
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v2
- name: Setup Node.JS 12
uses: actions/setup-node@v2
with:
node-version: 12.x
- run: npm ci
- run: npm run build
- run: npm run format-check
- run: npm test
- name: Verify no unstaged changes
if: runner.os != 'windows'
run: bash __tests__/verify-no-unstaged-changes.sh

86
.github/workflows/e2e-local-file.yml vendored Normal file
View File

@ -0,0 +1,86 @@
name: Validate local file
on:
push:
branches:
- main
- releases/*
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
jobs:
setup-java-local-file-adopt:
name: Validate installation from local file Adopt
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Download Adopt OpenJDK file
run: |
if ($IsLinux) {
$downloadUrl = "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.10%2B9/OpenJDK11U-jdk_x64_linux_hotspot_11.0.10_9.tar.gz"
$localFilename = "java_package.tar.gz"
} elseif ($IsMacOS) {
$downloadUrl = "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.10%2B9/OpenJDK11U-jdk_x64_mac_hotspot_11.0.10_9.tar.gz"
$localFilename = "java_package.tar.gz"
} elseif ($IsWindows) {
$downloadUrl = "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.10%2B9/OpenJDK11U-jdk_x64_windows_hotspot_11.0.10_9.zip"
$localFilename = "java_package.zip"
}
echo "LocalFilename=$localFilename" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
(New-Object System.Net.WebClient).DownloadFile($downloadUrl, "$env:RUNNER_TEMP/$localFilename")
shell: pwsh
- name: setup-java
uses: ./
id: setup-java
with:
distribution: 'jdkfile'
jdkFile: ${{ runner.temp }}/${{ env.LocalFilename }}
java-version: '11.0.0-ea'
architecture: x64
- name: Verify Java version
run: bash __tests__/verify-java.sh "11.0.10" "${{ steps.setup-java.outputs.path }}"
shell: bash
setup-java-local-file-zulu:
name: Validate installation from local file Zulu
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Download Zulu OpenJDK file
run: |
if ($IsLinux) {
$downloadUrl = "https://cdn.azul.com/zulu/bin/zulu11.2.3-jdk11.0.1-linux_x64.tar.gz"
$localFilename = "java_package.tar.gz"
} elseif ($IsMacOS) {
$downloadUrl = "https://cdn.azul.com/zulu/bin/zulu11.2.3-jdk11.0.1-macosx_x64.tar.gz"
$localFilename = "java_package.tar.gz"
} elseif ($IsWindows) {
$downloadUrl = "https://cdn.azul.com/zulu/bin/zulu11.45.27-ca-jdk11.0.10-win_x64.zip"
$localFilename = "java_package.zip"
}
echo "LocalFilename=$localFilename" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
(New-Object System.Net.WebClient).DownloadFile($downloadUrl, "$env:RUNNER_TEMP/$localFilename")
shell: pwsh
- name: setup-java
uses: ./
id: setup-java
with:
distribution: 'jdkfile'
jdkFile: ${{ runner.temp }}/${{ env.LocalFilename }}
java-version: '11.0.0-ea'
architecture: x64
- name: Verify Java version
run: bash __tests__/verify-java.sh "11.0" "${{ steps.setup-java.outputs.path }}"
shell: bash

152
.github/workflows/e2e-publishing.yml vendored Normal file
View File

@ -0,0 +1,152 @@
name: Validate publishing functionality
on:
push:
branches:
- main
- releases/*
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
defaults:
run:
shell: pwsh
jobs:
setup-java-publishing:
name: Validate settings.xml
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: setup-java
uses: ./
id: setup-java
with:
distribution: 'adopt'
java-version: '11'
server-id: maven
server-username: MAVEN_USERNAME
server-password: MAVEN_CENTRAL_TOKEN
gpg-passphrase: 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"
}
if (($servers[1].id -ne 'gpg.passphrase') -or ($servers[1].passphrase -ne '${env.MAVEN_GPG_PASSPHRASE}')) {
throw "Generated XML file is incorrect"
}
test-publishing-overwrite:
name: settings.xml is overwritten if flag is true
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Create fake settings.xml
run: |
$xmlDirectory = Join-Path $HOME ".m2"
$xmlPath = Join-Path $xmlDirectory "settings.xml"
New-Item -Path $xmlDirectory -ItemType Directory
Set-Content -Path $xmlPath -Value "Fake_XML"
- name: setup-java
uses: ./
id: setup-java
with:
distribution: 'adopt'
java-version: '11'
server-id: maven
server-username: MAVEN_USERNAME
server-password: MAVEN_CENTRAL_TOKEN
gpg-passphrase: MAVEN_GPG_PASSPHRASE
- name: Validate settings.xml is overwritten
run: |
$xmlPath = Join-Path $HOME ".m2" "settings.xml"
Get-Content $xmlPath | ForEach-Object { Write-Host $_ }
$content = Get-Content $xmlPath -Raw
if ($content -notlike '*maven*') {
throw "settings.xml file is not overwritten"
}
test-publishing-skip-overwrite:
name: settings.xml is not overwritten if flag is false
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Create fake settings.xml
run: |
$xmlDirectory = Join-Path $HOME ".m2"
$xmlPath = Join-Path $xmlDirectory "settings.xml"
New-Item -Path $xmlDirectory -ItemType Directory
Set-Content -Path $xmlPath -Value "Fake_XML"
- name: setup-java
uses: ./
id: setup-java
with:
distribution: 'adopt'
java-version: '11'
server-id: maven
server-username: MAVEN_USERNAME
server-password: MAVEN_CENTRAL_TOKEN
overwrite-settings: false
gpg-passphrase: MAVEN_GPG_PASSPHRASE
- name: Validate that settings.xml is not overwritten
run: |
$xmlPath = Join-Path $HOME ".m2" "settings.xml"
$content = Get-Content -Path $xmlPath -Raw
Write-Host $content
if ($content -notlike "*Fake_XML*") {
throw "settings.xml file was overwritten but it should not be"
}
test-publishing-custom-location:
name: settings.xml in custom location
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: setup-java
uses: ./
id: setup-java
with:
distribution: 'adopt'
java-version: '11'
server-id: maven
server-username: MAVEN_USERNAME
server-password: MAVEN_CENTRAL_TOKEN
gpg-passphrase: MAVEN_GPG_PASSPHRASE
settings-path: ${{ runner.temp }}
- name: Validate settings.xml location
run: |
$path = Join-Path $env:RUNNER_TEMP "settings.xml"
if (-not (Test-Path $path)) {
throw "settings.xml file is not found in expected location"
}

197
.github/workflows/e2e-versions.yml vendored Normal file
View File

@ -0,0 +1,197 @@
name: Validate Java e2e
on:
push:
branches:
- main
- releases/*
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
jobs:
setup-java-major-versions:
name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-x64) - ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
distribution: ['adopt', 'zulu']
version: ['8', '11', '15']
steps:
- name: Checkout
uses: actions/checkout@v2
- name: setup-java
uses: ./
id: setup-java
with:
java-version: ${{ matrix.version }}
distribution: ${{ matrix.distribution }}
- name: Verify Java
run: bash __tests__/verify-java.sh "${{ matrix.version }}" "${{ steps.setup-java.outputs.path }}"
shell: bash
setup-java-major-minor-versions:
name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-x64) - ${{ matrix.os }}
needs: setup-java-major-versions
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
distribution: ['adopt', 'zulu']
version:
- '11.0'
- '8.0.282'
- '11.0.2+7'
include:
- distribution: 'adopt'
version: '12.0.2+10.1'
os: macos-latest
- distribution: 'adopt'
version: '12.0.2+10.1'
os: windows-latest
- distribution: 'adopt'
version: '12.0.2+10.1'
os: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: setup-java
uses: ./
id: setup-java
with:
java-version: ${{ matrix.version }}
distribution: ${{ matrix.distribution }}
- name: Verify Java
run: bash __tests__/verify-java.sh "${{ matrix.version }}" "${{ steps.setup-java.outputs.path }}"
shell: bash
setup-java-check-latest:
name: ${{ matrix.distribution }} ${{ matrix.version }} - check-latest flag - ${{ matrix.os }}
needs: setup-java-major-versions
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
distribution: ['adopt', 'zulu']
steps:
- name: Checkout
uses: actions/checkout@v2
- name: setup-java
uses: ./
id: setup-java
with:
distribution: ${{ matrix.distribution }}
java-version: 11
check-latest: true
- name: Verify Java
run: bash __tests__/verify-java.sh "11" "${{ steps.setup-java.outputs.path }}"
shell: bash
setup-java-ea-versions-zulu:
name: zulu ${{ matrix.version }} (jdk-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', '15.0.0-ea.14']
steps:
- name: Checkout
uses: actions/checkout@v2
- name: setup-java
uses: ./
id: setup-java
with:
java-version: ${{ matrix.version }}
distribution: zulu
- name: Verify Java
run: bash __tests__/verify-java.sh "${{ matrix.version }}" "${{ steps.setup-java.outputs.path }}"
shell: bash
setup-java-ea-versions-adopt:
name: adopt ${{ matrix.version }} (jdk-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', '15.0.0-ea.14.1.202003160455']
steps:
- name: Checkout
uses: actions/checkout@v2
- name: setup-java
uses: ./
id: setup-java
with:
java-version: ${{ matrix.version }}
distribution: adopt
- name: Verify Java
run: bash __tests__/verify-java.sh "${{ matrix.version }}" "${{ steps.setup-java.outputs.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
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
distribution: ['adopt', 'zulu']
java-package: ['jre']
version:
- '15.0'
include:
- distribution: 'zulu'
java-package: jre+fx
version: '8'
os: ubuntu-latest
- distribution: 'zulu'
java-package: jdk+fx
version: '8.0.242'
os: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: setup-java
uses: ./
id: setup-java
with:
java-version: ${{ matrix.version }}
java-package: ${{ matrix.java-package }}
distribution: ${{ matrix.distribution }}
- name: Verify Java
run: bash __tests__/verify-java.sh "${{ matrix.version }}" "${{ steps.setup-java.outputs.path }}"
shell: bash
setup-java-custom-architecture:
name: ${{ matrix.distribution }} ${{ matrix.version }} (jdk-x86) - ${{ matrix.os }}
needs: setup-java-major-minor-versions
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
# Only Zulu provides x86 arch for now and only for windows / ubuntu
os: [windows-latest, ubuntu-latest]
distribution: ['zulu']
version: ['11']
steps:
- name: Checkout
uses: actions/checkout@v2
- name: setup-java
uses: ./
id: setup-java
with:
distribution: ${{ matrix.distribution }}
java-version: ${{ matrix.version }}
architecture: x86
- name: Verify Java
run: bash __tests__/verify-java.sh "${{ matrix.version }}" "${{ steps.setup-java.outputs.path }}"
shell: bash

20
.github/workflows/licensed.yml vendored Normal file
View File

@ -0,0 +1,20 @@
name: Licensed
on:
push: {branches: main}
pull_request: {branches: main}
jobs:
test:
runs-on: ubuntu-latest
name: Check licenses
steps:
- uses: actions/checkout@v2
- run: npm ci
- name: Install licensed
run: |
cd $RUNNER_TEMP
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/2.12.2/licensed-2.12.2-linux-x64.tar.gz
sudo tar -xzf licensed.tar.gz
sudo mv licensed /usr/local/bin/licensed
- run: licensed status

View File

@ -1,12 +0,0 @@
name: Lint YAML
on: [pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Lint action.yml
uses: ibiqlik/action-yamllint@master
with:
file_or_dir: action.yml
config_file: yaml-lint-config.yml

View File

@ -1,26 +0,0 @@
name: Main workflow
on: [push, pull_request]
jobs:
run:
name: Run
runs-on: ${{ matrix.operating-system }}
strategy:
matrix:
operating-system: [ubuntu-latest, windows-latest]
steps:
- name: Checkout
uses: actions/checkout@master
- name: Set Node.js 10.x
uses: actions/setup-node@master
with:
node-version: 10.x
- name: npm install
run: npm install
- name: Lint
run: npm run format-check
- name: npm test
run: npm test

14
.licensed.yml Normal file
View File

@ -0,0 +1,14 @@
sources:
npm: true
allowed:
- apache-2.0
- bsd-2-clause
- bsd-3-clause
- isc
- mit
- cc0-1.0
- unlicense
reviewed:
npm:

BIN
.licenses/npm/@actions/core.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/@actions/exec.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/@actions/http-client.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/@actions/io.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/@actions/tool-cache.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/@oozcitak/dom.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/@oozcitak/infra.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/@oozcitak/url.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/@oozcitak/util.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/@types/node.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/argparse.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/esprima.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/js-yaml.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/lru-cache.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/semver-6.3.0.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/semver-7.3.4.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/sprintf-js.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/tunnel.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/uuid.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/xmlbuilder2.dep.yml generated Normal file

Binary file not shown.

BIN
.licenses/npm/yallist.dep.yml generated Normal file

Binary file not shown.

View File

@ -1,11 +1,11 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid",
"parser": "typescript"
}
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
"arrowParens": "avoid",
"parser": "typescript"
}

38
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,38 @@
# Contributors
### Checkin
- Do checkin source (src)
- Do checkin a single index.js file after running `ncc`
- Do not checking node_modules
### NCC
In order to avoid uploading `node_modules` to the repository, we use [zeit/ncc](https://github.com/zeit/ncc) to create multiple `index.js` files that gets saved under `dist/`.
There are two main files that get created
- `dist/setup/index.js`
- Core `setup-java` logic that downloads and installs an appropriate version of Java
- Handling creating a `settings.xml` file to make it easier to publish packages
- `dist/cleanup/index/js`
- Extra cleanup script that is used to remove GPG keys (needed for certain self-hosted runner scenarios)
If you're developing locally, after doing `npm install`, you can use the following commands
```yaml
npm run build # runs tsc along with ncc
npm run format # runs prettier --write
npm run format-check # runs prettier --check
npm run test # runs jest
npm run release # add all the necessary ncc files under dist/* to the git staging area
```
Any files generated using `tsc` will be added to `lib/*`, however those files also are not uploaded to the repository and are excluded using `.gitignore`.
### Testing
Tests are included under `_tests_/*` and can be run using `npm run-script test`.
We ask that you include a link to a successful run that utilizes the changes you are working on. For example, if your changes are in the branch `newAwesomeFeature`, then show an example run that uses `setup-python@newAwesomeFeature` or `my-fork@newAwesomeFeature`. This will help speed up testing and help us confirm that there are no breaking changes or bugs.
### Licensed
This repository uses a tool called [Licensed](https://github.com/github/licensed) to verify third party dependencies. You may need to locally install licensed and run `licensed cache` to update the dependency cache if you install or update a production dependency. If licensed cache is unable to determine the dependency, you may need to modify the cache file yourself to put the correct license. You should still verify the dependency, licensed is a tool to help, but is not a substitute for human review of dependencies.

224
README.md
View File

@ -4,182 +4,114 @@
<a href="https://github.com/actions/setup-java"><img alt="GitHub Actions status" src="https://github.com/actions/setup-java/workflows/Main%20workflow/badge.svg"></a>
</p>
This action sets up a java environment for use in actions by:
This action provides the following functionality for GitHub Actions runners:
- Downloading and setting up a requested version of Java. See [Usage](#Usage) for a list of supported distributions
- Extracting and caching custom version of Java from a local file
- Configuring runner for publishing using Apache Maven
- Configuring runner for publishing using Gradle
- Configuring runner for using GPG private key
- Registering problem matchers for error output
- optionally downloading and caching a requested version of java by version and adding to PATH. Default downloads are populated from the [Zulu Community distribution of OpenJDK](http://static.azul.com/zulu/bin/)
- registering problem matchers for error output
## V2 vs V1
- V2 supports custom distributions and provides support for Zulu OpenJDK and Adopt OpenJDK out of the box. V1 supports only Zulu OpenJDK
- V2 requires you to specify distribution along with the version. V1 defaults to Zulu OpenJDK, only version input is required. Follow [the migration guide](docs/switching-to-v2.md) to switch from V1 to V2
# Usage
## Usage
Inputs `java-version` and `distribution` are mandatory. See [Supported distributions](../README.md#Supported-distributions) section for a list of available options.
See [action.yml](action.yml)
## Basic
### Basic
**Adopt OpenJDK**
```yaml
steps:
- uses: actions/checkout@v1
- uses: actions/setup-java@v1
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
java-version: '9.0.4' # The JDK version to make available on the path. Takes a whole or semver JDK version, or 1.x syntax (e.g. 1.8 => Jdk 8.x). To specify a specific version for JDK 8 or older use the following pattern (8.0.x)
java-package: jdk # (jre, jdk, or jdk+fx) - defaults to jdk
architecture: x64 # (x64 or x86) - defaults to x64
distribution: 'adopt' # See 'Supported distributions' for available options
java-version: '11'
- run: java -cp java HelloWorldApp
```
## Local file
**Zulu OpenJDK**
```yaml
steps:
- uses: actions/checkout@v1
- uses: actions/setup-java@v1
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
java-version: '4.0.0'
architecture: x64
jdkFile: <path to jdkFile> # Optional - jdkFile to install java from. Useful for versions not found on Zulu Community CDN
distribution: 'zulu' # See 'Supported distributions' for available options
java-version: '11'
- run: java -cp java HelloWorldApp
```
## Matrix Testing
#### Supported version syntax
The `java-version` input supports an exact version or a version range using [SemVer](https://semver.org/) notation:
- major versions: `8`, `11`, `15`
- more specific versions: `11.0`, `11.0.4`, `8.0.232`, `8.0.282+8`
- early access (EA) versions: `15-ea`, `15.0.0-ea`, `15.0.0-ea.2`, `15.0.0+2-ea`
#### Supported distributions
Currently, the following distributions are supported:
| Keyword | Distribution | Official site | License |
|-|-|-|-|
| `zulu` | Zulu OpenJDK | [Link](https://www.azul.com/downloads/zulu-community/?package=jdk) | [Link](https://www.azul.com/products/zulu-and-zulu-enterprise/zulu-terms-of-use/) |
| `adopt` | Adopt OpenJDK | [Link](https://adoptopenjdk.net/) | [Link](https://adoptopenjdk.net/about.html)
**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.
### Check latest
In the basic examples above, the `check-latest` flag defaults to `false`. When set to `false`, the action tries to first resolve a version of Java from the local tool cache on the runner. If unable to find a specific version in the cache, the action will download a version of Java. Use the default or set `check-latest` to `false` if you prefer a faster more consistent setup experience that prioritizes trying to use the cached versions at the expense of newer versions sometimes being available for download.
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.
For Java distributions that are not cached on Hosted images, `check-latest` always behaves as `true` and downloads Java on-flight. 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@v2
- uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '11'
check-latest: true
- run: java -cp java HelloWorldApp
```
### Testing against different Java versions
```yaml
jobs:
build:
runs-on: ubuntu-16.04
runs-on: ubuntu-20.04
strategy:
matrix:
# test against latest update of each major Java version, as well as specific updates of LTS versions:
java: [ 1.6, 6.0.83, 7, 7.0.181, 8, 8.0.192, 9.0.x, 10, 11.0.x, 11.0.3, 12, 13 ]
name: Java ${{ matrix.java }} sample
java: [ '8', '11', '13', '15' ]
name: Java ${{ matrix.Java }} sample
steps:
- uses: actions/checkout@master
- uses: actions/checkout@v2
- name: Setup java
uses: actions/setup-java@v1
uses: actions/setup-java@v2
with:
distribution: '<distribution>'
java-version: ${{ matrix.java }}
- run: java -cp java HelloWorldApp
```
## Publishing using Apache Maven
```yaml
jobs:
build:
### Advanced
- [Selecting a Java distribution](docs/advanced-usage.md#Selecting-a-Java-distribution)
- [Adopt](docs/advanced-usage.md#Adopt)
- [Zulu](docs/advanced-usage.md#Zulu)
- [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)
- [Publishing using Gradle](docs/advanced-usage.md#Publishing-using-Gradle)
- [Hosted Tool Cache](docs/advanced-usage.md#Hosted-Tool-Cache)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Publish to GitHub Packages Apache Maven
run: mvn deploy
env:
GITHUB_TOKEN: ${{ github.token }} # GITHUB_TOKEN is the default env for the password
- name: Set up Apache Maven Central
uses: actions/setup-java@v1
with: # running setup-java again overwrites the settings.xml
java-version: 1.8
server-id: maven # Value of the distributionManagement/repository/id field of the pom.xml
server-username: MAVEN_USERNAME # env variable for username in deploy
server-password: MAVEN_CENTRAL_TOKEN # env variable for token in deploy
- name: Publish to Apache Maven Central
run: mvn deploy
env:
MAVEN_USERNAME: maven_username123
MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }}
```
The two `settings.xml` files created from the above example look like the following.
`settings.xml` file created for the first deploy to GitHub Packages
```xml
<servers>
<server>
<id>github</id>
<username>${env.GITHUB_ACTOR}</username>
<password>${env.GITHUB_TOKEN}</password>
</server>
</servers>
```
`settings.xml` file created for the second deploy to Apache Maven Central
```xml
<servers>
<server>
<id>maven</id>
<username>${env.MAVEN_USERNAME}</username>
<password>${env.MAVEN_CENTRAL_TOKEN}</password>
</server>
</servers>
```
***NOTE: The `settings.xml` file is created in the Actions $HOME directory. If you have an existing `settings.xml` file at that location, it will be overwritten. See below for using the `settings-path` to change your `settings.xml` file location.***
See the help docs on [Publishing a Package](https://help.github.com/en/github/managing-packages-with-github-packages/configuring-apache-maven-for-use-with-github-packages#publishing-a-package) for more information on the `pom.xml` file.
## Publishing using Gradle
```yaml
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up JDK 1.8
uses: actions/setup-java@v1
- name: Build with Gradle
run: gradle build
- name: Publish to GitHub Packages
run: gradle publish
env:
USERNAME: ${{ github.actor }}
PASSWORD: ${{ secrets.GITHUB_TOKEN }}
```
***NOTE: The `USERNAME` and `PASSWORD` need to correspond to the credentials environment variables used in the publishing section of your `build.gradle`.***
See the help docs on [Publishing a Package with Gradle](https://help.github.com/en/github/managing-packages-with-github-packages/configuring-gradle-for-use-with-github-packages#example-using-gradle-groovy-for-a-single-package-in-a-repository) for more information on the `build.gradle` configuration file.
## Apache Maven with a settings path
When using an Actions self-hosted runner with multiple shared runners the default `$HOME` directory can be shared by a number runners at the same time which could overwrite existing settings file. Setting the `settings-path` variable allows you to choose a unique location for your settings file.
```yaml
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up JDK 1.8 for Shared Runner
uses: actions/setup-java@v1
with:
java-version: 1.8
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Publish to GitHub Packages Apache Maven
run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml
env:
GITHUB_TOKEN: ${{ github.token }}
```
# License
## License
The scripts and documentation in this project are released under the [MIT License](LICENSE)
# Contributions
## Contributions
Contributions are welcome! See [Contributor's Guide](docs/contributors.md)

View File

@ -1,14 +1,7 @@
import io = require('@actions/io');
import fs = require('fs');
import os = require('os');
import path = require('path');
// make the os.homedir() call be local to the tests
jest.doMock('os', () => {
return {
homedir: jest.fn(() => __dirname)
};
});
import os from 'os';
import * as auth from '../src/auth';
@ -16,8 +9,12 @@ const m2Dir = path.join(__dirname, auth.M2_DIR);
const settingsFile = path.join(m2Dir, auth.SETTINGS_FILE);
describe('auth tests', () => {
let spyOSHomedir: jest.SpyInstance;
beforeEach(async () => {
await io.rmRF(m2Dir);
spyOSHomedir = jest.spyOn(os, 'homedir');
spyOSHomedir.mockReturnValue(__dirname);
}, 300000);
afterAll(async () => {
@ -26,6 +23,9 @@ describe('auth tests', () => {
} catch {
console.log('Failed to remove test directories');
}
jest.resetAllMocks();
jest.clearAllMocks();
jest.restoreAllMocks();
}, 100000);
it('creates settings.xml in alternate locations', async () => {
@ -35,10 +35,9 @@ describe('auth tests', () => {
const altHome = path.join(__dirname, 'runner', 'settings');
const altSettingsFile = path.join(altHome, auth.SETTINGS_FILE);
process.env[`INPUT_SETTINGS-PATH`] = altHome;
await io.rmRF(altHome); // ensure it doesn't already exist
await auth.configAuthentication(id, username, password);
await auth.createAuthenticationSettings(id, username, password, altHome, true);
expect(fs.existsSync(m2Dir)).toBe(false);
expect(fs.existsSync(settingsFile)).toBe(false);
@ -49,21 +48,33 @@ describe('auth tests', () => {
auth.generate(id, username, password)
);
delete process.env[`INPUT_SETTINGS-PATH`];
await io.rmRF(altHome);
}, 100000);
it('creates settings.xml with username and password', async () => {
it('creates settings.xml with minimal configuration', async () => {
const id = 'packages';
const username = 'UNAME';
const password = 'TOKEN';
await auth.configAuthentication(id, username, password);
await auth.createAuthenticationSettings(id, username, password, m2Dir, true);
expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(auth.generate(id, username, password));
}, 100000);
it('creates settings.xml with additional configuration', async () => {
const id = 'packages';
const username = 'UNAME';
const password = 'TOKEN';
const gpgPassphrase = 'GPG';
await auth.createAuthenticationSettings(id, username, password, m2Dir, true, gpgPassphrase);
expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
auth.generate(id, username, password)
auth.generate(id, username, password, gpgPassphrase)
);
}, 100000);
@ -72,73 +83,77 @@ describe('auth tests', () => {
const username = 'USERNAME';
const password = 'PASSWORD';
fs.mkdirSync(m2Dir, {recursive: true});
fs.mkdirSync(m2Dir, { recursive: true });
fs.writeFileSync(settingsFile, 'FAKE FILE');
expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
await auth.configAuthentication(id, username, password);
await auth.createAuthenticationSettings(id, username, password, m2Dir, true);
expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
auth.generate(id, username, password)
);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(auth.generate(id, username, password));
}, 100000);
it('does not create settings.xml without required parameters', async () => {
await auth.configAuthentication('FOO');
it('does not overwrite existing settings.xml files', async () => {
const id = 'packages';
const username = 'USERNAME';
const password = 'PASSWORD';
fs.mkdirSync(m2Dir, { recursive: true });
fs.writeFileSync(settingsFile, 'FAKE FILE');
expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
await auth.createAuthenticationSettings(id, username, password, m2Dir, false);
expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
auth.generate('FOO', auth.DEFAULT_USERNAME, auth.DEFAULT_PASSWORD)
);
await auth.configAuthentication(undefined, 'BAR', undefined);
expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
auth.generate(auth.DEFAULT_ID, 'BAR', auth.DEFAULT_PASSWORD)
);
await auth.configAuthentication(undefined, undefined, 'BAZ');
expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
auth.generate(auth.DEFAULT_ID, auth.DEFAULT_USERNAME, 'BAZ')
);
await auth.configAuthentication();
expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
auth.generate(
auth.DEFAULT_ID,
auth.DEFAULT_USERNAME,
auth.DEFAULT_PASSWORD
)
);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual('FAKE FILE');
}, 100000);
it('escapes invalid XML inputs', () => {
it('generates valid settings.xml with minimal configuration', () => {
const id = 'packages';
const username = 'USER';
const password = '&<>"\'\'"><&';
expect(auth.generate(id, username, password)).toEqual(`
<settings>
<servers>
<server>
<id>${id}</id>
<username>\${env.${username}}</username>
<password>\${env.&amp;&lt;&gt;&quot;&apos;&apos;&quot;&gt;&lt;&amp;}</password>
</server>
</servers>
</settings>
`);
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">
<servers>
<server>
<id>${id}</id>
<username>\${env.${username}}</username>
<password>\${env.&amp;&lt;&gt;"''"&gt;&lt;&amp;}</password>
</server>
</servers>
</settings>`;
expect(auth.generate(id, username, password)).toEqual(expectedSettings);
});
it('generates valid settings.xml with additional configuration', () => {
const id = 'packages';
const username = 'USER';
const password = '&<>"\'\'"><&';
const gpgPassphrase = '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">
<servers>
<server>
<id>${id}</id>
<username>\${env.${username}}</username>
<password>\${env.&amp;&lt;&gt;"''"&gt;&lt;&amp;}</password>
</server>
<server>
<id>gpg.passphrase</id>
<passphrase>\${env.${gpgPassphrase}}</passphrase>
</server>
</servers>
</settings>`;
expect(auth.generate(id, username, password, gpgPassphrase)).toEqual(expectedSettings);
});
});

909
__tests__/data/adopt.json Normal file
View File

@ -0,0 +1,909 @@
[
{
"binaries": [
{
"architecture": "x64",
"download_count": 74181,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "09b7e6ab5d5eb4b73813f4caa793a0b616d33794a17988fa6a6b7c972e8f3dd3",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk14-binaries/releases/download/jdk-14.0.2%2B12/OpenJDK14U-jdk_x64_mac_hotspot_14.0.2_12.tar.gz.sha256.txt",
"download_count": 23872,
"link": "https://github.com/AdoptOpenJDK/openjdk14-binaries/releases/download/jdk-14.0.2%2B12/OpenJDK14U-jdk_x64_mac_hotspot_14.0.2_12.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk14-binaries/releases/download/jdk-14.0.2%2B12/OpenJDK14U-jdk_x64_mac_hotspot_14.0.2_12.tar.gz.json",
"name": "OpenJDK14U-jdk_x64_mac_hotspot_14.0.2_12.tar.gz",
"size": 195705010
},
"project": "jdk",
"scm_ref": "jdk-14.0.2+12_adopt",
"updated_at": "2020-07-16T08:55:45Z"
}
],
"download_count": 477080,
"id": "MDc6UmVsZWFzZTI4NjIyMDc4.+ve8KojpqJUpsA==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk14-binaries/releases/tag/jdk-14.0.2%2B12",
"release_name": "jdk-14.0.2+12",
"release_type": "ga",
"timestamp": "2020-07-16T08:54:16Z",
"updated_at": "2020-07-16T08:54:16Z",
"vendor": "adoptopenjdk",
"version_data": {
"build": 12,
"major": 14,
"minor": 0,
"openjdk_version": "14.0.2+12",
"security": 2,
"semver": "14.0.2+12"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 58023,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "b11cb192312530bcd84607631203d0c1727e672af12813078e6b525e3cce862d",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk14-binaries/releases/download/jdk-14.0.1%2B7/OpenJDK14U-jdk_x64_mac_hotspot_14.0.1_7.tar.gz.sha256.txt",
"download_count": 25276,
"link": "https://github.com/AdoptOpenJDK/openjdk14-binaries/releases/download/jdk-14.0.1%2B7/OpenJDK14U-jdk_x64_mac_hotspot_14.0.1_7.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk14-binaries/releases/download/jdk-14.0.1%2B7/OpenJDK14U-jdk_x64_mac_hotspot_14.0.1_7.tar.gz.json",
"name": "OpenJDK14U-jdk_x64_mac_hotspot_14.0.1_7.tar.gz",
"size": 195769653
},
"project": "jdk",
"scm_ref": "jdk-14.0.1+7_adopt",
"updated_at": "2020-04-20T12:54:23Z"
}
],
"download_count": 198607,
"id": "MDc6UmVsZWFzZTI1Njc4MzEw.z3NqYG25PFlG+Q==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk14-binaries/releases/tag/jdk-14.0.1%2B7",
"release_name": "jdk-14.0.1+7",
"release_type": "ga",
"timestamp": "2020-04-20T12:52:51Z",
"updated_at": "2020-04-20T12:52:51Z",
"vendor": "adoptopenjdk",
"version_data": {
"adopt_build_number": 1,
"build": 7,
"major": 14,
"minor": 0,
"openjdk_version": "14.0.1+7",
"security": 1,
"semver": "14.0.1+7.1"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 30069,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "d358a7ff03905282348c6c80562a4da2e04eb377b60ad2152be4c90f8d580b7f",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15.0.2%2B7/OpenJDK15U-jdk_x64_mac_hotspot_15.0.2_7.tar.gz.sha256.txt",
"download_count": 3718,
"link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15.0.2%2B7/OpenJDK15U-jdk_x64_mac_hotspot_15.0.2_7.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15.0.2%2B7/OpenJDK15U-jdk_x64_mac_hotspot_15.0.2_7.tar.gz.json",
"name": "OpenJDK15U-jdk_x64_mac_hotspot_15.0.2_7.tar.gz",
"size": 195232978
},
"project": "jdk",
"scm_ref": "jdk-15.0.2+7_adopt",
"updated_at": "2021-01-22T17:33:20Z"
}
],
"download_count": 124226,
"id": "MDc6UmVsZWFzZTM2NzgwOTAw.X2+6VqPND3E8CA==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/tag/jdk-15.0.2%2B7",
"release_name": "jdk-15.0.2+7",
"release_type": "ga",
"timestamp": "2021-01-22T17:31:37Z",
"updated_at": "2021-01-22T17:31:37Z",
"vendor": "adoptopenjdk",
"version_data": {
"build": 7,
"major": 15,
"minor": 0,
"openjdk_version": "15.0.2+7",
"security": 2,
"semver": "15.0.2+7"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 24542,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "b8c2e2ad31f3d6676ea665d9505b06df15e23741847556612b40e3ee329fc046",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15.0.1%2B9.1/OpenJDK15U-jdk_x64_mac_hotspot_15.0.1_9.tar.gz.sha256.txt",
"download_count": 3274,
"link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15.0.1%2B9.1/OpenJDK15U-jdk_x64_mac_hotspot_15.0.1_9.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15.0.1%2B9.1/OpenJDK15U-jdk_x64_mac_hotspot_15.0.1_9.tar.gz.json",
"name": "OpenJDK15U-jdk_x64_mac_hotspot_15.0.1_9.tar.gz",
"size": 195872839
},
"project": "jdk",
"scm_ref": "jdk-15.0.1+9_adopt",
"updated_at": "2020-12-01T16:57:47Z"
}
],
"download_count": 25378,
"id": "MDc6UmVsZWFzZTM0NjQ2MDU4.Yj2XZf+VBGAPtw==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/tag/jdk-15.0.1%2B9.1",
"release_name": "jdk-15.0.1+9.1",
"release_type": "ga",
"timestamp": "2020-12-01T16:57:26Z",
"updated_at": "2020-12-01T16:57:26Z",
"vendor": "adoptopenjdk",
"version_data": {
"adopt_build_number": 1,
"build": 9,
"major": 15,
"minor": 0,
"openjdk_version": "15.0.1+9",
"security": 1,
"semver": "15.0.1+9.1"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 21675,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "d32f9429c4992cef7be559a15c542011503d6bc38c89379800cd209a9d7ec539",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15.0.1%2B9/OpenJDK15U-jdk_x64_mac_hotspot_15.0.1_9.tar.gz.sha256.txt",
"download_count": 11935,
"link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15.0.1%2B9/OpenJDK15U-jdk_x64_mac_hotspot_15.0.1_9.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15.0.1%2B9/OpenJDK15U-jdk_x64_mac_hotspot_15.0.1_9.tar.gz.json",
"name": "OpenJDK15U-jdk_x64_mac_hotspot_15.0.1_9.tar.gz",
"size": 195773522
},
"project": "jdk",
"scm_ref": "jdk-15.0.1+9_adopt",
"updated_at": "2020-10-23T20:48:09Z"
}
],
"download_count": 308690,
"id": "MDc6UmVsZWFzZTMyOTk4MTUx.3oazo3YGfHhF3w==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/tag/jdk-15.0.1%2B9",
"release_name": "jdk-15.0.1+9",
"release_type": "ga",
"timestamp": "2020-10-23T20:46:22Z",
"updated_at": "2020-10-23T20:46:22Z",
"vendor": "adoptopenjdk",
"version_data": {
"build": 9,
"major": 15,
"minor": 0,
"openjdk_version": "15.0.1+9",
"security": 1,
"semver": "15.0.1+9"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 51254,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "bd1fc774232e2dfee93056a01f5765bd92ffb19d68dd548c233a82bb5c162be4",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15%2B36/OpenJDK15U-jdk_x64_mac_hotspot_15_36.tar.gz.sha256.txt",
"download_count": 5325,
"link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15%2B36/OpenJDK15U-jdk_x64_mac_hotspot_15_36.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15%2B36/OpenJDK15U-jdk_x64_mac_hotspot_15_36.tar.gz.json",
"name": "OpenJDK15U-jdk_x64_mac_hotspot_15_36.tar.gz",
"size": 195853361
},
"project": "jdk",
"scm_ref": "jdk-15+36_adopt",
"updated_at": "2020-09-17T07:43:54Z"
}
],
"download_count": 157313,
"id": "MDc6UmVsZWFzZTMxNDUwMjA0.eYpt0EBEjldfEQ==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/tag/jdk-15%2B36",
"release_name": "jdk-15+36",
"release_type": "ga",
"timestamp": "2020-09-17T07:42:21Z",
"updated_at": "2020-09-17T07:42:21Z",
"vendor": "adoptopenjdk",
"version_data": {
"build": 36,
"major": 15,
"minor": 0,
"openjdk_version": "15+36",
"security": 0,
"semver": "15.0.0+36"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 27428,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "aabc3aebb0abf1ba64d9bd5796d0c7eb7239983f6e4c0f015b5b88be5616e4bd",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk14-binaries/releases/download/jdk-14%2B36/OpenJDK14U-jdk_x64_mac_hotspot_14_36.tar.gz.sha256.txt",
"download_count": 19544,
"link": "https://github.com/AdoptOpenJDK/openjdk14-binaries/releases/download/jdk-14%2B36/OpenJDK14U-jdk_x64_mac_hotspot_14_36.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk14-binaries/releases/download/jdk-14%2B36/OpenJDK14U-jdk_x64_mac_hotspot_14_36.tar.gz.json",
"name": "OpenJDK14U-jdk_x64_mac_hotspot_14_36.tar.gz",
"size": 201087797
},
"project": "jdk",
"scm_ref": "jdk-14+36_adopt",
"updated_at": "2020-03-18T12:13:05Z"
}
],
"download_count": 364816,
"id": "MDc6UmVsZWFzZTI0NjMxMDAy.AY7rtvmrnWWlIg==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk14-binaries/releases/tag/jdk-14%2B36",
"release_name": "jdk-14+36",
"release_type": "ga",
"timestamp": "2020-03-18T12:11:08Z",
"updated_at": "2020-03-18T12:11:08Z",
"vendor": "adoptopenjdk",
"version_data": {
"adopt_build_number": 1,
"build": 36,
"major": 14,
"minor": 0,
"openjdk_version": "14+36",
"security": 0,
"semver": "14.0.0+36.1"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 63201,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "0ddb24efdf5aab541898d19b7667b149a1a64a8bd039b708fc58ee0284fa7e07",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk13-binaries/releases/download/jdk-13.0.2%2B8/OpenJDK13U-jdk_x64_mac_hotspot_13.0.2_8.tar.gz.sha256.txt",
"download_count": 32531,
"link": "https://github.com/AdoptOpenJDK/openjdk13-binaries/releases/download/jdk-13.0.2%2B8/OpenJDK13U-jdk_x64_mac_hotspot_13.0.2_8.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk13-binaries/releases/download/jdk-13.0.2%2B8/OpenJDK13U-jdk_x64_mac_hotspot_13.0.2_8.tar.gz.json",
"name": "OpenJDK13U-jdk_x64_mac_hotspot_13.0.2_8.tar.gz",
"size": 198206427
},
"project": "jdk",
"scm_ref": "jdk-13.0.2+8_adopt",
"updated_at": "2020-01-20T16:46:24Z"
}
],
"download_count": 349677,
"id": "MDc6UmVsZWFzZTIyOTgxNTM1.gtZYwGfBgkb3Gg==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk13-binaries/releases/tag/jdk-13.0.2%2B8",
"release_name": "jdk-13.0.2+8",
"release_type": "ga",
"timestamp": "2020-01-20T16:42:35Z",
"updated_at": "2020-01-20T16:42:35Z",
"vendor": "adoptopenjdk",
"version_data": {
"adopt_build_number": 1,
"build": 8,
"major": 13,
"minor": 0,
"openjdk_version": "13.0.2+8",
"security": 2,
"semver": "13.0.2+8.1"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 41508,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "9c82de98ce9bc2353bcf314d85366c9a2c572db034e10a71aa47e804e13748c1",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk13-binaries/releases/download/jdk-13.0.1%2B9/OpenJDK13U-jdk_x64_mac_hotspot_13.0.1_9.tar.gz.sha256.txt",
"download_count": 32262,
"link": "https://github.com/AdoptOpenJDK/openjdk13-binaries/releases/download/jdk-13.0.1%2B9/OpenJDK13U-jdk_x64_mac_hotspot_13.0.1_9.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk13-binaries/releases/download/jdk-13.0.1%2B9/OpenJDK13U-jdk_x64_mac_hotspot_13.0.1_9.tar.gz.json",
"name": "OpenJDK13U-jdk_x64_mac_hotspot_13.0.1_9.tar.gz",
"size": 198205689
},
"project": "jdk",
"scm_ref": "jdk-13.0.1+9_adopt",
"updated_at": "2019-10-26T14:44:27Z"
}
],
"download_count": 680021,
"id": "MDc6UmVsZWFzZTIwOTk4NDA0.srlG2TmLho/j0w==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk13-binaries/releases/tag/jdk-13.0.1%2B9",
"release_name": "jdk-13.0.1+9",
"release_type": "ga",
"timestamp": "2019-10-26T14:43:52Z",
"updated_at": "2019-10-26T14:43:52Z",
"vendor": "adoptopenjdk",
"version_data": {
"adopt_build_number": 1,
"build": 9,
"major": 13,
"minor": 0,
"openjdk_version": "13.0.1+9",
"security": 1,
"semver": "13.0.1+9.1"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 37738,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "f948be96daba250b6695e22cb51372d2ba3060e4d778dd09c89548889783099f",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk13-binaries/releases/download/jdk-13%2B33/OpenJDK13U-jdk_x64_mac_hotspot_13_33.tar.gz.sha256.txt",
"download_count": 37738,
"link": "https://github.com/AdoptOpenJDK/openjdk13-binaries/releases/download/jdk-13%2B33/OpenJDK13U-jdk_x64_mac_hotspot_13_33.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk13-binaries/releases/download/jdk-13%2B33/OpenJDK13U-jdk_x64_mac_hotspot_13_33.tar.gz.json",
"name": "OpenJDK13U-jdk_x64_mac_hotspot_13_33.tar.gz",
"size": 198189530
},
"project": "jdk",
"scm_ref": "jdk-13+33_adopt",
"updated_at": "2019-09-19T10:20:21Z"
}
],
"download_count": 226200,
"id": "MDc6UmVsZWFzZTIwMTA0MTUy.trK7qCbNtlMWFw==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk13-binaries/releases/tag/jdk-13%2B33",
"release_name": "jdk-13+33",
"release_type": "ga",
"timestamp": "2019-09-19T10:19:58Z",
"updated_at": "2019-09-19T10:19:58Z",
"vendor": "adoptopenjdk",
"version_data": {
"adopt_build_number": 1,
"build": 33,
"major": 13,
"minor": 0,
"openjdk_version": "13+33",
"security": 0,
"semver": "13.0.0+33.1"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 24493,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "9919eee037554d40c7d2f219bbd654f2bf119e16a2f4d284d8dedaf525ee59e6",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12.0.2%2B10/OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz.sha256.txt",
"download_count": 22907,
"link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12.0.2%2B10/OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12.0.2%2B10/OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz.json",
"name": "OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz",
"size": 198392994
},
"project": "jdk",
"scm_ref": "jdk-12.0.2+10_adopt",
"updated_at": "2019-07-18T20:27:24Z"
}
],
"download_count": 396318,
"id": "MDc6UmVsZWFzZTE4NzE2Mzk5.S/VUFSgnrVIv8A==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/tag/jdk-12.0.2%2B10",
"release_name": "jdk-12.0.2+10",
"release_type": "ga",
"timestamp": "2019-07-18T20:26:29Z",
"updated_at": "2019-07-18T20:26:29Z",
"vendor": "adoptopenjdk",
"version_data": {
"adopt_build_number": 1,
"build": 10,
"major": 12,
"minor": 0,
"openjdk_version": "12.0.2+10",
"security": 2,
"semver": "12.0.2+10.1"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 5539,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "7acd697e816491d31b24d0ae1867fd63060aa738cfa388757946ae312a60b4f2",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12.0.2%2B10.3/OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz.sha256.txt",
"download_count": 5539,
"link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12.0.2%2B10.3/OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12.0.2%2B10.3/OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz.json",
"name": "OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz",
"size": 198429049
},
"project": "jdk",
"scm_ref": "jdk-12.0.2+10_adopt",
"updated_at": "2019-09-19T17:17:37Z"
}
],
"download_count": 5879,
"id": "MDc6UmVsZWFzZTIwMTE2ODQ3.QGQl8Nj1qkma4Q==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/tag/jdk-12.0.2%2B10.3",
"release_name": "jdk-12.0.2+10.3",
"release_type": "ga",
"timestamp": "2019-09-19T17:17:26Z",
"updated_at": "2019-12-06T15:10:37Z",
"vendor": "adoptopenjdk",
"version_data": {
"adopt_build_number": 3,
"build": 10,
"major": 12,
"minor": 0,
"openjdk_version": "12.0.2+10",
"security": 2,
"semver": "12.0.2+10.3"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 22794,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "2c1a46c0fab6d4bdbc443f23c3f6a313c2de47fbbd9c16b5c1133a88f6c1ab8f",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12.0.2%2B10.2/OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz.sha256.txt",
"download_count": 637,
"link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12.0.2%2B10.2/OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12.0.2%2B10.2/OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz.json",
"name": "OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz",
"size": 198862174
},
"project": "jdk",
"scm_ref": "jdk-12.0.2+10_adopt",
"updated_at": "2019-08-06T10:41:10Z"
}
],
"download_count": 23563,
"id": "MDc6UmVsZWFzZTE5MTAzMTI3.in65dKG+veAxOg==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/tag/jdk-12.0.2%2B10.2",
"release_name": "jdk-12.0.2+10.2",
"release_type": "ga",
"timestamp": "2019-08-06T10:40:44Z",
"updated_at": "2019-08-06T10:40:44Z",
"vendor": "adoptopenjdk",
"version_data": {
"adopt_build_number": 2,
"build": 10,
"major": 12,
"minor": 0,
"openjdk_version": "12.0.2+10",
"security": 2,
"semver": "12.0.2+10.2"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 24493,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "9919eee037554d40c7d2f219bbd654f2bf119e16a2f4d284d8dedaf525ee59e6",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12.0.2%2B10/OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz.sha256.txt",
"download_count": 22907,
"link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12.0.2%2B10/OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12.0.2%2B10/OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz.json",
"name": "OpenJDK12U-jdk_x64_mac_hotspot_12.0.2_10.tar.gz",
"size": 198392994
},
"project": "jdk",
"scm_ref": "jdk-12.0.2+9_adopt",
"updated_at": "2019-07-18T20:27:24Z"
}
],
"download_count": 396318,
"id": "MDc6UmVsZWFzZTE4NzE2Mzk5.S/VUFSgnrVIv8A==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/tag/jdk-12.0.2%2B10",
"release_name": "jdk-12.0.2+9",
"release_type": "ga",
"timestamp": "2019-07-18T20:26:29Z",
"updated_at": "2019-07-18T20:26:29Z",
"vendor": "adoptopenjdk",
"version_data": {
"adopt_build_number": 1,
"build": 10,
"major": 12,
"minor": 0,
"openjdk_version": "12.0.2+9",
"security": 2,
"semver": "12.0.2+9.1"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 39519,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "dcb2ab681247298eda018df24166ba01674127083fb02892acf087e6181d8c56",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12.0.1%2B12/OpenJDK12U-jdk_x64_mac_hotspot_12.0.1_12.tar.gz.sha256.txt",
"download_count": 33306,
"link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12.0.1%2B12/OpenJDK12U-jdk_x64_mac_hotspot_12.0.1_12.tar.gz",
"name": "OpenJDK12U-jdk_x64_mac_hotspot_12.0.1_12.tar.gz",
"size": 198112975
},
"project": "jdk",
"updated_at": "2019-04-21T15:12:34Z"
}
],
"download_count": 1038669,
"id": "MDc6UmVsZWFzZTE2ODg3NDU3",
"release_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/tag/jdk-12.0.1%2B12",
"release_name": "jdk-12.0.1+12",
"release_type": "ga",
"timestamp": "2019-04-21T15:11:56Z",
"updated_at": "2019-04-21T15:11:56Z",
"vendor": "adoptopenjdk",
"version_data": {
"build": 12,
"major": 12,
"minor": 0,
"openjdk_version": "12.0.1+12",
"security": 1,
"semver": "12.0.1+12"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 3136,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "985036459d4ef0867a3fe83b0bf87877d8e66a121c7b9c145bb97bd921aaf3f1",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12%2B33/OpenJDK12U-jdk_x64_mac_hotspot_12_33.tar.gz.sha256.txt",
"download_count": 1905,
"link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/download/jdk-12%2B33/OpenJDK12U-jdk_x64_mac_hotspot_12_33.tar.gz",
"name": "OpenJDK12U-jdk_x64_mac_hotspot_12_33.tar.gz",
"size": 198099074
},
"project": "jdk",
"updated_at": "2019-03-22T12:09:13Z"
}
],
"download_count": 757289,
"id": "MDc6UmVsZWFzZTE2MjgyMjM2",
"release_link": "https://github.com/AdoptOpenJDK/openjdk12-binaries/releases/tag/jdk-12%2B33",
"release_name": "jdk-12+33",
"release_type": "ga",
"timestamp": "2019-03-22T12:08:43Z",
"updated_at": "2019-03-22T12:08:43Z",
"vendor": "adoptopenjdk",
"version_data": {
"build": 33,
"major": 12,
"minor": 0,
"openjdk_version": "12+33",
"security": 0,
"semver": "12.0.0+33"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 75576,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "ee7c98c9d79689aca6e717965747b8bf4eec5413e89d5444cc2bd6dbd59e3811",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.10%2B9/OpenJDK11U-jdk_x64_mac_hotspot_11.0.10_9.tar.gz.sha256.txt",
"download_count": 17426,
"link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.10%2B9/OpenJDK11U-jdk_x64_mac_hotspot_11.0.10_9.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.10%2B9/OpenJDK11U-jdk_x64_mac_hotspot_11.0.10_9.tar.gz.json",
"name": "OpenJDK11U-jdk_x64_mac_hotspot_11.0.10_9.tar.gz",
"size": 186160219
},
"project": "jdk",
"scm_ref": "jdk-11.0.10+9_adopt",
"updated_at": "2021-01-22T14:16:47Z"
}
],
"download_count": 636180,
"id": "MDc6UmVsZWFzZTM2NzcwNDUy.hAVJRiZZTufG+w==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/tag/jdk-11.0.10%2B9",
"release_name": "jdk-11.0.10+9",
"release_type": "ga",
"timestamp": "2021-01-22T14:15:12Z",
"updated_at": "2021-01-22T14:15:12Z",
"vendor": "adoptopenjdk",
"version_data": {
"build": 9,
"major": 11,
"minor": 0,
"openjdk_version": "11.0.10+9",
"security": 10,
"semver": "11.0.10+9"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 108441,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "96bc469f9b02a3b84382a0685b0bd7935e1ad1bd82a0aab9befb5b42a17cbd77",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.9.1%2B1/OpenJDK11U-jdk_x64_mac_hotspot_11.0.9.1_1.tar.gz.sha256.txt",
"download_count": 22211,
"link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.9.1%2B1/OpenJDK11U-jdk_x64_mac_hotspot_11.0.9.1_1.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.9.1%2B1/OpenJDK11U-jdk_x64_mac_hotspot_11.0.9.1_1.tar.gz.json",
"name": "OpenJDK11U-jdk_x64_mac_hotspot_11.0.9.1_1.tar.gz",
"size": 185368626
},
"project": "jdk",
"scm_ref": "jdk-11.0.9.1+1_adopt",
"updated_at": "2020-11-12T14:10:45Z"
}
],
"download_count": 815676,
"id": "MDc6UmVsZWFzZTMzODU4MDE1.94IbKUd3vvhzsA==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/tag/jdk-11.0.9.1%2B1",
"release_name": "jdk-11.0.9.1+1",
"release_type": "ga",
"timestamp": "2020-11-12T14:08:55Z",
"updated_at": "2020-11-12T14:08:55Z",
"vendor": "adoptopenjdk",
"version_data": {
"build": 1,
"major": 11,
"minor": 0,
"openjdk_version": "11.0.9.1+1",
"patch": 1,
"security": 9,
"semver": "11.0.9+101"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 45450,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "7b21961ffb2649e572721a0dfad64169b490e987937b661cb4e13a594c21e764",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.9%2B11.1/OpenJDK11U-jdk_x64_mac_hotspot_11.0.9_11.tar.gz.sha256.txt",
"download_count": 11117,
"link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.9%2B11.1/OpenJDK11U-jdk_x64_mac_hotspot_11.0.9_11.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.9%2B11.1/OpenJDK11U-jdk_x64_mac_hotspot_11.0.9_11.tar.gz.json",
"name": "OpenJDK11U-jdk_x64_mac_hotspot_11.0.9_11.tar.gz",
"size": 186006796
},
"project": "jdk",
"scm_ref": "jdk-11.0.9+11_adopt",
"updated_at": "2020-10-25T14:43:54Z"
}
],
"download_count": 423635,
"id": "MDc6UmVsZWFzZTMzMDI4MDcz.dRvNNRwJCgY3Xw==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/tag/jdk-11.0.9%2B11.1",
"release_name": "jdk-11.0.9+11.1",
"release_type": "ga",
"timestamp": "2020-10-25T13:31:15Z",
"updated_at": "2020-10-25T13:31:15Z",
"vendor": "adoptopenjdk",
"version_data": {
"adopt_build_number": 1,
"build": 11,
"major": 11,
"minor": 0,
"openjdk_version": "11.0.9+11",
"security": 9,
"semver": "11.0.9+11.1"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 2456,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "e84b00d74f08f059829bbf121c8423dc37ff65135968c1fcda5839600be4f542",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.9%2B11/OpenJDK11U-jdk_x64_mac_hotspot_11.0.9_11.tar.gz.sha256.txt",
"download_count": 1046,
"link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.9%2B11/OpenJDK11U-jdk_x64_mac_hotspot_11.0.9_11.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.9%2B11/OpenJDK11U-jdk_x64_mac_hotspot_11.0.9_11.tar.gz.json",
"name": "OpenJDK11U-jdk_x64_mac_hotspot_11.0.9_11.tar.gz",
"size": 185532704
},
"project": "jdk",
"scm_ref": "jdk-11.0.9+11_adopt",
"updated_at": "2020-10-25T13:28:33Z"
}
],
"download_count": 359580,
"id": "MDc6UmVsZWFzZTMyOTk4MzM5.6h9TT9pzYTK2Kg==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/tag/jdk-11.0.9%2B11",
"release_name": "jdk-11.0.9+11",
"release_type": "ga",
"timestamp": "2020-10-23T20:52:14Z",
"updated_at": "2020-10-23T20:52:14Z",
"vendor": "adoptopenjdk",
"version_data": {
"build": 11,
"major": 11,
"minor": 0,
"openjdk_version": "11.0.9+11",
"security": 9,
"semver": "11.0.9+11"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 149393,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "4a8dadd58cdc32c7e59978971d56aec610be7ee0ddf0dc1d137bb8b78456499f",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.8%2B10/OpenJDK11U-jdk_x64_mac_hotspot_11.0.8_10.tar.gz.sha256.txt",
"download_count": 40158,
"link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.8%2B10/OpenJDK11U-jdk_x64_mac_hotspot_11.0.8_10.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.8%2B10/OpenJDK11U-jdk_x64_mac_hotspot_11.0.8_10.tar.gz.json",
"name": "OpenJDK11U-jdk_x64_mac_hotspot_11.0.8_10.tar.gz",
"size": 185054456
},
"project": "jdk",
"scm_ref": "jdk-11.0.8+10_adopt",
"updated_at": "2020-07-15T14:30:51Z"
}
],
"download_count": 1968658,
"id": "MDc6UmVsZWFzZTI4NTg5Nzcz.pCNBA7G9E1o7pw==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/tag/jdk-11.0.8%2B10",
"release_name": "jdk-11.0.8+10",
"release_type": "ga",
"timestamp": "2020-07-15T14:29:27Z",
"updated_at": "2020-07-15T14:29:27Z",
"vendor": "adoptopenjdk",
"version_data": {
"build": 10,
"major": 11,
"minor": 0,
"openjdk_version": "11.0.8+10",
"security": 8,
"semver": "11.0.8+10"
}
},
{
"binaries": [],
"download_count": 1968658,
"id": "MDc6UmVsZWFzZTI4NTg5Nzcz.pCNBA7G9E1o7pw==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/tag/jdk-11.0.8%2B10",
"release_name": "jdk-11.0.8+10",
"release_type": "ga",
"timestamp": "2020-07-15T14:29:27Z",
"updated_at": "2020-07-15T14:29:27Z",
"vendor": "adoptopenjdk",
"version_data": {
"build": 10,
"major": 9,
"minor": 0,
"openjdk_version": "9.0.8+10",
"security": 8,
"semver": "9.0.8+10"
}
},
{
"binaries": [
{
"architecture": "x64",
"download_count": 149393,
"heap_size": "normal",
"image_type": "jdk",
"jvm_impl": "hotspot",
"os": "mac",
"package": {
"checksum": "4a8dadd58cdc32c7e59978971d56aec610be7ee0ddf0dc1d137bb8b78456499f",
"checksum_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.8%2B10/OpenJDK11U-jdk_x64_mac_hotspot_11.0.8_10.tar.gz.sha256.txt",
"download_count": 40158,
"link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.8%2B10/OpenJDK11U-jdk_x64_mac_hotspot_11.0.8_10.tar.gz",
"metadata_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.8%2B10/OpenJDK11U-jdk_x64_mac_hotspot_11.0.8_10.tar.gz.json",
"name": "OpenJDK11U-jdk_x64_mac_hotspot_11.0.8_10.tar.gz",
"size": 185054456
},
"project": "jdk",
"scm_ref": "jdk-11.0.8+10_adopt",
"updated_at": "2020-07-15T14:30:51Z"
}
],
"download_count": 1968658,
"id": "MDc6UmVsZWFzZTI4NTg5Nzcz.pCNBA7G9E1o7pw==",
"release_link": "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/tag/jdk-11.0.8%2B10",
"release_name": "jdk-11.0.8+10",
"release_type": "ga",
"timestamp": "2020-07-15T14:29:27Z",
"updated_at": "2020-07-15T14:29:27Z",
"vendor": "adoptopenjdk",
"version_data": {
"build": 10,
"major": 9,
"minor": 0,
"openjdk_version": "9.0.8+10",
"security": 8,
"semver": "9.0.7+10"
}
}
]

View File

@ -0,0 +1,247 @@
[
{
"id": 10996,
"url": "https://cdn.azul.com/zulu/bin/zulu1.8.0_05-8.1.0.10-macosx.tar.gz",
"name": "zulu1.8.0_05-8.1.0.10-macosx.tar.gz",
"zulu_version": [8, 1, 0, 10],
"jdk_version": [8, 0, 5, 13]
},
{
"id": 10997,
"url": "https://cdn.azul.com/zulu/bin/zulu1.8.0_11-8.2.0.1-macosx.tar.gz",
"name": "zulu1.8.0_11-8.2.0.1-macosx.tar.gz",
"zulu_version": [8, 2, 0, 1],
"jdk_version": [8, 0, 11, 12]
},
{
"id": 10346,
"url": "https://cdn.azul.com/zulu/bin/zulu8.21.0.1-jdk8.0.131-macosx_x64.tar.gz",
"name": "zulu8.21.0.1-jdk8.0.131-macosx_x64.tar.gz",
"zulu_version": [8, 21, 0, 1],
"jdk_version": [8, 0, 131, 11]
},
{
"id": 10362,
"url": "https://cdn.azul.com/zulu/bin/zulu8.23.0.3-jdk8.0.144-macosx_x64.tar.gz",
"name": "zulu8.23.0.3-jdk8.0.144-macosx_x64.tar.gz",
"zulu_version": [8, 23, 0, 3],
"jdk_version": [8, 0, 144, 1]
},
{
"id": 10399,
"url": "https://cdn.azul.com/zulu/bin/zulu8.25.0.1-jdk8.0.152-macosx_x64.tar.gz",
"name": "zulu8.25.0.1-jdk8.0.152-macosx_x64.tar.gz",
"zulu_version": [8, 25, 0, 1],
"jdk_version": [8, 0, 152, 16]
},
{
"id": 11355,
"url": "https://cdn.azul.com/zulu/bin/zulu8.46.0.19-ca-jdk8.0.252-macosx_x64.tar.gz",
"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]
},
{
"id": 11481,
"url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.47-ca-jdk8.0.262-macosx_x64.tar.gz",
"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]
},
{
"id": 11622,
"url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.51-ca-jdk8.0.262-macosx_x64.tar.gz",
"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]
},
{
"id": 11535,
"url": "https://cdn.azul.com/zulu/bin/zulu8.48.0.49-ca-jdk8.0.262-macosx_x64.tar.gz",
"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]
},
{
"id": 12424,
"url": "https://cdn.azul.com/zulu/bin/zulu8.52.0.23-ca-jdk8.0.282-macosx_x64.tar.gz",
"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]
},
{
"id": 10383,
"url": "https://cdn.azul.com/zulu/bin/zulu9.0.0.15-jdk9.0.0-macosx_x64.tar.gz",
"name": "zulu9.0.0.15-jdk9.0.0-macosx_x64.tar.gz",
"zulu_version": [9, 0, 0, 15],
"jdk_version": [9, 0, 0, 0]
},
{
"id": 10413,
"url": "https://cdn.azul.com/zulu/bin/zulu9.0.1.3-jdk9.0.1-macosx_x64.tar.gz",
"name": "zulu9.0.1.3-jdk9.0.1-macosx_x64.tar.gz",
"zulu_version": [9, 0, 1, 3],
"jdk_version": [9, 0, 1, 0]
},
{
"id": 10503,
"url": "https://cdn.azul.com/zulu/bin/zulu10.2+3-jdk10.0.1-macosx_x64.tar.gz",
"name": "zulu10.2+3-jdk10.0.1-macosx_x64.tar.gz",
"zulu_version": [10, 2, 3, 0],
"jdk_version": [10, 0, 1, 9]
},
{
"id": 10541,
"url": "https://cdn.azul.com/zulu/bin/zulu10.3+5-jdk10.0.2-macosx_x64.tar.gz",
"name": "zulu10.3+5-jdk10.0.2-macosx_x64.tar.gz",
"zulu_version": [10, 3, 5, 0],
"jdk_version": [10, 0, 2, 13]
},
{
"id": 10576,
"url": "https://cdn.azul.com/zulu/bin/zulu11.2.3-jdk11.0.1-macosx_x64.tar.gz",
"name": "zulu11.2.3-jdk11.0.1-macosx_x64.tar.gz",
"zulu_version": [11, 2, 3, 0],
"jdk_version": [11, 0, 1, 13]
},
{
"id": 10604,
"url": "https://cdn.azul.com/zulu/bin/zulu11.29.3-ca-jdk11.0.2-macosx_x64.tar.gz",
"name": "zulu11.29.3-ca-jdk11.0.2-macosx_x64.tar.gz",
"zulu_version": [11, 29, 3, 0],
"jdk_version": [11, 0, 2, 7]
},
{
"id": 10687,
"url": "https://cdn.azul.com/zulu/bin/zulu11.31.11-ca-jdk11.0.3-macosx_x64.tar.gz",
"name": "zulu11.31.11-ca-jdk11.0.3-macosx_x64.tar.gz",
"zulu_version": [11, 31, 11, 0],
"jdk_version": [11, 0, 3, 7]
},
{
"id": 10856,
"url": "https://cdn.azul.com/zulu/bin/zulu11.35.13-ca-jdk11.0.5-macosx_x64.tar.gz",
"name": "zulu11.35.13-ca-jdk11.0.5-macosx_x64.tar.gz",
"zulu_version": [11, 35, 13, 0],
"jdk_version": [11, 0, 5, 10]
},
{
"id": 10933,
"url": "https://cdn.azul.com/zulu/bin/zulu11.35.15-ca-jdk11.0.5-macosx_x64.tar.gz",
"name": "zulu11.35.15-ca-jdk11.0.5-macosx_x64.tar.gz",
"zulu_version": [11, 35, 15, 0],
"jdk_version": [11, 0, 5, 10]
},
{
"id": 10933,
"url": "https://cdn.azul.com/zulu/bin/zulu11.35.11-ca-jdk11.0.5-macosx_x64.tar.gz",
"name": "zulu11.35.15-ca-jdk11.0.5-macosx_x64.tar.gz",
"zulu_version": [11, 35, 11, 0],
"jdk_version": [11, 0, 5, 10]
},
{
"id": 12397,
"url": "https://cdn.azul.com/zulu/bin/zulu11.45.27-ca-jdk11.0.10-macosx_x64.tar.gz",
"name": "zulu11.45.27-ca-jdk11.0.10-macosx_x64.tar.gz",
"zulu_version": [11, 45, 27, 0],
"jdk_version": [11, 0, 10, 9]
},
{
"id": 10667,
"url": "https://cdn.azul.com/zulu/bin/zulu12.1.3-ca-jdk12.0.0-macosx_x64.tar.gz",
"name": "zulu12.1.3-ca-jdk12.0.0-macosx_x64.tar.gz",
"zulu_version": [12, 1, 3, 0],
"jdk_version": [12, 0, 0, 33]
},
{
"id": 10710,
"url": "https://cdn.azul.com/zulu/bin/zulu12.2.3-ca-jdk12.0.1-macosx_x64.tar.gz",
"name": "zulu12.2.3-ca-jdk12.0.1-macosx_x64.tar.gz",
"zulu_version": [12, 2, 3, 0],
"jdk_version": [12, 0, 1, 12]
},
{
"id": 10780,
"url": "https://cdn.azul.com/zulu/bin/zulu12.3.11-ca-jdk12.0.2-macosx_x64.tar.gz",
"name": "zulu12.3.11-ca-jdk12.0.2-macosx_x64.tar.gz",
"zulu_version": [12, 3, 11, 0],
"jdk_version": [12, 0, 2, 3]
},
{
"id": 10846,
"url": "https://cdn.azul.com/zulu/bin/zulu13.27.9-ca-jdk13.0.0-macosx_x64.tar.gz",
"name": "zulu13.27.9-ca-jdk13.0.0-macosx_x64.tar.gz",
"zulu_version": [13, 27, 9, 0],
"jdk_version": [13, 0, 0, 33]
},
{
"id": 10888,
"url": "https://cdn.azul.com/zulu/bin/zulu13.28.11-ca-jdk13.0.1-macosx_x64.tar.gz",
"name": "zulu13.28.11-ca-jdk13.0.1-macosx_x64.tar.gz",
"zulu_version": [13, 28, 11, 0],
"jdk_version": [13, 0, 1, 10]
},
{
"id": 11073,
"url": "https://cdn.azul.com/zulu/bin/zulu13.29.9-ca-jdk13.0.2-macosx_x64.tar.gz",
"name": "zulu13.29.9-ca-jdk13.0.2-macosx_x64.tar.gz",
"zulu_version": [13, 29, 9, 0],
"jdk_version": [13, 0, 2, 6]
},
{
"id": 12408,
"url": "https://cdn.azul.com/zulu/bin/zulu13.37.21-ca-jdk13.0.6-macosx_x64.tar.gz",
"name": "zulu13.37.21-ca-jdk13.0.6-macosx_x64.tar.gz",
"zulu_version": [13, 37, 21, 0],
"jdk_version": [13, 0, 6, 5]
},
{
"id": 11236,
"url": "https://cdn.azul.com/zulu/bin/zulu14.27.1-ca-jdk14.0.0-macosx_x64.tar.gz",
"name": "zulu14.27.1-ca-jdk14.0.0-macosx_x64.tar.gz",
"zulu_version": [14, 27, 1, 0],
"jdk_version": [14, 0, 0, 36]
},
{
"id": 11349,
"url": "https://cdn.azul.com/zulu/bin/zulu14.28.21-ca-jdk14.0.1-macosx_x64.tar.gz",
"name": "zulu14.28.21-ca-jdk14.0.1-macosx_x64.tar.gz",
"zulu_version": [14, 28, 21, 0],
"jdk_version": [14, 0, 1, 8]
},
{
"id": 11513,
"url": "https://cdn.azul.com/zulu/bin/zulu14.29.23-ca-jdk14.0.2-macosx_x64.tar.gz",
"name": "zulu14.29.23-ca-jdk14.0.2-macosx_x64.tar.gz",
"zulu_version": [14, 29, 23, 0],
"jdk_version": [14, 0, 2, 12]
},
{
"id": 11780,
"url": "https://cdn.azul.com/zulu/bin/zulu15.27.17-ca-jdk15.0.0-macosx_x64.tar.gz",
"name": "zulu15.27.17-ca-jdk15.0.0-macosx_x64.tar.gz",
"zulu_version": [15, 27, 17, 0],
"jdk_version": [15, 0, 0, 36]
},
{
"id": 11924,
"url": "https://cdn.azul.com/zulu/bin/zulu15.28.13-ca-jdk15.0.1-macosx_x64.tar.gz",
"name": "zulu15.28.13-ca-jdk15.0.1-macosx_x64.tar.gz",
"zulu_version": [15, 28, 13, 0],
"jdk_version": [15, 0, 1, 8]
},
{
"id": 12101,
"url": "https://cdn.azul.com/zulu/bin/zulu15.28.51-ca-jdk15.0.1-macosx_x64.tar.gz",
"name": "zulu15.28.51-ca-jdk15.0.1-macosx_x64.tar.gz",
"zulu_version": [15, 28, 51, 0],
"jdk_version": [15, 0, 1, 9]
},
{
"id": 12445,
"url": "https://cdn.azul.com/zulu/bin/zulu15.29.15-ca-jdk15.0.2-macosx_x64.tar.gz",
"name": "zulu15.29.15-ca-jdk15.0.2-macosx_x64.tar.gz",
"zulu_version": [15, 29, 15, 0],
"jdk_version": [15, 0, 2, 7]
}
]

View File

@ -0,0 +1,154 @@
import { HttpClient } from '@actions/http-client';
import * as semver from 'semver';
import { AdoptDistribution } from '../../src/distributions/adopt/installer';
import { JavaInstallerOptions } from '../../src/distributions/base-models';
let manifestData = require('../data/adopt.json') as [];
describe('getAvailableVersions', () => {
let spyHttpClient: jest.SpyInstance;
beforeEach(() => {
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
spyHttpClient.mockReturnValue({
statusCode: 200,
headers: {},
result: []
});
});
afterEach(() => {
jest.resetAllMocks();
jest.clearAllMocks();
jest.restoreAllMocks();
});
it.each([
[
{ version: '11', architecture: 'x64', packageType: 'jdk', checkLatest: false },
'os=mac&architecture=x64&image_type=jdk&release_type=ga&page_size=20&page=0'
],
[
{ version: '11', architecture: 'x86', packageType: 'jdk', checkLatest: false },
'os=mac&architecture=x86&image_type=jdk&release_type=ga&page_size=20&page=0'
],
[
{ version: '11', architecture: 'x64', packageType: 'jre', checkLatest: false },
'os=mac&architecture=x64&image_type=jre&release_type=ga&page_size=20&page=0'
],
[
{ version: '11-ea', architecture: 'x64', packageType: 'jdk', checkLatest: false },
'os=mac&architecture=x64&image_type=jdk&release_type=ea&page_size=20&page=0'
]
])(
'build correct url for %s',
async (installerOptions: JavaInstallerOptions, expectedParameters) => {
const distribution = new AdoptDistribution(installerOptions);
const baseUrl = 'https://api.adoptopenjdk.net/v3/assets/version/%5B1.0,100.0%5D';
const expectedUrl = `${baseUrl}?project=jdk&vendor=adoptopenjdk&heap_size=normal&jvm_impl=hotspot&sort_method=DEFAULT&sort_order=DESC&${expectedParameters}`;
distribution['getPlatformOption'] = () => 'mac';
await distribution['getAvailableVersions']();
expect(spyHttpClient.mock.calls).toHaveLength(1);
expect(spyHttpClient.mock.calls[0][0]).toBe(expectedUrl);
}
);
it('load available versions', async () => {
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
spyHttpClient
.mockReturnValueOnce({
statusCode: 200,
headers: {},
result: manifestData
})
.mockReturnValueOnce({
statusCode: 200,
headers: {},
result: manifestData
})
.mockReturnValueOnce({
statusCode: 200,
headers: {},
result: []
});
const distribution = new AdoptDistribution({
version: '11',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
const availableVersions = await distribution['getAvailableVersions']();
expect(availableVersions).not.toBeNull();
expect(availableVersions.length).toBe(manifestData.length * 2);
});
});
describe('findPackageForDownload', () => {
it.each([
['9', '9.0.7+10'],
['15', '15.0.2+7'],
['15.0', '15.0.2+7'],
['15.0.2', '15.0.2+7'],
['15.0.1', '15.0.1+9.1'],
['11.x', '11.0.10+9'],
['x', '15.0.2+7'],
['12', '12.0.2+10.3'], // make sure that '12.0.2+10.1', '12.0.2+10.3', '12.0.2+10.2' are sorted correctly
['12.0.2+10.1', '12.0.2+10.1'],
['15.0.1+9', '15.0.1+9'],
['15.0.1+9.1', '15.0.1+9.1']
])('version is resolved correctly %s -> %s', async (input, expected) => {
const distribution = new AdoptDistribution({
version: '11',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
distribution['getAvailableVersions'] = async () => manifestData;
const resolvedVersion = await distribution['findPackageForDownload'](input);
expect(resolvedVersion.version).toBe(expected);
});
it('version is found but binaries list is empty', async () => {
const distribution = new AdoptDistribution({
version: '11',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
distribution['getAvailableVersions'] = async () => manifestData;
await expect(distribution['findPackageForDownload']('9.0.8')).rejects.toThrowError(
/Could not find satisfied version for SemVer */
);
});
it('version is not found', async () => {
const distribution = new AdoptDistribution({
version: '11',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
distribution['getAvailableVersions'] = async () => manifestData;
await expect(distribution['findPackageForDownload']('7.x')).rejects.toThrowError(
/Could not find satisfied version for SemVer */
);
});
it('version list is empty', async () => {
const distribution = new AdoptDistribution({
version: '11',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
distribution['getAvailableVersions'] = async () => [];
await expect(distribution['findPackageForDownload']('11')).rejects.toThrowError(
/Could not find satisfied version for SemVer */
);
});
});

View File

@ -0,0 +1,351 @@
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 {
JavaDownloadRelease,
JavaInstallerOptions,
JavaInstallerResults
} from '../../src/distributions/base-models';
class EmptyJavaBase extends JavaBase {
constructor(installerOptions: JavaInstallerOptions) {
super('Empty', installerOptions);
}
protected async downloadTool(javaRelease: JavaDownloadRelease): Promise<JavaInstallerResults> {
return {
version: '11.0.9',
path: path.join('toolcache', this.toolcacheFolderName, '11.0.9', this.architecture)
};
}
protected async findPackageForDownload(range: string): Promise<JavaDownloadRelease> {
const availableVersion = '11.0.9';
if (!semver.satisfies(availableVersion, range)) {
throw new Error('Available version not found');
}
return {
version: availableVersion,
url: `some/random_url/java/${availableVersion}`
};
}
}
describe('findInToolcache', () => {
const actualJavaVersion = '11.0.8';
const javaPath = path.join('Java_Empty_jdk', actualJavaVersion, 'x64');
let mockJavaBase: EmptyJavaBase;
let spyGetToolcachePath: jest.SpyInstance;
let spyTcFindAllVersions: jest.SpyInstance;
beforeEach(() => {
spyGetToolcachePath = jest.spyOn(util, 'getToolcachePath');
spyTcFindAllVersions = jest.spyOn(tc, 'findAllVersions');
});
afterEach(() => {
jest.resetAllMocks();
jest.clearAllMocks();
jest.restoreAllMocks();
});
it.each([
[
{ version: '11', architecture: 'x64', packageType: 'jdk', checkLatest: false },
{ version: actualJavaVersion, path: javaPath }
],
[
{ version: '11.0', architecture: 'x64', packageType: 'jdk', checkLatest: false },
{ version: actualJavaVersion, path: javaPath }
],
[
{ version: '11.0.8', architecture: 'x64', packageType: 'jdk', checkLatest: false },
{ version: actualJavaVersion, path: javaPath }
],
[
{ version: '11', architecture: 'x64', packageType: 'jdk', checkLatest: true },
{ version: actualJavaVersion, path: javaPath }
],
[
{ version: '11.0', architecture: 'x64', packageType: 'jdk', checkLatest: true },
{ version: actualJavaVersion, path: javaPath }
],
[
{ version: '11.0.8', architecture: 'x64', packageType: 'jdk', checkLatest: true },
{ version: actualJavaVersion, path: javaPath }
],
[{ version: '11', architecture: 'x64', packageType: 'jre', checkLatest: false }, null],
[{ version: '8', architecture: 'x64', packageType: 'jdk', checkLatest: false }, null],
[{ version: '11', architecture: 'x86', packageType: 'jdk', checkLatest: false }, null],
[{ version: '11', architecture: 'x86', packageType: 'jre', checkLatest: false }, null]
])(`should find java for path %s -> %s`, (input, expected) => {
spyTcFindAllVersions.mockReturnValue([actualJavaVersion]);
spyGetToolcachePath.mockImplementation(
(toolname: string, javaVersion: string, architecture: string) => {
const semverVersion = new semver.Range(javaVersion);
if (path.basename(javaPath) !== architecture || !javaPath.includes(toolname)) {
return '';
}
return semver.satisfies(actualJavaVersion, semverVersion) ? javaPath : '';
}
);
mockJavaBase = new EmptyJavaBase(input);
expect(mockJavaBase['findInToolcache']()).toEqual(expected);
});
it.each([
['11', { version: '11.0.3+2', versionInPath: '11.0.3-2' }],
['11.0', { version: '11.0.3+2', versionInPath: '11.0.3-2' }],
['11.0.1', { version: '11.0.1', versionInPath: '11.0.1' }],
['11.0.3', { version: '11.0.3+2', versionInPath: '11.0.3-2' }],
['15', { version: '15.0.2+4', versionInPath: '15.0.2-4' }],
['x', { version: '15.0.2+4', versionInPath: '15.0.2-4' }],
['x-ea', { version: '17.4.4', versionInPath: '17.4.4-ea' }],
['11-ea', { version: '11.3.3+5.2.1231421', versionInPath: '11.3.3-ea.5.2.1231421' }],
['11.2-ea', { version: '11.2.1', versionInPath: '11.2.1-ea' }],
['11.2.1-ea', { version: '11.2.1', versionInPath: '11.2.1-ea' }]
])('should choose correct java from tool-cache for input %s', (input, expected) => {
spyTcFindAllVersions.mockReturnValue([
'17.4.4-ea',
'11.0.2',
'15.0.2-4',
'11.0.3-2',
'11.2.1-ea',
'11.3.2-ea',
'11.3.2-ea.5',
'11.3.3-ea.5.2.1231421',
'12.3.2-0',
'11.0.1'
]);
spyGetToolcachePath.mockImplementation(
(toolname: string, javaVersion: string, architecture: string) =>
`/hostedtoolcache/${toolname}/${javaVersion}/${architecture}`
);
mockJavaBase = new EmptyJavaBase({
version: input,
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});
const foundVersion = mockJavaBase['findInToolcache']();
expect(foundVersion).toEqual({
version: expected.version,
path: `/hostedtoolcache/Java_Empty_jdk/${expected.versionInPath}/x64`
});
});
});
describe('setupJava', () => {
const actualJavaVersion = '11.0.9';
const installedJavaVersion = '11.0.8';
const javaPath = path.join('Java_Empty_jdk', installedJavaVersion, 'x86');
const javaPathInstalled = path.join('toolcache', 'Java_Empty_jdk', actualJavaVersion, 'x86');
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;
beforeEach(() => {
spyGetToolcachePath = jest.spyOn(util, 'getToolcachePath');
spyGetToolcachePath.mockImplementation(
(toolname: string, javaVersion: string, architecture: string) => {
const semverVersion = new semver.Range(javaVersion);
if (path.basename(javaPath) !== architecture || !javaPath.includes(toolname)) {
return '';
}
return semver.satisfies(installedJavaVersion, semverVersion) ? javaPath : '';
}
);
spyTcFindAllVersions = jest.spyOn(tc, 'findAllVersions');
spyTcFindAllVersions.mockReturnValue([installedJavaVersion]);
// Spy on core methods
spyCoreDebug = jest.spyOn(core, 'debug');
spyCoreDebug.mockImplementation(() => undefined);
spyCoreInfo = jest.spyOn(core, 'info');
spyCoreInfo.mockImplementation(() => undefined);
spyCoreAddPath = jest.spyOn(core, 'addPath');
spyCoreAddPath.mockImplementation(() => undefined);
spyCoreExportVariable = jest.spyOn(core, 'exportVariable');
spyCoreExportVariable.mockImplementation(() => undefined);
spyCoreSetOutput = jest.spyOn(core, 'setOutput');
spyCoreSetOutput.mockImplementation(() => undefined);
});
afterEach(() => {
jest.resetAllMocks();
jest.clearAllMocks();
jest.restoreAllMocks();
});
it.each([
[
{ version: '11', architecture: 'x86', packageType: 'jdk', checkLatest: false },
{ version: installedJavaVersion, path: javaPath }
],
[
{ version: '11.0', architecture: 'x86', packageType: 'jdk', checkLatest: false },
{ version: installedJavaVersion, path: javaPath }
],
[
{ version: '11.0.8', architecture: 'x86', packageType: 'jdk', checkLatest: false },
{ version: installedJavaVersion, path: javaPath }
]
])('should find java locally for %s', (input, expected) => {
mockJavaBase = new EmptyJavaBase(input);
expect(mockJavaBase.setupJava()).resolves.toEqual(expected);
expect(spyGetToolcachePath).toHaveBeenCalled();
expect(spyCoreInfo).toHaveBeenCalledWith(`Resolved Java ${expected.version} from tool-cache`);
expect(spyCoreInfo).toHaveBeenCalledWith(`Setting Java ${expected.version} as the default`);
expect(spyCoreInfo).not.toHaveBeenCalledWith(
'Trying to resolve the latest version from remote'
);
expect(spyCoreInfo).not.toHaveBeenCalledWith('Trying to download...');
});
it.each([
[
{ version: '11', architecture: 'x86', packageType: 'jre', checkLatest: false },
{ path: path.join('toolcache', 'Java_Empty_jre', '11.0.9', 'x86'), version: '11.0.9' }
],
[
{ version: '11', architecture: 'x64', packageType: 'jdk', checkLatest: false },
{ path: path.join('toolcache', 'Java_Empty_jdk', '11.0.9', 'x64'), version: '11.0.9' }
],
[
{ version: '11', architecture: 'x64', packageType: 'jre', checkLatest: false },
{ path: path.join('toolcache', 'Java_Empty_jre', '11.0.9', 'x64'), version: '11.0.9' }
]
])('download java with configuration %s', async (input, expected) => {
mockJavaBase = new EmptyJavaBase(input);
await expect(mockJavaBase.setupJava()).resolves.toEqual(expected);
expect(spyGetToolcachePath).toHaveBeenCalled();
expect(spyCoreAddPath).toHaveBeenCalled();
expect(spyCoreExportVariable).toHaveBeenCalled();
expect(spyCoreSetOutput).toHaveBeenCalled();
expect(spyCoreInfo).toHaveBeenCalledWith('Trying to resolve the latest version from remote');
expect(spyCoreInfo).toHaveBeenCalledWith(`Resolved latest version as ${expected.version}`);
expect(spyCoreInfo).toHaveBeenCalledWith('Trying to download...');
expect(spyCoreInfo).toHaveBeenCalledWith(`Java ${expected.version} was downloaded`);
expect(spyCoreInfo).toHaveBeenCalledWith(`Setting Java ${expected.version} as the default`);
});
it.each([
[
{ version: '11.0.9', architecture: 'x86', packageType: 'jdk', checkLatest: true },
{ version: '11.0.9', path: javaPathInstalled }
]
])('should check the latest java version for %s and resolve locally', async (input, expected) => {
mockJavaBase = new EmptyJavaBase(input);
mockJavaBase['findInToolcache'] = () => ({ version: '11.0.9', path: expected.path });
await expect(mockJavaBase.setupJava()).resolves.toEqual(expected);
expect(spyCoreInfo).toHaveBeenCalledWith('Trying to resolve the latest version from remote');
expect(spyCoreInfo).toHaveBeenCalledWith(`Resolved latest version as ${expected.version}`);
expect(spyCoreInfo).toHaveBeenCalledWith(`Resolved Java ${expected.version} from tool-cache`);
expect(spyCoreInfo).toHaveBeenCalledWith(`Setting Java ${expected.version} as the default`);
});
it.each([
[
{ version: '11', architecture: 'x86', packageType: 'jdk', checkLatest: true },
{ version: actualJavaVersion, path: javaPathInstalled }
],
[
{ version: '11.0', architecture: 'x86', packageType: 'jdk', checkLatest: true },
{ version: actualJavaVersion, path: javaPathInstalled }
],
[
{ version: '11.0.x', architecture: 'x86', packageType: 'jdk', checkLatest: true },
{ version: actualJavaVersion, path: javaPathInstalled }
]
])('should check the latest java version for %s and download', async (input, expected) => {
mockJavaBase = new EmptyJavaBase(input);
await expect(mockJavaBase.setupJava()).resolves.toEqual(expected);
expect(spyGetToolcachePath).toHaveBeenCalled();
expect(spyCoreInfo).toHaveBeenCalledWith('Trying to resolve the latest version from remote');
expect(spyCoreInfo).toHaveBeenCalledWith(`Resolved latest version as ${actualJavaVersion}`);
expect(spyCoreInfo).toHaveBeenCalledWith('Trying to download...');
expect(spyCoreInfo).toHaveBeenCalledWith(`Java ${actualJavaVersion} was downloaded`);
expect(spyCoreInfo).toHaveBeenCalledWith(`Setting Java ${expected.version} as the default`);
});
it.each([
[{ version: '15', architecture: 'x86', packageType: 'jre', checkLatest: false }],
[{ version: '11.0.7', architecture: 'x64', packageType: 'jre', checkLatest: false }]
])('should throw an error for Available version not found for %s', async input => {
mockJavaBase = new EmptyJavaBase(input);
await expect(mockJavaBase.setupJava()).rejects.toThrowError('Available version not found');
expect(spyTcFindAllVersions).toHaveBeenCalled();
expect(spyCoreAddPath).not.toHaveBeenCalled();
expect(spyCoreExportVariable).not.toHaveBeenCalled();
expect(spyCoreSetOutput).not.toHaveBeenCalled();
});
});
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 }]
])('normalizeVersion from %s to %s', (input, expected) => {
expect(DummyJavaBase.prototype.normalizeVersion.call(null, input)).toEqual(expected);
});
it('normalizeVersion should throw an error for non semver', () => {
const version = '11g';
expect(DummyJavaBase.prototype.normalizeVersion.bind(null, version)).toThrowError(
`The string '${version}' is not valid SemVer notation for a Java version. Please check README file for code snippets and more detailed information`
);
});
});
describe('getToolcacheVersionName', () => {
const DummyJavaBase = JavaBase as any;
it.each([
[{ version: '11', stable: true }, '11'],
[{ version: '11.0.2', stable: true }, '11.0.2'],
[{ version: '11.0.2+4', stable: true }, '11.0.2-4'],
[{ version: '11.0.2+4.1.2563234', stable: true }, '11.0.2-4.1.2563234'],
[{ version: '11.0', stable: false }, '11.0-ea'],
[{ version: '11.0.3', stable: false }, '11.0.3-ea'],
[{ version: '11.0.3+4', stable: false }, '11.0.3-ea.4'],
[{ version: '11.0.3+4.2.256', stable: false }, '11.0.3-ea.4.2.256']
])('returns correct version name for %s', (input, expected) => {
const inputVersion = input.stable ? '11' : '11-ea';
const mockJavaBase = new EmptyJavaBase({
version: inputVersion,
packageType: 'jdk',
architecture: 'x64',
checkLatest: false
});
const actual = mockJavaBase['getToolcacheVersionName'](input.version);
expect(actual).toBe(expected);
});
});

View File

@ -0,0 +1,235 @@
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';
describe('setupJava', () => {
const actualJavaVersion = '11.1.10';
const javaPath = path.join('Java_jdkfile_jdk', actualJavaVersion, 'x86');
let mockJavaBase: 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 expectedJdkFile = 'JavaLocalJdkFile';
beforeEach(() => {
spyGetToolcachePath = jest.spyOn(util, 'getToolcachePath');
spyGetToolcachePath.mockImplementation(
(toolname: string, javaVersion: string, architecture: string) => {
const semverVersion = new semver.Range(javaVersion);
if (path.basename(javaPath) !== architecture || !javaPath.includes(toolname)) {
return '';
}
return semver.satisfies(actualJavaVersion, semverVersion) ? javaPath : '';
}
);
spyTcCacheDir = jest.spyOn(tc, 'cacheDir');
spyTcCacheDir.mockImplementation(
(archivePath: string, toolcacheFolderName: string, version: string, architecture: string) =>
path.join(toolcacheFolderName, version, architecture)
);
spyTcFindAllVersions = jest.spyOn(tc, 'findAllVersions');
spyTcFindAllVersions.mockReturnValue([actualJavaVersion]);
// Spy on core methods
spyCoreDebug = jest.spyOn(core, 'debug');
spyCoreDebug.mockImplementation(() => undefined);
spyCoreInfo = jest.spyOn(core, 'info');
spyCoreInfo.mockImplementation(() => undefined);
spyCoreAddPath = jest.spyOn(core, 'addPath');
spyCoreAddPath.mockImplementation(() => undefined);
spyCoreExportVariable = jest.spyOn(core, 'exportVariable');
spyCoreExportVariable.mockImplementation(() => undefined);
spyCoreSetOutput = jest.spyOn(core, 'setOutput');
spyCoreSetOutput.mockImplementation(() => undefined);
// Spy on fs methods
spyFsReadDir = jest.spyOn(fs, 'readdirSync');
spyFsReadDir.mockImplementation(() => ['JavaTest']);
spyFsStat = jest.spyOn(fs, 'statSync');
spyFsStat.mockImplementation((file: string) => {
return { isFile: () => file === expectedJdkFile };
});
// Spy on util methods
spyUtilsExtractJdkFile = jest.spyOn(util, 'extractJdkFile');
spyUtilsExtractJdkFile.mockImplementation(() => 'some/random/path/');
// Spy on path methods
spyPathResolve = jest.spyOn(path, 'resolve');
spyPathResolve.mockImplementation((path: string) => path);
});
afterEach(() => {
jest.resetAllMocks();
jest.clearAllMocks();
jest.restoreAllMocks();
});
it('java is resolved from toolcache, jdkfile is untouched', async () => {
const inputs = {
version: actualJavaVersion,
architecture: 'x86',
packageType: 'jdk',
checkLatest: false
};
const jdkFile = 'not_existing_one';
const expected = {
version: actualJavaVersion,
path: path.join('Java_jdkfile_jdk', inputs.version, inputs.architecture)
};
mockJavaBase = new LocalDistribution(inputs, jdkFile);
await expect(mockJavaBase.setupJava()).resolves.toEqual(expected);
expect(spyGetToolcachePath).toHaveBeenCalled();
expect(spyCoreInfo).toHaveBeenCalledWith(`Resolved Java ${actualJavaVersion} from tool-cache`);
expect(spyCoreInfo).not.toHaveBeenCalledWith(
`Java ${inputs.version} was not found in tool-cache. Trying to unpack JDK file...`
);
});
it("java is resolved from toolcache, jdkfile doesn't exist", async () => {
const inputs = {
version: actualJavaVersion,
architecture: 'x86',
packageType: 'jdk',
checkLatest: false
};
const jdkFile = undefined;
const expected = {
version: actualJavaVersion,
path: path.join('Java_jdkfile_jdk', inputs.version, inputs.architecture)
};
mockJavaBase = new LocalDistribution(inputs, jdkFile);
await expect(mockJavaBase.setupJava()).resolves.toEqual(expected);
expect(spyGetToolcachePath).toHaveBeenCalled();
expect(spyCoreInfo).toHaveBeenCalledWith(`Resolved Java ${actualJavaVersion} from tool-cache`);
expect(spyCoreInfo).not.toHaveBeenCalledWith(
`Java ${inputs.version} was not found in tool-cache. Trying to unpack JDK file...`
);
});
it('java is unpacked from jdkfile', async () => {
const inputs = {
version: '11.0.289',
architecture: 'x86',
packageType: 'jdk',
checkLatest: false
};
const jdkFile = expectedJdkFile;
const expected = {
version: '11.0.289',
path: path.join('Java_jdkfile_jdk', inputs.version, inputs.architecture)
};
mockJavaBase = new LocalDistribution(inputs, jdkFile);
await expect(mockJavaBase.setupJava()).resolves.toEqual(expected);
expect(spyTcFindAllVersions).toHaveBeenCalled();
expect(spyCoreInfo).not.toHaveBeenCalledWith(
`Resolved Java ${actualJavaVersion} from tool-cache`
);
expect(spyCoreInfo).toHaveBeenCalledWith(`Extracting Java from '${jdkFile}'`);
expect(spyCoreInfo).toHaveBeenCalledWith(
`Java ${inputs.version} was not found in tool-cache. Trying to unpack JDK file...`
);
});
it('jdk file is not found', async () => {
const inputs = {
version: '11.0.289',
architecture: 'x86',
packageType: 'jdk',
checkLatest: false
};
const jdkFile = 'not_existing_one';
const expected = {
javaVersion: '11.0.289',
javaPath: path.join('Java_jdkfile_jdk', inputs.version, inputs.architecture)
};
mockJavaBase = new LocalDistribution(inputs, jdkFile);
expected.javaPath = path.join('Java_jdkfile_jdk', inputs.version, inputs.architecture);
await expect(mockJavaBase.setupJava()).rejects.toThrowError(
"JDK file was not found in path 'not_existing_one'"
);
expect(spyTcFindAllVersions).toHaveBeenCalled();
expect(spyCoreInfo).not.toHaveBeenCalledWith(
`Resolved Java ${actualJavaVersion} from tool-cache`
);
expect(spyCoreInfo).not.toHaveBeenCalledWith(`Extracting Java from '${jdkFile}'`);
expect(spyCoreInfo).toHaveBeenCalledWith(
`Java ${inputs.version} was not found in tool-cache. Trying to unpack JDK file...`
);
});
it.each([
[
{ version: '8.0.289', architecture: 'x64', packageType: 'jdk', checkLatest: false },
'otherJdkFile'
],
[
{ version: '11.0.289', architecture: 'x64', packageType: 'jdk', checkLatest: false },
'otherJdkFile'
],
[
{ version: '12.0.289', architecture: 'x64', packageType: 'jdk', checkLatest: false },
'otherJdkFile'
],
[
{ version: '11.1.11', architecture: 'x64', packageType: 'jdk', checkLatest: false },
'not_existing_one'
]
])(
`Throw an error if jdkfile has wrong path, inputs %s, jdkfile %s, real name ${expectedJdkFile}`,
async (inputs, jdkFile) => {
mockJavaBase = new LocalDistribution(inputs, jdkFile);
await expect(mockJavaBase.setupJava()).rejects.toThrowError(
/JDK file was not found in path */
);
expect(spyTcFindAllVersions).toHaveBeenCalled();
}
);
it.each([
[{ version: '8.0.289', architecture: 'x64', packageType: 'jdk', checkLatest: false }, ''],
[
{ version: '7.0.289', architecture: 'x64', packageType: 'jdk', checkLatest: false },
undefined
],
[
{ version: '11.0.289', architecture: 'x64', packageType: 'jdk', checkLatest: false },
undefined
]
])('Throw an error if jdkfile is not specified, inputs %s', async (inputs, jdkFile) => {
mockJavaBase = new LocalDistribution(inputs, jdkFile);
await expect(mockJavaBase.setupJava()).rejects.toThrowError("'jdkFile' is not specified");
expect(spyTcFindAllVersions).toHaveBeenCalled();
});
});

View File

@ -0,0 +1,165 @@
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';
const manifestData = require('../data/zulu-releases-default.json') as [];
describe('getAvailableVersions', () => {
let spyHttpClient: jest.SpyInstance;
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
beforeEach(() => {
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
spyHttpClient.mockReturnValue({
statusCode: 200,
headers: {},
result: manifestData as IZuluVersions[]
});
spyUtilGetDownloadArchiveExtension = jest.spyOn(utils, 'getDownloadArchiveExtension');
spyUtilGetDownloadArchiveExtension.mockReturnValue('tar.gz');
});
afterEach(() => {
jest.resetAllMocks();
jest.clearAllMocks();
jest.restoreAllMocks();
});
it.each([
[
{ version: '11', architecture: 'x86', packageType: 'jdk', checkLatest: false },
'?os=macos&ext=tar.gz&bundle_type=jdk&javafx=false&arch=x86&hw_bitness=32&release_status=ga'
],
[
{ version: '11-ea', architecture: 'x86', packageType: 'jdk', checkLatest: false },
'?os=macos&ext=tar.gz&bundle_type=jdk&javafx=false&arch=x86&hw_bitness=32&release_status=ea'
],
[
{ version: '8', architecture: 'x64', packageType: 'jdk', checkLatest: false },
'?os=macos&ext=tar.gz&bundle_type=jdk&javafx=false&arch=x86&hw_bitness=64&release_status=ga'
],
[
{ version: '8', architecture: 'x64', packageType: 'jre', checkLatest: false },
'?os=macos&ext=tar.gz&bundle_type=jre&javafx=false&arch=x86&hw_bitness=64&release_status=ga'
],
[
{ version: '8', architecture: 'x64', 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'
],
[
{ version: '8', architecture: 'x64', 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'
]
])('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}`;
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 ZuluDistribution({
version: '11',
architecture: 'x86',
packageType: 'jdk',
checkLatest: false
});
const availableVersions = await distribution['getAvailableVersions']();
expect(availableVersions).toHaveLength(manifestData.length);
});
});
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: '' }]
])('%s -> %s', (input, expected) => {
const distribution = new ZuluDistribution({
version: '11',
architecture: input.architecture,
packageType: 'jdk',
checkLatest: false
});
expect(distribution['getArchitectureOptions']()).toEqual(expected);
});
});
describe('findPackageForDownload', () => {
it.each([
['8', '8.0.282+8'],
['11.x', '11.0.10+9'],
['8.0', '8.0.282+8'],
['11.0.x', '11.0.10+9'],
['15', '15.0.2+7'],
['9.0.0', '9.0.0+0'],
['9.0', '9.0.1+0'],
['8.0.262', '8.0.262+19'], // validate correct choise between [8.0.262.17, 8.0.262.19, 8.0.262.18]
['8.0.262+17', '8.0.262+17'],
['15.0.1+8', '15.0.1+8'],
['15.0.1+9', '15.0.1+9']
])('version is %s -> %s', async (input, expected) => {
const distribution = new ZuluDistribution({
version: input,
architecture: 'x86',
packageType: 'jdk',
checkLatest: false
});
distribution['getAvailableVersions'] = async () => manifestData;
const result = await distribution['findPackageForDownload'](distribution['version']);
expect(result.version).toBe(expected);
});
it('select correct bundle if there are multiple items with the same jdk version but different zulu versions', async () => {
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.url).toBe(
'https://cdn.azul.com/zulu/bin/zulu11.35.15-ca-jdk11.0.5-macosx_x64.tar.gz'
);
});
it('should throw an error', async () => {
const distribution = new ZuluDistribution({
version: '18',
architecture: 'x86',
packageType: 'jdk',
checkLatest: false
});
await expect(
distribution['findPackageForDownload'](distribution['version'])
).rejects.toThrowError(/Could not find satisfied version for semver */);
});
});
describe('convertVersionToSemver', () => {
it.each([
[[12], '12'],
[[12, 0], '12.0'],
[[12, 0, 2], '12.0.2'],
[[12, 0, 2, 1], '12.0.2+1'],
[[12, 0, 2, 1, 3], '12.0.2+1']
])('%s -> %s', (input: number[], expected: string) => {
const distribution = new ZuluDistribution({
version: '18',
architecture: 'x86',
packageType: 'jdk',
checkLatest: false
});
const actual = distribution['convertVersionToSemver'](input);
expect(actual).toBe(expected);
});
});

48
__tests__/gpg.test.ts Normal file
View File

@ -0,0 +1,48 @@
import path = require('path');
import io = require('@actions/io');
import exec = require('@actions/exec');
jest.mock('@actions/exec', () => {
return {
exec: jest.fn()
};
});
const tempDir = path.join(__dirname, 'runner', 'temp');
process.env['RUNNER_TEMP'] = tempDir;
import gpg = require('../src/gpg');
describe('gpg tests', () => {
beforeEach(async () => {
await io.mkdirP(tempDir);
});
afterAll(async () => {
try {
await io.rmRF(tempDir);
} catch {
console.log('Failed to remove test directories');
}
});
describe('importKey', () => {
it('attempts to import private key and returns null key id on failure', async () => {
const privateKey = 'KEY CONTENTS';
const keyId = await gpg.importKey(privateKey);
expect(keyId).toBeNull();
expect(exec.exec).toHaveBeenCalledWith('gpg', expect.anything(), expect.anything());
});
});
describe('deleteKey', () => {
it('deletes private key', async () => {
const keyId = 'asdfhjkl';
await gpg.deleteKey(keyId);
expect(exec.exec).toHaveBeenCalledWith('gpg', expect.anything(), expect.anything());
});
});
});

View File

@ -1,159 +0,0 @@
import io = require('@actions/io');
import fs = require('fs');
import path = require('path');
import child_process = require('child_process');
const toolDir = path.join(__dirname, 'runner', 'tools');
const tempDir = path.join(__dirname, 'runner', 'temp');
const javaDir = path.join(__dirname, 'runner', 'java');
process.env['RUNNER_TOOL_CACHE'] = toolDir;
process.env['RUNNER_TEMP'] = tempDir;
import * as installer from '../src/installer';
let javaFilePath = '';
let javaUrl = '';
if (process.platform === 'win32') {
javaFilePath = path.join(javaDir, 'java_win.zip');
javaUrl =
'https://download.java.net/java/GA/jdk12/33/GPL/openjdk-12_windows-x64_bin.zip';
} else if (process.platform === 'darwin') {
javaFilePath = path.join(javaDir, 'java_mac.tar.gz');
javaUrl =
'https://download.java.net/java/GA/jdk12/33/GPL/openjdk-12_osx-x64_bin.tar.gz';
} else {
javaFilePath = path.join(javaDir, 'java_linux.tar.gz');
javaUrl =
'https://download.java.net/java/GA/jdk12/33/GPL/openjdk-12_linux-x64_bin.tar.gz';
}
describe('installer tests', () => {
beforeAll(async () => {
await io.rmRF(toolDir);
await io.rmRF(tempDir);
if (!fs.existsSync(`${javaFilePath}.complete`)) {
// Download java
await io.mkdirP(javaDir);
console.log('Downloading java');
child_process.execSync(`curl "${javaUrl}" > "${javaFilePath}"`);
// Write complete file so we know it was successful
fs.writeFileSync(`${javaFilePath}.complete`, 'content');
}
}, 300000);
afterAll(async () => {
try {
await io.rmRF(toolDir);
await io.rmRF(tempDir);
} catch {
console.log('Failed to remove test directories');
}
}, 100000);
it('Installs version of Java from jdkFile if no matching version is installed', async () => {
await installer.getJava('12', 'x64', javaFilePath, 'jdk');
const JavaDir = path.join(toolDir, 'jdk', '12.0.0', 'x64');
expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true);
expect(fs.existsSync(path.join(JavaDir, 'bin'))).toBe(true);
}, 100000);
it('Throws if invalid directory to jdk', async () => {
let thrown = false;
try {
await installer.getJava('1000', 'x64', 'bad path', 'jdk');
} catch {
thrown = true;
}
expect(thrown).toBe(true);
});
it('Downloads java if no file given', async () => {
await installer.getJava('8.0.102', 'x64', '', 'jdk');
const JavaDir = path.join(toolDir, 'jdk', '8.0.102', 'x64');
expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true);
expect(fs.existsSync(path.join(JavaDir, 'bin'))).toBe(true);
}, 100000);
it('Downloads java with 1.x syntax', async () => {
await installer.getJava('1.10', 'x64', '', 'jdk');
const JavaDir = path.join(toolDir, 'jdk', '10.0.2', 'x64');
expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true);
expect(fs.existsSync(path.join(JavaDir, 'bin'))).toBe(true);
}, 100000);
it('Downloads java with normal semver syntax', async () => {
await installer.getJava('9.0.x', 'x64', '', 'jdk');
const JavaDir = path.join(toolDir, 'jdk', '9.0.7', 'x64');
expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true);
expect(fs.existsSync(path.join(JavaDir, 'bin'))).toBe(true);
}, 100000);
it('Downloads java if package is jre', async () => {
await installer.getJava('8.0.222', 'x64', '', 'jre');
const JavaDir = path.join(toolDir, 'jre', '8.0.222', 'x64');
expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true);
expect(fs.existsSync(path.join(JavaDir, 'bin'))).toBe(true);
}, 100000);
it('Downloads java if package is jdk+fx', async () => {
await installer.getJava('8.0.222', 'x64', '', 'jdk+fx');
const JavaDir = path.join(toolDir, 'jdk+fx', '8.0.222', 'x64');
expect(fs.existsSync(`${JavaDir}.complete`)).toBe(true);
expect(fs.existsSync(path.join(JavaDir, 'bin'))).toBe(true);
}, 100000);
it('Throws if invalid java package is specified', async () => {
let thrown = false;
try {
await installer.getJava('8.0.222', 'x64', '', 'bad jdk');
} catch {
thrown = true;
}
expect(thrown).toBe(true);
});
it('Throws if invalid directory to jdk', async () => {
let thrown = false;
try {
await installer.getJava('1000', 'x64', 'bad path', 'jdk');
} catch {
thrown = true;
}
expect(thrown).toBe(true);
});
it('Uses version of Java installed in cache', async () => {
const JavaDir: string = path.join(toolDir, 'jdk', '250.0.0', 'x64');
await io.mkdirP(JavaDir);
fs.writeFileSync(`${JavaDir}.complete`, 'hello');
// This will throw if it doesn't find it in the cache (because no such version exists)
await installer.getJava(
'250',
'x64',
'path shouldnt matter, found in cache',
'jdk'
);
return;
});
it('Doesnt use version of Java that was only partially installed in cache', async () => {
const JavaDir: string = path.join(toolDir, 'jdk', '251.0.0', 'x64');
await io.mkdirP(JavaDir);
let thrown = false;
try {
// This will throw if it doesn't find it in the cache (because no such version exists)
await installer.getJava('251', 'x64', 'bad path', 'jdk');
} catch {
thrown = true;
}
expect(thrown).toBe(true);
return;
});
});

22
__tests__/util.test.ts Normal file
View File

@ -0,0 +1,22 @@
import { isVersionSatisfies } from '../src/util';
describe('isVersionSatisfies', () => {
it.each([
['x', '11.0.0', true],
['3', '3.7.1', true],
['3', '3.7.2', true],
['3', '3.7.2+4', true],
['2.5', '2.5.0', true],
['2.5', '2.5.0+1', true],
['2.5', '2.6.1', false],
['2.5.1', '2.5.0', false],
['2.5.1+3', '2.5.0', false],
['2.5.1+3', '2.5.1+3', true],
['2.5.1+3', '2.5.1+2', false],
['15.0.0+14', '15.0.0+14.1.202003190635', false],
['15.0.0+14.1.202003190635', '15.0.0+14.1.202003190635', true]
])('%s, %s -> %s', (inputRange: string, inputVersion: string, expected: boolean) => {
const actual = isVersionSatisfies(inputRange, inputVersion);
expect(actual).toBe(expected);
});
});

39
__tests__/verify-java.sh Executable file
View File

@ -0,0 +1,39 @@
#!/bin/sh
if [ -z "$1" ]; then
echo "::error::Must supply java version argument"
exit 1
fi
if [ -z "$2" ]; then
echo "::error::Must supply java path argument"
exit 1
fi
EXPECTED_JAVA_VERSION=$1
EXPECTED_PATH=$2
EXPECTED_JAVA_VERSION=$(echo $EXPECTED_JAVA_VERSION | cut -d'+' -f1)
if [[ $EXPECTED_JAVA_VERSION == 8 ]] || [[ $EXPECTED_JAVA_VERSION == 8.* ]]; then
EXPECTED_JAVA_VERSION="1.${EXPECTED_JAVA_VERSION}"
fi
if [[ $EXPECTED_JAVA_VERSION == *-ea* ]]; then
EXPECTED_JAVA_VERSION=$(echo $EXPECTED_JAVA_VERSION | cut -d'-' -f1 | cut -d'.' -f1)
fi
ACTUAL_JAVA_VERSION="$(java -version 2>&1)"
echo "Found java version: $ACTUAL_JAVA_VERSION"
GREP_RESULT=$(echo $ACTUAL_JAVA_VERSION | grep "^openjdk version \"$EXPECTED_JAVA_VERSION")
if [ -z "$GREP_RESULT" ]; then
echo "::error::Unexpected version"
echo "Expected version: $EXPECTED_JAVA_VERSION"
exit 1
fi
if [ "$EXPECTED_PATH" != "$JAVA_HOME" ]; then
echo "::error::Unexpected path"
echo "Actual path: $JAVA_HOME"
echo "Expected path: $EXPECTED_PATH"
exit 1
fi

View File

@ -0,0 +1,17 @@
#!/bin/bash
if [[ "$(git status --porcelain)" != "" ]]; then
echo ----------------------------------------
echo git status
echo ----------------------------------------
git status
echo ----------------------------------------
echo git diff
echo ----------------------------------------
git diff
echo ----------------------------------------
echo Troubleshooting
echo ----------------------------------------
echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && npm ci && npm run pre-checkin"
exit 1
fi

View File

@ -4,36 +4,63 @@ description: 'Set up a specific version of the Java JDK and add the
author: 'GitHub'
inputs:
java-version:
description: 'The Java version to make available on the path. Takes a whole
or semver Java version, or 1.x syntax (e.g. 1.8 => Java 8.x)'
description: 'The Java version to set up. Takes a whole or semver Java version. See examples of supported syntax in README file'
required: true
distribution:
description: 'Java distribution. See the list of supported distributions in README file'
required: true
java-package:
description: 'The package type (jre, jdk, jdk+fx)'
description: 'The package type (jdk, jre, jdk+fx, jre+fx)'
required: false
default: 'jdk'
architecture:
description: 'The architecture (x86, x64) of the package.'
description: 'The architecture of the package'
required: false
default: 'x64'
jdkFile:
description: 'Path to where the compressed JDK is located. The path could
be in your source repository or a local path on the agent.'
description: 'Path to where the compressed JDK is located'
required: false
check-latest:
description: 'Set this option if you want the action to check for the latest available version that satisfies the version spec'
required: false
default: false
server-id:
description: 'ID of the distributionManagement repository in the pom.xml
file. Default is `github`'
required: false
default: 'github'
server-username:
description: 'Environment variable name for the username for authentication
to the Apache Maven repository. Default is $GITHUB_ACTOR'
required: false
default: 'GITHUB_ACTOR'
server-password:
description: 'Environment variable name for password or token for
authentication to the Apache Maven repository. Default is $GITHUB_TOKEN'
required: false
default: 'GITHUB_TOKEN'
settings-path:
description: 'Path to where the settings.xml file will be written. Default is ~/.m2.'
required: false
overwrite-settings:
description: 'Overwrite the settings.xml file if it exists. Default is "true".'
required: false
default: true
gpg-private-key:
description: 'GPG private key to import. Default is empty string.'
required: false
gpg-passphrase:
description: 'Environment variable name for the GPG private key passphrase. Default is
$GPG_PASSPHRASE.'
required: false
outputs:
distribution:
description: 'Distribution of Java that has been installed'
version:
description: 'Actual version of the java environment that has been installed'
path:
description: 'Path to where the java environment has been installed (same as $JAVA_HOME)'
runs:
using: 'node12'
main: 'dist/index.js'
main: 'dist/setup/index.js'
post: 'dist/cleanup/index.js'

8338
dist/cleanup/index.js vendored Normal file

File diff suppressed because it is too large Load Diff

BIN
dist/index.js generated vendored

Binary file not shown.

44703
dist/setup/index.js vendored Normal file

File diff suppressed because it is too large Load Diff

BIN
dist/unzip vendored

Binary file not shown.

View File

@ -0,0 +1,65 @@
# 0. V2 setup-java
Date: 2020-08-24
Status: Proposed
# Context
- The `v1` version of `setup-java` downloads and installs Zulu builds of OpenJDK. There is a huge ask from customers to offer AdoptOpenJDK/Adoptium builds of OpenJDK: https://github.com/actions/setup-java/issues/13
- Zulu and AdoptOpenJDK aren't the only distributions of Java though. Other providers include Oracle OpenJDK or Amazon Corretto and ideally it would be nice to support downloading Java from all providers.
- GitHub Actions virtual environments install and default to AdoptOpenJDK builds of OpenJDK. `setup-java` should give users an option to download and use other distributions that may not be be installed
# Decision
## New input
A new required input parameter (titled `distribution`) will be added to `setup-java` that will allow users to specify the distribution that they would like to download
```yaml
with:
java-version: '11'
distribution: adoptium
```
## Default Behavior
There will be no default distribution that we pick for the user. Users will have to specify a distribution in their YAML or else the action will fail.
Requiring a default version will break users that are pinned to `@main` as they will have no `distribution` specified in their YAML. Telemetry indicates that only a small percentage of users would be effected though. Users pinned to `v1` will be uneffected. This change is meant to not be backward compatible and it is acceptable to change the default behavior because a new major version will be released alongside these changes.
## Extensibility & Documentation
`setup-java` should be structured in such a way that will allow the open source community to easily add support for extra distributions.
Existing code will be restructured so that distribution specific code will be easily separated. Currently the core download logic is in a single file, `installer.ts`. This file will be split up and abstracted out so that there will be no vendor specified logic. Each distribution will have it's own files under `src/distributions` that will contain the core setup logic for a specific distribution.
```yaml
∟ src/
installer.ts # core installer logic
distributions/
∟ adoptium/ # adoptium (formerly AdoptOpenJDK) specific logic
∟ zulu/ # zulu specific logic
# future distributions will be added here
```
The contribution doc (`CONTRIBUTING.md`) will describe how a new distribution should be added and how everything should be structured.
## v2-preview
There will be a `v2-preview` branch that will be created for development and testing. Any changes will first be merged into `v2-preview` branch. After a period of testing & verification, the `v2-preview` branch will be merged into the `main` branch and a `v2` tag will be created. Any [GitHub public documentation](https://docs.github.com/en/actions/language-and-framework-guides/github-actions-for-java) and [starter workflows](https://github.com/actions/starter-workflows) that mention `setup-java` will then be updated to use `v2` instead of `v1`.
## Goals & Anti-Goals
The main focus of the `v2` version of `setup-java` will be to add support for adoptium builds of openJDK in addition to Zulu builds of openJDK. In addition, extensibility will be a priority so that other distributions can be added in the future.
The `setup-java` action has some logic that creates a `settings.xml` file so that it is easier to publish packages. Any improvements or modifications to this logic or anything Gradle/Maven specific will be avoided during the development of the `v2-preview`.
# Consequences
- Users will have more flexibility and the freedom to choose a specific distribution that they would like (AdoptOpenJDK builds of OpenJDK in addition or Zulu builds of OpenJDK)
- `setup-java` will be structured in such a way that will allow for more distributions to be easily added in the future
- A large subset of users pin to `@main` or `@master` instead of to a specific version (`v1`). By introducing a breaking change that now requires a distribution to be specified, many users will have their workflows fail until they go and update their yaml
- Higher maintenance and support burden moving forward

19
docs/adrs/README.md Normal file
View File

@ -0,0 +1,19 @@
# ADRs
ADR, short for "Architecture Decision Record" is a way of capturing important architectural decisions, along with their context and consequences.
This folder includes ADRs for the setup-java action. ADRs are proposed in the form of a pull request, and they commonly follow this format:
* **Title**: short present tense imperative phrase, less than 50 characters, like a git commit message.
* **Status**: proposed, accepted, rejected, deprecated, superseded, etc.
* **Context**: what is the issue that we're seeing that is motivating this decision or change.
* **Decision**: what is the change that we're actually proposing or doing.
* **Consequences**: what becomes easier or more difficult to do because of this change.
---
- More information about ADRs can be found [here](https://github.com/joelparkerhenderson/architecture_decision_record).

301
docs/advanced-usage.md Normal file
View File

@ -0,0 +1,301 @@
# Usage
- [Selecting a Java distribution](#Selecting-a-Java-distribution)
- [Adopt](#Adopt)
- [Zulu](#Zulu)
- [Installing custom Java package type](#Installing-custom-Java-package-type)
- [Installing custom Java architecture](#Installing-custom-Java-architecture)
- [Installing custom Java distribution from local file](#Installing-Java-from-local-file)
- [Testing against different Java distributions](#Testing-against-different-Java-distributions)
- [Testing against different platforms](#Testing-against-different-platforms)
- [Publishing using Apache Maven](#Publishing-using-Apache-Maven)
- [Publishing using Gradle](#Publishing-using-Gradle)
- [Hosted Tool Cache](#Hosted-Tool-Cache)
See [action.yml](../action.yml) for more details on task inputs.
## Selecting a Java distribution
Inputs `java-version` and `distribution` are mandatory and needs to be provided. See [Supported distributions](../README.md#Supported-distributions) for a list of available options.
### Adopt
```yaml
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '11'
- run: java -cp java HelloWorldApp
```
### Zulu
```yaml
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: '11'
java-package: jdk # optional (jdk, jre, jdk+fx or jre+fx) - defaults to jdk
- run: java -cp java HelloWorldApp
```
## Installing custom Java package type
```yaml
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: '<distribution>'
java-version: '11'
java-package: jdk # optional (jdk or jre) - defaults to jdk
- run: java -cp java HelloWorldApp
```
## Installing custom Java architecture
```yaml
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: '<distribution>'
java-version: '11'
architecture: x86 # optional - defaults to x64
- run: java -cp java HelloWorldApp
```
## Installing Java from local file
If your use-case requires a custom distribution or a version that is not provided by setup-java, you can download it manually and setup-java will take care of the installation and caching on the VM:
```yaml
steps:
- run: |
download_url="https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.10%2B9/OpenJDK11U-jdk_x64_linux_hotspot_11.0.10_9.tar.gz"
wget -O $RUNNER_TEMP/java_package.tar.gz $download_url
- uses: actions/setup-java@v2
with:
distribution: 'jdkFile'
jdkFile: ${{ runner.temp }}/java_package.tar.gz
java-version: '11.0.0'
architecture: x64
- run: java -cp java HelloWorldApp
```
## Testing against different Java distributions
**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.
```yaml
jobs:
build:
runs-on: ubuntu-20.04
strategy:
matrix:
distribution: [ 'zulu', 'adopt' ]
java: [ '8', '11', '13', '15' ]
name: Java ${{ matrix.Java }} (${{ matrix.distribution }}) sample
steps:
- uses: actions/checkout@v2
- name: Setup java
uses: actions/setup-java@v2
with:
distribution: ${{ matrix.distribution }}
java-version: ${{ matrix.java }}
- run: java -cp java HelloWorldApp
```
#### Testing against different platforms
```yaml
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
java: [ '8', '11' ]
os: [ 'ubuntu-latest', 'macos-latest', 'windows-latest' ]
name: Java ${{ matrix.Java }} (${{ matrix.os }}) sample
steps:
- uses: actions/checkout@v2
- name: Setup java
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: ${{ matrix.java }}
- run: java -cp java HelloWorldApp
```
## Publishing using Apache Maven
### Yaml example:
```yaml
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
distribution: '<distribution>'
java-version: '11'
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Publish to GitHub Packages Apache Maven
run: mvn deploy
env:
GITHUB_TOKEN: ${{ github.token }} # GITHUB_TOKEN is the default env for the password
- name: Set up Apache Maven Central
uses: actions/setup-java@v2
with: # running setup-java again overwrites the settings.xml
distribution: 'adopt'
java-version: '11'
server-id: maven # Value of the distributionManagement/repository/id field of the pom.xml
server-username: MAVEN_USERNAME # env variable for username in deploy
server-password: MAVEN_CENTRAL_TOKEN # env variable for token in deploy
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
- name: Publish to Apache Maven Central
run: mvn deploy
env:
MAVEN_USERNAME: maven_username123
MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
```
The two `settings.xml` files created from the above example look like the following.
`settings.xml` file created for the first deploy to GitHub Packages
```xml
<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">
<servers>
<server>
<id>github</id>
<username>${env.GITHUB_ACTOR}</username>
<password>${env.GITHUB_TOKEN}</password>
</server>
<server>
<id>gpg.passphrase</id>
<passphrase>${env.GPG_PASSPHRASE}</passphrase>
</server>
</servers>
</settings>
```
`settings.xml` file created for the second deploy to Apache Maven Central
```xml
<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">
<servers>
<server>
<id>maven</id>
<username>${env.MAVEN_USERNAME}</username>
<password>${env.MAVEN_CENTRAL_TOKEN}</password>
</server>
<server>
<id>gpg.passphrase</id>
<passphrase>${env.MAVEN_GPG_PASSPHRASE}</passphrase>
</server>
</servers>
</settings>
```
***NOTE***: The `settings.xml` file is created in the Actions $HOME/.m2 directory. If you have an existing `settings.xml` file at that location, it will be overwritten. See below for using the `settings-path` to change your `settings.xml` file location.
If you don't want to overwrite the `settings.xml` file, you can set `overwrite-settings: false`
### Extra setup for pom.xml:
The Maven GPG Plugin configuration in the pom.xml file should contain the following structure to avoid possible issues like `Inappropriate ioctl for device` or `gpg: signing failed: No such file or directory`:
```xml
<configuration>
<!-- Prevent gpg from using pinentry programs -->
<gpgArguments>
<arg>--pinentry-mode</arg>
<arg>loopback</arg>
</gpgArguments>
</configuration>
```
GPG 2.1 requires `--pinentry-mode` to be set to `loopback` in order to pick up the `gpg.passphrase` value defined in Maven `settings.xml`.
### GPG
If `gpg-private-key` input is provided, the private key will be written to a file in the runner's temp directory, the private key file will be imported into the GPG keychain, and then the file will be promptly removed before proceeding with the rest of the setup process. A cleanup step will remove the imported private key from the GPG keychain after the job completes regardless of the job status. This ensures that the private key is no longer accessible on self-hosted runners and cannot "leak" between jobs (hosted runners are always clean instances).
**GPG key should be exported by: `gpg --armor --export-secret-keys YOUR_ID`**
See the help docs on [Publishing a Package](https://help.github.com/en/github/managing-packages-with-github-packages/configuring-apache-maven-for-use-with-github-packages#publishing-a-package) for more information on the `pom.xml` file.
## Publishing using Gradle
```yaml
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
distribution: '<distribution>'
java-version: '11'
- name: Build with Gradle
run: gradle build
- name: Publish to GitHub Packages
run: gradle publish
env:
USERNAME: ${{ github.actor }}
PASSWORD: ${{ secrets.GITHUB_TOKEN }}
```
***NOTE: The `USERNAME` and `PASSWORD` need to correspond to the credentials environment variables used in the publishing section of your `build.gradle`.***
See the help docs on [Publishing a Package with Gradle](https://help.github.com/en/github/managing-packages-with-github-packages/configuring-gradle-for-use-with-github-packages#example-using-gradle-groovy-for-a-single-package-in-a-repository) for more information on the `build.gradle` configuration file.
## Apache Maven with a settings path
When using an Actions self-hosted runner with multiple shared runners the default `$HOME` directory can be shared by a number runners at the same time which could overwrite existing settings file. Setting the `settings-path` variable allows you to choose a unique location for your settings file.
```yaml
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11 for Shared Runner
uses: actions/setup-java@v2
with:
distribution: '<distribution>'
java-version: '11'
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Publish to GitHub Packages Apache Maven
run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml
env:
GITHUB_TOKEN: ${{ github.token }}
```
## Hosted Tool Cache
GitHub Hosted Runners have a tool cache that comes with some Java versions pre-installed. This tool cache helps speed up runs and tool setup by not requiring any new downloads. There is an environment variable called `RUNNER_TOOL_CACHE` on each runner that describes the location of this tools cache and this is where you can find the pre-installed versions of Java. `setup-java` works by taking a specific version of Java in this tool cache and adding it to PATH if the version, architecture and distribution match.
Currently, LTS versions of Adopt OpenJDK (`adopt`) are cached on the GitHub Hosted Runners.
The tools cache gets updated on a weekly basis. For information regarding locally cached versions of Java on GitHub hosted runners, check out [GitHub Actions Virtual Environments](https://github.com/actions/virtual-environments).

View File

@ -1,34 +0,0 @@
# Contributors
### Checkin
- Do checkin source (src)
- Do checkin a single index.js file after running `ncc`
- Do not checking node_modules
### NCC
In order to avoid uploading `node_modules` to the repository, we use [zeit/ncc](https://github.com/zeit/ncc) to create a single `index.js` file that gets saved in `dist/`.
If you're developing locally you can run
```
npm install
tsc
ncc build
```
You can also do
```
npm run-script build # runs tsc
npm run-script format # runs prettier --write
npm run-script format-check # runs prettier --check
npm run-script test # runs jest
npm run-script release # runs ncc build
```
Any files generated using `tsc` will be added to `lib/*`, however those files also are not uploaded to the repository and are excluded using `.gitignore`.
### Testing
Tests are included under `_tests_/*` and can be run using `npm run-script test`.
We ask that you include a link to a successful run that utilizes the changes you are working on. For example, if your changes are in the branch `newAwesomeFeature`, then show an example run that uses `setup-python@newAwesomeFeature` or `my-fork@newAwesomeFeature`. This will help speed up testing and help us confirm that there are no breaking changes or bugs.

35
docs/switching-to-v2.md Normal file
View File

@ -0,0 +1,35 @@
# Switching to V2
## Java distribution
The major breaking change in V2 is the new mandatory `distribution` input. This field should be specified with one of supported distributions. See [Supported distributions](../README.md#Supported-distributions) for a list of available options.
Use the `zulu` keyword if you would like to continue using the same distribution as in V1.
```yaml
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: '11'
java-package: jdk # optional (jdk or jre) - defaults to jdk
- run: java -cp java HelloWorldApp
```
**General recommendation** — configure CI with the same distribution that is used on your local dev machine.
## Installing custom Java distribution from local file
Since the `distribution` input is required in V2, you should specify it using `jdkFile` to continue installing Java from a local file on the runner
```yaml
steps:
- run: |
download_url="https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.10%2B9/OpenJDK11U-jdk_x64_linux_hotspot_11.0.10_9.tar.gz"
wget -O $RUNNER_TEMP/java_package.tar.gz $download_url
- uses: actions/setup-java@v2
with:
distribution: 'jdkFile'
jdkFile: ${{ runner.temp }}/java_package.tar.gz
java-version: '11.0.0'
architecture: x64
```
## Dropping legacy Java version syntax 1.x
V1 supported legacy Java syntax such as `1.8` (same as `8`) and `1.8.0.212` (same as `8.0.212`).
V2 dropped support for legacy syntax so workflows should be updated accordingly.

4856
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,15 @@
{
"name": "setup-java",
"version": "1.0.0",
"version": "2.0.0",
"private": true,
"description": "setup java action",
"main": "dist/index.js",
"main": "dist/setup/index.js",
"scripts": {
"build": "ncc build src/setup-java.ts",
"format": "prettier --write **/*.ts",
"format-check": "prettier --check **/*.ts",
"build": "ncc build -o dist/setup src/setup-java.ts && ncc build -o dist/cleanup src/cleanup-java.ts",
"format": "prettier --write \"{,!(node_modules)/**/}*.ts\"",
"format-check": "prettier --check \"{,!(node_modules)/**/}*.ts\"",
"prerelease": "npm run-script build",
"release": "git add -f dist/index.js",
"release": "git add -f dist/setup/index.js dist/cleanup/index.js",
"test": "jest"
},
"repository": {
@ -18,29 +18,30 @@
},
"keywords": [
"actions",
"node",
"java",
"setup"
],
"author": "GitHub",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.0.0",
"@actions/exec": "^1.0.0",
"@actions/io": "^1.0.0",
"@actions/tool-cache": "^1.0.0",
"semver": "^6.1.1",
"typed-rest-client": "1.5.0"
"@actions/core": "^1.2.6",
"@actions/exec": "^1.0.4",
"@actions/http-client": "^1.0.9",
"@actions/io": "^1.0.2",
"@actions/tool-cache": "^1.6.1",
"semver": "^7.3.4",
"xmlbuilder2": "^2.4.0"
},
"devDependencies": {
"@types/jest": "^24.0.13",
"@types/node": "^12.0.4",
"@types/semver": "^6.0.0",
"@types/jest": "^26.0.20",
"@types/node": "^12.19.13",
"@types/semver": "^7.3.4",
"@zeit/ncc": "^0.20.5",
"jest": "^24.8.0",
"jest-circus": "^24.7.1",
"jest": "^26.6.3",
"jest-circus": "^26.6.3",
"prettier": "^1.19.1",
"ts-jest": "^24.0.2",
"typescript": "^3.5.1"
"ts-jest": "^26.5.3",
"typescript": "^4.2.3"
},
"husky": {
"skipCI": true,

View File

@ -1,70 +1,122 @@
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import * as core from '@actions/core';
import * as io from '@actions/io';
import * as fs from 'fs';
import * as os from 'os';
import { create as xmlCreate } from 'xmlbuilder2';
import * as constants from './constants';
import * as gpg from './gpg';
import { getBooleanInput } from './util';
export const M2_DIR = '.m2';
export const SETTINGS_FILE = 'settings.xml';
export const DEFAULT_ID = 'github';
export const DEFAULT_USERNAME = 'GITHUB_ACTOR';
export const DEFAULT_PASSWORD = 'GITHUB_TOKEN';
export async function configureAuthentication() {
const id = core.getInput(constants.INPUT_SERVER_ID);
const username = core.getInput(constants.INPUT_SERVER_USERNAME);
const password = core.getInput(constants.INPUT_SERVER_PASSWORD);
const settingsDirectory =
core.getInput(constants.INPUT_SETTINGS_PATH) || path.join(os.homedir(), M2_DIR);
const overwriteSettings = getBooleanInput(constants.INPUT_OVERWRITE_SETTINGS, true);
const gpgPrivateKey =
core.getInput(constants.INPUT_GPG_PRIVATE_KEY) || constants.INPUT_DEFAULT_GPG_PRIVATE_KEY;
const gpgPassphrase =
core.getInput(constants.INPUT_GPG_PASSPHRASE) ||
(gpgPrivateKey ? constants.INPUT_DEFAULT_GPG_PASSPHRASE : undefined);
export async function configAuthentication(
id = DEFAULT_ID,
username = DEFAULT_USERNAME,
password = DEFAULT_PASSWORD
) {
console.log(
`creating ${SETTINGS_FILE} with server-id: ${id};`,
`environment variables: username=\$${username} and password=\$${password}`
if (gpgPrivateKey) {
core.setSecret(gpgPrivateKey);
}
await createAuthenticationSettings(
id,
username,
password,
settingsDirectory,
overwriteSettings,
gpgPassphrase
);
// when an alternate m2 location is specified use only that location (no .m2 directory)
// otherwise use the home/.m2/ path
const directory: string = path.join(
core.getInput('settings-path') || os.homedir(),
core.getInput('settings-path') ? '' : M2_DIR
);
await io.mkdirP(directory);
core.debug(`created directory ${directory}`);
await write(directory, generate(id, username, password));
if (gpgPrivateKey) {
core.info('Importing private gpg key');
const keyFingerprint = (await gpg.importKey(gpgPrivateKey)) || '';
core.saveState(constants.STATE_GPG_PRIVATE_KEY_FINGERPRINT, keyFingerprint);
}
}
function escapeXML(value: string) {
return value
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&apos;');
export async function createAuthenticationSettings(
id: string,
username: string,
password: string,
settingsDirectory: string,
overwriteSettings: boolean,
gpgPassphrase: string | undefined = undefined
) {
core.info(`Creating ${SETTINGS_FILE} with server-id: ${id}`);
// when an alternate m2 location is specified use only that location (no .m2 directory)
// otherwise use the home/.m2/ path
await io.mkdirP(settingsDirectory);
await write(
settingsDirectory,
generate(id, username, password, gpgPassphrase),
overwriteSettings
);
}
// only exported for testing purposes
export function generate(
id = DEFAULT_ID,
username = DEFAULT_USERNAME,
password = DEFAULT_PASSWORD
id: string,
username: string,
password: string,
gpgPassphrase?: string | undefined
) {
return `
<settings>
<servers>
<server>
<id>${escapeXML(id)}</id>
<username>\${env.${escapeXML(username)}}</username>
<password>\${env.${escapeXML(password)}}</password>
</server>
</servers>
</settings>
`;
const xmlObj: { [key: string]: any } = {
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',
servers: {
server: [
{
id: id,
username: `\${env.${username}}`,
password: `\${env.${password}}`
}
]
}
}
};
if (gpgPassphrase) {
const gpgServer = {
id: 'gpg.passphrase',
passphrase: `\${env.${gpgPassphrase}}`
};
xmlObj.settings.servers.server.push(gpgServer);
}
return xmlCreate(xmlObj).end({
headless: true,
prettyPrint: true,
width: 80
});
}
async function write(directory: string, settings: string) {
async function write(directory: string, settings: string, overwriteSettings: boolean) {
const location = path.join(directory, SETTINGS_FILE);
if (fs.existsSync(location)) {
console.warn(`overwriting existing file ${location}`);
const settingsExists = fs.existsSync(location);
if (settingsExists && overwriteSettings) {
core.info(`Overwriting existing file ${location}`);
} else if (!settingsExists) {
core.info(`Writing to ${location}`);
} else {
console.log(`writing ${location}`);
core.info(
`Skipping generation ${location} because file already exists and overwriting is not required`
);
return;
}
return fs.writeFileSync(location, settings, {

17
src/cleanup-java.ts Normal file
View File

@ -0,0 +1,17 @@
import * as core from '@actions/core';
import * as gpg from './gpg';
import * as constants from './constants';
async function run() {
if (core.getInput(constants.INPUT_GPG_PRIVATE_KEY, { required: false })) {
core.info('Removing private key from keychain');
try {
const keyFingerprint = core.getState(constants.STATE_GPG_PRIVATE_KEY_FINGERPRINT);
await gpg.deleteKey(keyFingerprint);
} catch (error) {
core.setFailed('Failed to remove private key');
}
}
}
run();

19
src/constants.ts Normal file
View File

@ -0,0 +1,19 @@
export const MACOS_JAVA_CONTENT_POSTFIX = 'Contents/Home';
export const INPUT_JAVA_VERSION = 'java-version';
export const INPUT_ARCHITECTURE = 'architecture';
export const INPUT_JAVA_PACKAGE = 'java-package';
export const INPUT_DISTRIBUTION = 'distribution';
export const INPUT_JDK_FILE = 'jdkFile';
export const INPUT_CHECK_LATEST = 'check-latest';
export const INPUT_SERVER_ID = 'server-id';
export const INPUT_SERVER_USERNAME = 'server-username';
export const INPUT_SERVER_PASSWORD = 'server-password';
export const INPUT_SETTINGS_PATH = 'settings-path';
export const INPUT_OVERWRITE_SETTINGS = 'overwrite-settings';
export const INPUT_GPG_PRIVATE_KEY = 'gpg-private-key';
export const INPUT_GPG_PASSPHRASE = 'gpg-passphrase';
export const INPUT_DEFAULT_GPG_PRIVATE_KEY = undefined;
export const INPUT_DEFAULT_GPG_PASSPHRASE = 'GPG_PASSPHRASE';
export const STATE_GPG_PRIVATE_KEY_FINGERPRINT = 'gpg-private-key-fingerprint';

View File

@ -0,0 +1,141 @@
import * as core from '@actions/core';
import * as tc from '@actions/tool-cache';
import fs from 'fs';
import path from 'path';
import semver from 'semver';
import { JavaBase } from '../base-installer';
import { IAdoptAvailableVersions } from './models';
import { JavaInstallerOptions, JavaDownloadRelease, JavaInstallerResults } from '../base-models';
import { MACOS_JAVA_CONTENT_POSTFIX } from '../../constants';
import { extractJdkFile, getDownloadArchiveExtension, isVersionSatisfies } from '../../util';
export class AdoptDistribution extends JavaBase {
constructor(installerOptions: JavaInstallerOptions) {
super('Adopt', installerOptions);
}
protected async findPackageForDownload(version: string): Promise<JavaDownloadRelease> {
const availableVersionsRaw = await this.getAvailableVersions();
const availableVersionsWithBinaries = availableVersionsRaw
.filter(item => item.binaries.length > 0)
.map(item => {
return {
version: item.version_data.semver,
url: item.binaries[0].package.link
} as JavaDownloadRelease;
});
const satisfiedVersions = availableVersionsWithBinaries
.filter(item => isVersionSatisfies(version, item.version))
.sort((a, b) => {
return -semver.compareBuild(a.version, b.version);
});
const resolvedFullVersion = satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
if (!resolvedFullVersion) {
const availableOptions = availableVersionsWithBinaries.map(item => item.version).join(', ');
const availableOptionsMessage = availableOptions
? `\nAvailable versions: ${availableOptions}`
: '';
throw new Error(
`Could not find satisfied version for SemVer '${version}'. ${availableOptionsMessage}`
);
}
return resolvedFullVersion;
}
protected async downloadTool(javaRelease: JavaDownloadRelease): Promise<JavaInstallerResults> {
let javaPath: string;
let extractedJavaPath: string;
core.info(
`Downloading Java ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...`
);
const javaArchivePath = await tc.downloadTool(javaRelease.url);
core.info(`Extracting Java archive...`);
let extension = getDownloadArchiveExtension();
extractedJavaPath = await extractJdkFile(javaArchivePath, extension);
const archiveName = fs.readdirSync(extractedJavaPath)[0];
const archivePath = path.join(extractedJavaPath, archiveName);
const version = this.getToolcacheVersionName(javaRelease.version);
javaPath = await tc.cacheDir(archivePath, this.toolcacheFolderName, version, this.architecture);
return { version: javaRelease.version, path: javaPath };
}
private async getAvailableVersions(): Promise<IAdoptAvailableVersions[]> {
const platform = this.getPlatformOption();
const arch = this.architecture;
const imageType = this.packageType;
const versionRange = encodeURI('[1.0,100.0]'); // retrieve all available versions
const releaseType = this.stable ? 'ga' : 'ea';
console.time('adopt-retrieve-available-versions');
const baseRequestArguments = [
`project=jdk`,
'vendor=adoptopenjdk',
`heap_size=normal`,
`jvm_impl=hotspot`,
'sort_method=DEFAULT',
'sort_order=DESC',
`os=${platform}`,
`architecture=${arch}`,
`image_type=${imageType}`,
`release_type=${releaseType}`
].join('&');
// need to iterate through all pages to retrieve the list of all versions
// Adopt API doesn't provide way to retrieve the count of pages to iterate so infinity loop
let page_index = 0;
const availableVersions: IAdoptAvailableVersions[] = [];
while (true) {
const requestArguments = `${baseRequestArguments}&page_size=20&page=${page_index}`;
const availableVersionsUrl = `https://api.adoptopenjdk.net/v3/assets/version/${versionRange}?${requestArguments}`;
if (core.isDebug() && page_index === 0) {
// url is identical except page_index so print it once for debug
core.debug(`Gathering available versions from '${availableVersionsUrl}'`);
}
const paginationPage = (
await this.http.getJson<IAdoptAvailableVersions[]>(availableVersionsUrl)
).result;
if (paginationPage === null || paginationPage.length === 0) {
// break infinity loop because we have reached end of pagination
break;
}
availableVersions.push(...paginationPage);
page_index++;
}
if (core.isDebug()) {
core.startGroup('Print information about available versions');
console.timeEnd('adopt-retrieve-available-versions');
console.log(`Available versions: [${availableVersions.length}]`);
console.log(availableVersions.map(item => item.version_data.semver).join(', '));
core.endGroup();
}
return availableVersions;
}
private getPlatformOption(): string {
// Adopt has own platform names so need to map them
switch (process.platform) {
case 'darwin':
return 'mac';
case 'win32':
return 'windows';
default:
return process.platform;
}
}
}

View File

@ -0,0 +1,38 @@
// Models from https://api.adoptopenjdk.net/swagger-ui/#/Assets/get_v3_assets_version__version
export interface IAdoptAvailableVersions {
binaries: [
{
architecture: string;
heap_size: string;
image_type: string;
jvm_impl: string;
os: string;
package: {
checksum: string;
checksum_link: string;
download_count: number;
link: string;
metadata_link: string;
name: string;
size: string;
};
project: string;
scm_ref: string;
updated_at: string;
}
];
id: string;
release_link: string;
release_name: string;
release_type: string;
vendor: string;
version_data: {
build: number;
major: number;
minor: number;
openjdk_version: string;
security: string;
semver: string;
};
}

View File

@ -0,0 +1,151 @@
import * as tc from '@actions/tool-cache';
import * as core from '@actions/core';
import * as fs from 'fs';
import semver from 'semver';
import path from 'path';
import * as httpm from '@actions/http-client';
import { getToolcachePath, getVersionFromToolcachePath, isVersionSatisfies } from '../util';
import { JavaDownloadRelease, JavaInstallerOptions, JavaInstallerResults } from './base-models';
import { MACOS_JAVA_CONTENT_POSTFIX } from '../constants';
export abstract class JavaBase {
protected http: httpm.HttpClient;
protected version: string;
protected architecture: string;
protected packageType: string;
protected stable: boolean;
protected checkLatest: boolean;
constructor(protected distribution: string, installerOptions: JavaInstallerOptions) {
this.http = new httpm.HttpClient('actions/setup-java', undefined, {
allowRetries: true,
maxRetries: 3
});
({ version: this.version, stable: this.stable } = this.normalizeVersion(
installerOptions.version
));
this.architecture = installerOptions.architecture;
this.packageType = installerOptions.packageType;
this.checkLatest = installerOptions.checkLatest;
}
protected abstract downloadTool(javaRelease: JavaDownloadRelease): Promise<JavaInstallerResults>;
protected abstract findPackageForDownload(range: string): Promise<JavaDownloadRelease>;
public async setupJava(): Promise<JavaInstallerResults> {
let foundJava = this.findInToolcache();
if (foundJava && !this.checkLatest) {
core.info(`Resolved Java ${foundJava.version} from tool-cache`);
} else {
core.info('Trying to resolve the latest version from remote');
const javaRelease = await this.findPackageForDownload(this.version);
core.info(`Resolved latest version as ${javaRelease.version}`);
if (foundJava?.version === javaRelease.version) {
core.info(`Resolved Java ${foundJava.version} from tool-cache`);
} else {
core.info('Trying to download...');
foundJava = await this.downloadTool(javaRelease);
core.info(`Java ${foundJava.version} was downloaded`);
}
}
// JDK folder may contain postfix "Contents/Home" on macOS
const macOSPostfixPath = path.join(foundJava.path, MACOS_JAVA_CONTENT_POSTFIX);
if (process.platform === 'darwin' && fs.existsSync(macOSPostfixPath)) {
foundJava.path = macOSPostfixPath;
}
core.info(`Setting Java ${foundJava.version} as the default`);
this.setJavaDefault(foundJava.version, foundJava.path);
return foundJava;
}
protected get toolcacheFolderName(): string {
return `Java_${this.distribution}_${this.packageType}`;
}
protected getToolcacheVersionName(version: string): string {
if (!this.stable) {
if (version.includes('+')) {
return version.replace('+', '-ea.');
} else {
return `${version}-ea`;
}
}
// Kotlin and some Java dependencies don't work properly when Java path contains "+" sign
// so replace "/hostedtoolcache/Java/11.0.3+4/x64" to "/hostedtoolcache/Java/11.0.3-4/x64" when saves to cache
// related issue: https://github.com/actions/virtual-environments/issues/3014
return version.replace('+', '-');
}
protected findInToolcache(): JavaInstallerResults | null {
// we can't use tc.find directly because firstly, we need to filter versions by stability flag
// if *-ea is provided, take only ea versions from toolcache, otherwise - only stable versions
const availableVersions = tc
.findAllVersions(this.toolcacheFolderName, this.architecture)
.map(item => {
return {
version: item
.replace('-ea.', '+')
.replace(/-ea$/, '')
// Kotlin and some Java dependencies don't work properly when Java path contains "+" sign
// so replace "/hostedtoolcache/Java/11.0.3-4/x64" to "/hostedtoolcache/Java/11.0.3+4/x64" when retrieves to cache
// related issue: https://github.com/actions/virtual-environments/issues/3014
.replace('-', '+'),
path: getToolcachePath(this.toolcacheFolderName, item, this.architecture) || '',
stable: !item.includes('-ea')
};
})
.filter(item => item.stable === this.stable);
const satisfiedVersions = availableVersions
.filter(item => isVersionSatisfies(this.version, item.version))
.filter(item => item.path)
.sort((a, b) => {
return -semver.compareBuild(a.version, b.version);
});
if (!satisfiedVersions || satisfiedVersions.length === 0) {
return null;
}
return {
version: satisfiedVersions[0].version,
path: satisfiedVersions[0].path
};
}
protected normalizeVersion(version: string) {
let stable = true;
if (version.endsWith('-ea')) {
version = version.replace(/-ea$/, '');
stable = false;
} else if (version.includes('-ea.')) {
// transform '11.0.3-ea.2' -> '11.0.3+2'
version = version.replace('-ea.', '+');
stable = false;
}
if (!semver.validRange(version)) {
throw new Error(
`The string '${version}' is not valid SemVer notation for a Java version. Please check README file for code snippets and more detailed information`
);
}
return {
version,
stable
};
}
protected setJavaDefault(version: string, toolPath: string) {
core.exportVariable('JAVA_HOME', toolPath);
core.addPath(path.join(toolPath, 'bin'));
core.setOutput('distribution', this.distribution);
core.setOutput('path', toolPath);
core.setOutput('version', version);
}
}

View File

@ -0,0 +1,16 @@
export interface JavaInstallerOptions {
version: string;
architecture: string;
packageType: string;
checkLatest: boolean;
}
export interface JavaInstallerResults {
version: string;
path: string;
}
export interface JavaDownloadRelease {
version: string;
url: string;
}

View File

@ -0,0 +1,28 @@
import { AdoptDistribution } from './adopt/installer';
import { JavaBase } from './base-installer';
import { JavaInstallerOptions } from './base-models';
import { LocalDistribution } from './local/installer';
import { ZuluDistribution } from './zulu/installer';
enum JavaDistribution {
Adopt = 'adopt',
Zulu = 'zulu',
JdkFile = 'jdkfile'
}
export function getJavaDistribution(
distributionName: string,
installerOptions: JavaInstallerOptions,
jdkFile?: string
): JavaBase | null {
switch (distributionName) {
case JavaDistribution.JdkFile:
return new LocalDistribution(installerOptions, jdkFile);
case JavaDistribution.Adopt:
return new AdoptDistribution(installerOptions);
case JavaDistribution.Zulu:
return new ZuluDistribution(installerOptions);
default:
return null;
}
}

View File

@ -0,0 +1,76 @@
import * as tc from '@actions/tool-cache';
import * as core from '@actions/core';
import fs from 'fs';
import path from 'path';
import semver from 'semver';
import { JavaBase } from '../base-installer';
import { JavaInstallerOptions, JavaDownloadRelease, JavaInstallerResults } from '../base-models';
import { extractJdkFile } from '../../util';
import { MACOS_JAVA_CONTENT_POSTFIX } from '../../constants';
export class LocalDistribution extends JavaBase {
constructor(installerOptions: JavaInstallerOptions, private jdkFile?: string) {
super('jdkfile', installerOptions);
}
public async setupJava(): Promise<JavaInstallerResults> {
let foundJava = this.findInToolcache();
if (foundJava) {
core.info(`Resolved Java ${foundJava.version} from tool-cache`);
} else {
core.info(`Java ${this.version} was not found in tool-cache. Trying to unpack JDK file...`);
if (!this.jdkFile) {
throw new Error("'jdkFile' is not specified");
}
const jdkFilePath = path.resolve(this.jdkFile);
const stats = fs.statSync(jdkFilePath);
if (!stats.isFile()) {
throw new Error(`JDK file was not found in path '${jdkFilePath}'`);
}
core.info(`Extracting Java from '${jdkFilePath}'`);
const extractedJavaPath = await extractJdkFile(jdkFilePath);
const archiveName = fs.readdirSync(extractedJavaPath)[0];
const archivePath = path.join(extractedJavaPath, archiveName);
const javaVersion = this.version;
let javaPath = await tc.cacheDir(
archivePath,
this.toolcacheFolderName,
this.getToolcacheVersionName(javaVersion),
this.architecture
);
// for different Java distributions, postfix can exist or not so need to check both cases
if (
process.platform === 'darwin' &&
fs.existsSync(path.join(javaPath, MACOS_JAVA_CONTENT_POSTFIX))
) {
javaPath = path.join(javaPath, MACOS_JAVA_CONTENT_POSTFIX);
}
foundJava = {
version: javaVersion,
path: javaPath
};
}
core.info(`Setting Java ${foundJava.version} as default`);
this.setJavaDefault(foundJava.version, foundJava.path);
return foundJava;
}
protected async findPackageForDownload(version: string): Promise<JavaDownloadRelease> {
throw new Error('This method should not be implemented in local file provider');
}
protected async downloadTool(javaRelease: JavaDownloadRelease): Promise<JavaInstallerResults> {
throw new Error('This method should not be implemented in local file provider');
}
}

View File

@ -0,0 +1,163 @@
import * as core from '@actions/core';
import * as tc from '@actions/tool-cache';
import path from 'path';
import fs from 'fs';
import semver from 'semver';
import { JavaBase } from '../base-installer';
import { IZuluVersions } from './models';
import { extractJdkFile, getDownloadArchiveExtension, isVersionSatisfies } from '../../util';
import { JavaDownloadRelease, JavaInstallerOptions, JavaInstallerResults } from '../base-models';
export class ZuluDistribution extends JavaBase {
constructor(installerOptions: JavaInstallerOptions) {
super('Zulu', installerOptions);
}
protected async findPackageForDownload(version: string): Promise<JavaDownloadRelease> {
const availableVersionsRaw = await this.getAvailableVersions();
const availableVersions = availableVersionsRaw.map(item => {
return {
version: this.convertVersionToSemver(item.jdk_version),
url: item.url,
zuluVersion: this.convertVersionToSemver(item.zulu_version)
};
});
const satisfiedVersions = availableVersions
.filter(item => isVersionSatisfies(version, item.version))
.sort((a, b) => {
// Azul provides two versions: jdk_version and azul_version
// we should sort by both fields by descending
return (
-semver.compareBuild(a.version, b.version) ||
-semver.compareBuild(a.zuluVersion, b.zuluVersion)
);
})
.map(item => {
return {
version: item.version,
url: item.url
} as JavaDownloadRelease;
});
const resolvedFullVersion = satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
if (!resolvedFullVersion) {
const availableOptions = availableVersions.map(item => item.version).join(', ');
const availableOptionsMessage = availableOptions
? `\nAvailable versions: ${availableOptions}`
: '';
throw new Error(
`Could not find satisfied version for semver ${version}. ${availableOptionsMessage}`
);
}
return resolvedFullVersion;
}
protected async downloadTool(javaRelease: JavaDownloadRelease): Promise<JavaInstallerResults> {
let extractedJavaPath: string;
core.info(
`Downloading Java ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...`
);
const javaArchivePath = await tc.downloadTool(javaRelease.url);
core.info(`Extracting Java archive...`);
let extension = getDownloadArchiveExtension();
extractedJavaPath = await extractJdkFile(javaArchivePath, extension);
const archiveName = fs.readdirSync(extractedJavaPath)[0];
const archivePath = path.join(extractedJavaPath, archiveName);
const javaPath = await tc.cacheDir(
archivePath,
this.toolcacheFolderName,
this.getToolcacheVersionName(javaRelease.version),
this.architecture
);
return { version: javaRelease.version, path: javaPath };
}
private async getAvailableVersions(): Promise<IZuluVersions[]> {
const { arch, hw_bitness, abi } = this.getArchitectureOptions();
const [bundleType, features] = this.packageType.split('+');
const platform = this.getPlatformOption();
const extension = getDownloadArchiveExtension();
const javafx = features?.includes('fx') ?? false;
const releaseStatus = this.stable ? 'ga' : 'ea';
console.time('azul-retrieve-available-versions');
const requestArguments = [
`os=${platform}`,
`ext=${extension}`,
`bundle_type=${bundleType}`,
`javafx=${javafx}`,
`arch=${arch}`,
`hw_bitness=${hw_bitness}`,
`release_status=${releaseStatus}`,
abi ? `abi=${abi}` : null,
features ? `features=${features}` : null
]
.filter(Boolean)
.join('&');
const availableVersionsUrl = `https://api.azul.com/zulu/download/community/v1.0/bundles/?${requestArguments}`;
if (core.isDebug()) {
core.debug(`Gathering available versions from '${availableVersionsUrl}'`);
}
const availableVersions =
(await this.http.getJson<Array<IZuluVersions>>(availableVersionsUrl)).result ?? [];
if (core.isDebug()) {
core.startGroup('Print information about available versions');
console.timeEnd('azul-retrieve-available-versions');
console.log(`Available versions: [${availableVersions.length}]`);
console.log(availableVersions.map(item => item.jdk_version.join('.')).join(', '));
core.endGroup();
}
return availableVersions;
}
private getArchitectureOptions(): {
arch: string;
hw_bitness: string;
abi: string;
} {
if (this.architecture == 'x64') {
return { arch: 'x86', hw_bitness: '64', abi: '' };
} else if (this.architecture == 'x86') {
return { arch: 'x86', hw_bitness: '32', abi: '' };
} else {
return { arch: this.architecture, hw_bitness: '', abi: '' };
}
}
private getPlatformOption(): string {
// Azul has own platform names so need to map them
switch (process.platform) {
case 'darwin':
return 'macos';
case 'win32':
return 'windows';
default:
return process.platform;
}
}
// Azul API returns jdk_version as array of digits like [11, 0, 2, 1]
private convertVersionToSemver(version_array: number[]) {
const mainVersion = version_array.slice(0, 3).join('.');
if (version_array.length > 3) {
// intentionally ignore more than 4 numbers because it is invalid semver
return `${mainVersion}+${version_array[3]}`;
}
return mainVersion;
}
}

View File

@ -0,0 +1,9 @@
// Models from https://app.swaggerhub.com/apis-docs/azul/zulu-download-community/1.0
export interface IZuluVersions {
id: number;
name: string;
url: string;
jdk_version: Array<number>;
zulu_version: Array<number>;
}

46
src/gpg.ts Normal file
View File

@ -0,0 +1,46 @@
import * as fs from 'fs';
import * as path from 'path';
import * as io from '@actions/io';
import * as exec from '@actions/exec';
import * as util from './util';
import { ExecOptions } from '@actions/exec/lib/interfaces';
export const PRIVATE_KEY_FILE = path.join(util.getTempDir(), 'private-key.asc');
const PRIVATE_KEY_FINGERPRINT_REGEX = /\w{40}/;
export async function importKey(privateKey: string) {
fs.writeFileSync(PRIVATE_KEY_FILE, privateKey, {
encoding: 'utf-8',
flag: 'w'
});
let output = '';
const options: ExecOptions = {
silent: true,
listeners: {
stdout: (data: Buffer) => {
output += data.toString();
}
}
};
await exec.exec(
'gpg',
['--batch', '--import-options', 'import-show', '--import', PRIVATE_KEY_FILE],
options
);
await io.rmRF(PRIVATE_KEY_FILE);
const match = output.match(PRIVATE_KEY_FINGERPRINT_REGEX);
return match && match[0];
}
export async function deleteKey(keyFingerprint: string) {
await exec.exec('gpg', ['--batch', '--yes', '--delete-secret-keys', keyFingerprint], {
silent: true
});
await exec.exec('gpg', ['--batch', '--yes', '--delete-keys', keyFingerprint], { silent: true });
}

View File

@ -1,286 +0,0 @@
let tempDirectory = process.env['RUNNER_TEMP'] || '';
import * as core from '@actions/core';
import * as io from '@actions/io';
import * as exec from '@actions/exec';
import * as tc from '@actions/tool-cache';
import * as fs from 'fs';
import * as path from 'path';
import * as semver from 'semver';
import * as httpm from 'typed-rest-client/HttpClient';
const IS_WINDOWS = process.platform === 'win32';
if (!tempDirectory) {
let baseLocation;
if (IS_WINDOWS) {
// On windows use the USERPROFILE env variable
baseLocation = process.env['USERPROFILE'] || 'C:\\';
} else {
if (process.platform === 'darwin') {
baseLocation = '/Users';
} else {
baseLocation = '/home';
}
}
tempDirectory = path.join(baseLocation, 'actions', 'temp');
}
export async function getJava(
version: string,
arch: string,
jdkFile: string,
javaPackage: string
): Promise<void> {
let toolPath = tc.find(javaPackage, version);
if (toolPath) {
core.debug(`Tool found in cache ${toolPath}`);
} else {
let compressedFileExtension = '';
if (!jdkFile) {
core.debug('Downloading Jdk from Azul');
let http: httpm.HttpClient = new httpm.HttpClient('setup-java');
let contents = await (
await http.get('https://static.azul.com/zulu/bin/')
).readBody();
let refs = contents.match(/<a href.*\">/gi) || [];
const downloadInfo = getDownloadInfo(refs, version, javaPackage);
jdkFile = await tc.downloadTool(downloadInfo.url);
version = downloadInfo.version;
compressedFileExtension = IS_WINDOWS ? '.zip' : '.tar.gz';
} else {
core.debug('Retrieving Jdk from local path');
}
compressedFileExtension = compressedFileExtension || getFileEnding(jdkFile);
let tempDir: string = path.join(
tempDirectory,
'temp_' + Math.floor(Math.random() * 2000000000)
);
const jdkDir = await unzipJavaDownload(
jdkFile,
compressedFileExtension,
tempDir
);
core.debug(`jdk extracted to ${jdkDir}`);
toolPath = await tc.cacheDir(
jdkDir,
javaPackage,
getCacheVersionString(version),
arch
);
}
let extendedJavaHome = 'JAVA_HOME_' + version + '_' + arch;
core.exportVariable('JAVA_HOME', toolPath);
core.exportVariable(extendedJavaHome, toolPath);
core.addPath(path.join(toolPath, 'bin'));
}
function getCacheVersionString(version: string) {
const versionArray = version.split('.');
const major = versionArray[0];
const minor = versionArray.length > 1 ? versionArray[1] : '0';
const patch = versionArray.length > 2 ? versionArray[2] : '0';
return `${major}.${minor}.${patch}`;
}
function getFileEnding(file: string): string {
let fileEnding = '';
if (file.endsWith('.tar')) {
fileEnding = '.tar';
} else if (file.endsWith('.tar.gz')) {
fileEnding = '.tar.gz';
} else if (file.endsWith('.zip')) {
fileEnding = '.zip';
} else if (file.endsWith('.7z')) {
fileEnding = '.7z';
} else {
throw new Error(`${file} has an unsupported file extension`);
}
return fileEnding;
}
async function extractFiles(
file: string,
fileEnding: string,
destinationFolder: string
): Promise<void> {
const stats = fs.statSync(file);
if (!stats) {
throw new Error(`Failed to extract ${file} - it doesn't exist`);
} else if (stats.isDirectory()) {
throw new Error(`Failed to extract ${file} - it is a directory`);
}
if ('.tar' === fileEnding || '.tar.gz' === fileEnding) {
await tc.extractTar(file, destinationFolder);
} else if ('.zip' === fileEnding) {
await tc.extractZip(file, destinationFolder);
} else {
// fall through and use sevenZip
await tc.extract7z(file, destinationFolder);
}
}
// This method recursively finds all .pack files under fsPath and unpacks them with the unpack200 tool
async function unpackJars(fsPath: string, javaBinPath: string) {
if (fs.existsSync(fsPath)) {
if (fs.lstatSync(fsPath).isDirectory()) {
for (const file in fs.readdirSync(fsPath)) {
const curPath = path.join(fsPath, file);
await unpackJars(curPath, javaBinPath);
}
} else if (path.extname(fsPath).toLowerCase() === '.pack') {
// Unpack the pack file synchonously
const p = path.parse(fsPath);
const toolName = IS_WINDOWS ? 'unpack200.exe' : 'unpack200';
const args = IS_WINDOWS ? '-r -v -l ""' : '';
const name = path.join(p.dir, p.name);
await exec.exec(`"${path.join(javaBinPath, toolName)}"`, [
`${args} "${name}.pack" "${name}.jar"`
]);
}
}
}
async function unzipJavaDownload(
repoRoot: string,
fileEnding: string,
destinationFolder: string,
extension?: string
): Promise<string> {
// Create the destination folder if it doesn't exist
await io.mkdirP(destinationFolder);
const jdkFile = path.normalize(repoRoot);
const stats = fs.statSync(jdkFile);
if (stats.isFile()) {
await extractFiles(jdkFile, fileEnding, destinationFolder);
const jdkDirectory = path.join(
destinationFolder,
fs.readdirSync(destinationFolder)[0]
);
await unpackJars(jdkDirectory, path.join(jdkDirectory, 'bin'));
return jdkDirectory;
} else {
throw new Error(`Jdk argument ${jdkFile} is not a file`);
}
}
function getDownloadInfo(
refs: string[],
version: string,
javaPackage: string
): {version: string; url: string} {
version = normalizeVersion(version);
let extension = '';
if (IS_WINDOWS) {
extension = `-win_x64.zip`;
} else {
if (process.platform === 'darwin') {
extension = `-macosx_x64.tar.gz`;
} else {
extension = `-linux_x64.tar.gz`;
}
}
let pkgRegexp = new RegExp('');
let pkgTypeLength = 0;
if (javaPackage === 'jdk') {
pkgRegexp = /jdk.*-/gi;
pkgTypeLength = 'jdk'.length;
} else if (javaPackage == 'jre') {
pkgRegexp = /jre.*-/gi;
pkgTypeLength = 'jre'.length;
} else if (javaPackage == 'jdk+fx') {
pkgRegexp = /fx-jdk.*-/gi;
pkgTypeLength = 'fx-jdk'.length;
} else {
throw new Error(
`package argument ${javaPackage} is not in [jdk | jre | jdk+fx]`
);
}
// Maps version to url
let versionMap = new Map();
// Filter by platform
refs.forEach(ref => {
if (!ref.endsWith(extension + '">')) {
return;
}
// If we haven't returned, means we're looking at the correct platform
let versions = ref.match(pkgRegexp) || [];
if (versions.length > 1) {
throw new Error(
`Invalid ref received from https://static.azul.com/zulu/bin/: ${ref}`
);
}
if (versions.length == 0) {
return;
}
const refVersion = versions[0].slice(pkgTypeLength, versions[0].length - 1);
if (semver.satisfies(refVersion, version)) {
versionMap.set(
refVersion,
'https://static.azul.com/zulu/bin/' +
ref.slice('<a href="'.length, ref.length - '">'.length)
);
}
});
// Choose the most recent satisfying version
let curVersion = '0.0.0';
let curUrl = '';
for (const entry of versionMap.entries()) {
const entryVersion = entry[0];
const entryUrl = entry[1];
if (semver.gt(entryVersion, curVersion)) {
curUrl = entryUrl;
curVersion = entryVersion;
}
}
if (curUrl == '') {
throw new Error(
`No valid download found for version ${version} and package ${javaPackage}. Check https://static.azul.com/zulu/bin/ for a list of valid versions or download your own jdk file and add the jdkFile argument`
);
}
return {version: curVersion, url: curUrl};
}
function normalizeVersion(version: string): string {
if (version.slice(0, 2) === '1.') {
// Trim leading 1. for versions like 1.8
version = version.slice(2);
if (!version) {
throw new Error('1. is not a valid version');
}
}
if (version.endsWith('-ea')) {
// convert e.g. 14-ea to 14.0.0-ea
if (version.indexOf('.') == -1) {
version = version.slice(0, version.length - 3) + '.0.0-ea';
}
// match anything in -ea.X (semver won't do .x matching on pre-release versions)
if (version[0] >= '0' && version[0] <= '9') {
version = '>=' + version;
}
} else if (version.split('.').length < 3) {
// For non-ea versions, add trailing .x if it is missing
if (version[version.length - 1] != 'x') {
version = version + '.x';
}
}
return version;
}

View File

@ -1,30 +1,45 @@
import * as core from '@actions/core';
import * as installer from './installer';
import * as auth from './auth';
import { getBooleanInput } from './util';
import * as constants from './constants';
import * as path from 'path';
import { getJavaDistribution } from './distributions/distribution-factory';
import { JavaInstallerOptions } from './distributions/base-models';
async function run() {
try {
let version = core.getInput('version');
if (!version) {
version = core.getInput('java-version', {required: true});
const version = core.getInput(constants.INPUT_JAVA_VERSION, { required: true });
const distributionName = core.getInput(constants.INPUT_DISTRIBUTION, { required: true });
const architecture = core.getInput(constants.INPUT_ARCHITECTURE);
const packageType = core.getInput(constants.INPUT_JAVA_PACKAGE);
const jdkFile = core.getInput(constants.INPUT_JDK_FILE);
const checkLatest = getBooleanInput(constants.INPUT_CHECK_LATEST, false);
const installerOptions: JavaInstallerOptions = {
architecture,
packageType,
version,
checkLatest
};
const distribution = getJavaDistribution(distributionName, installerOptions, jdkFile);
if (!distribution) {
throw new Error(`No supported distribution was found for input ${distributionName}`);
}
const arch = core.getInput('architecture', {required: true});
const javaPackage = core.getInput('java-package', {required: true});
const jdkFile = core.getInput('jdkFile', {required: false}) || '';
await installer.getJava(version, arch, jdkFile, javaPackage);
const result = await distribution.setupJava();
const matchersPath = path.join(__dirname, '..', '.github');
console.log(`##[add-matcher]${path.join(matchersPath, 'java.json')}`);
core.info('');
core.info('Java configuration:');
core.info(` Distribution: ${distributionName}`);
core.info(` Version: ${result.version}`);
core.info(` Path: ${result.path}`);
core.info('');
const id = core.getInput('server-id', {required: false}) || undefined;
const username =
core.getInput('server-username', {required: false}) || undefined;
const password =
core.getInput('server-password', {required: false}) || undefined;
const matchersPath = path.join(__dirname, '..', '..', '.github');
core.info(`##[add-matcher]${path.join(matchersPath, 'java.json')}`);
await auth.configAuthentication(id, username, password);
await auth.configureAuthentication();
} catch (error) {
core.setFailed(error.message);
}

71
src/util.ts Normal file
View File

@ -0,0 +1,71 @@
import os from 'os';
import path from 'path';
import * as fs from 'fs';
import * as semver from 'semver';
import * as core from '@actions/core';
import * as tc from '@actions/tool-cache';
export function getTempDir() {
let tempDirectory = process.env['RUNNER_TEMP'] || os.tmpdir();
return tempDirectory;
}
export function getBooleanInput(inputName: string, defaultValue: boolean = false) {
return (core.getInput(inputName) || String(defaultValue)).toUpperCase() === 'TRUE';
}
export function getVersionFromToolcachePath(toolPath: string) {
if (toolPath) {
return path.basename(path.dirname(toolPath));
}
return toolPath;
}
export async function extractJdkFile(toolPath: string, extension?: string) {
if (!extension) {
extension = toolPath.endsWith('.tar.gz') ? 'tar.gz' : path.extname(toolPath);
if (extension.startsWith('.')) {
extension = extension.substring(1);
}
}
switch (extension) {
case 'tar.gz':
case 'tar':
return await tc.extractTar(toolPath);
case 'zip':
return await tc.extractZip(toolPath);
default:
return await tc.extract7z(toolPath);
}
}
export function getDownloadArchiveExtension() {
return process.platform === 'win32' ? 'zip' : 'tar.gz';
}
export function isVersionSatisfies(range: string, version: string): boolean {
if (semver.valid(range)) {
// if full version with build digit is provided as a range (such as '1.2.3+4')
// we should check for exact equal via compareBuild
// since semver.satisfies doesn't handle 4th digit
const semRange = semver.parse(range);
if (semRange && semRange.build?.length > 0) {
return semver.compareBuild(range, version) === 0;
}
}
return semver.satisfies(version, range);
}
export function getToolcachePath(toolName: string, version: string, architecture: string) {
const toolcacheRoot = process.env['RUNNER_TOOL_CACHE'] ?? '';
const fullPath = path.join(toolcacheRoot, toolName, version, architecture);
if (fs.existsSync(fullPath)) {
return fullPath;
}
return null;
}

View File

@ -1,7 +1,7 @@
extends: default
rules:
# 80 chars should be enough, but don't fail if a line is longer
# 100 chars should be enough, but don't fail if a line is longer
line-length:
max: 80
max: 100
level: warning