From fc62ccaa4ff0ce26bfc693d16da2da265b83dc3d Mon Sep 17 00:00:00 2001 From: Konrad Pabjan Date: Mon, 8 Mar 2021 12:38:33 -0500 Subject: [PATCH 1/6] V2 setup-java ADR (#97) * V2 setup-java initial ADR * Update ADR * Misc fixes * Clarifications around default behavior and new input * PR feedback --- docs/adrs/0000-v2-setup-java.md | 65 +++++++++++++++++++++++++++++++++ docs/adrs/README.md | 19 ++++++++++ 2 files changed, 84 insertions(+) create mode 100644 docs/adrs/0000-v2-setup-java.md create mode 100644 docs/adrs/README.md diff --git a/docs/adrs/0000-v2-setup-java.md b/docs/adrs/0000-v2-setup-java.md new file mode 100644 index 0000000..2d0c170 --- /dev/null +++ b/docs/adrs/0000-v2-setup-java.md @@ -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 \ No newline at end of file diff --git a/docs/adrs/README.md b/docs/adrs/README.md new file mode 100644 index 0000000..f23a8f7 --- /dev/null +++ b/docs/adrs/README.md @@ -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). \ No newline at end of file From 9c7940b9c600aa59f59155ebf16e815fb97bd6a4 Mon Sep 17 00:00:00 2001 From: Maxim Lobanov Date: Mon, 22 Mar 2021 11:06:35 +0300 Subject: [PATCH 2/6] Add breaking change warning to 'main' branch (#138) * add warning * Update src/setup-java.ts Co-authored-by: Konrad Pabjan Co-authored-by: Konrad Pabjan --- dist/setup/index.js | 1 + src/setup-java.ts | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/dist/setup/index.js b/dist/setup/index.js index a1ef83a..55052c5 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -28814,6 +28814,7 @@ function run() { const keyFingerprint = (yield gpg.importKey(gpgPrivateKey)) || ''; core.saveState(constants.STATE_GPG_PRIVATE_KEY_FINGERPRINT, keyFingerprint); } + core.warning(`All setup-java actions pinned to 'main' branch will fail on 5th April 2021. Please explicitly reference your action to the 'v1' tag ('actions/setup-java@v1') to avoid build failures. Find more details in https://github.com/actions/setup-java/issues/137`); } catch (error) { core.setFailed(error.message); diff --git a/src/setup-java.ts b/src/setup-java.ts index 5ba3529..5cfb28a 100644 --- a/src/setup-java.ts +++ b/src/setup-java.ts @@ -55,6 +55,10 @@ async function run() { keyFingerprint ); } + + core.warning( + `All setup-java actions pinned to the 'main' branch will fail on April 5th 2021. Please explicitly reference your action with the 'v1' tag ('actions/setup-java@v1') to avoid build failures. Find more details at https://github.com/actions/setup-java/issues/137` + ); } catch (error) { core.setFailed(error.message); } From ebb424f2cb8fcb418a7b62a00e052ee78fc9ed68 Mon Sep 17 00:00:00 2001 From: Maxim Lobanov Date: Mon, 22 Mar 2021 12:05:47 +0300 Subject: [PATCH 3/6] Beatify "main" warning about breaking changes (#144) * add warning * Update src/setup-java.ts Co-authored-by: Konrad Pabjan * Update index.js Co-authored-by: Konrad Pabjan --- dist/setup/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index 55052c5..0e7603e 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -28814,7 +28814,7 @@ function run() { const keyFingerprint = (yield gpg.importKey(gpgPrivateKey)) || ''; core.saveState(constants.STATE_GPG_PRIVATE_KEY_FINGERPRINT, keyFingerprint); } - core.warning(`All setup-java actions pinned to 'main' branch will fail on 5th April 2021. Please explicitly reference your action to the 'v1' tag ('actions/setup-java@v1') to avoid build failures. Find more details in https://github.com/actions/setup-java/issues/137`); + core.warning(`All setup-java actions pinned to the 'main' branch will fail on April 5th 2021. Please explicitly reference your action with the 'v1' tag ('actions/setup-java@v1') to avoid build failures. Find more details at https://github.com/actions/setup-java/issues/137`); } catch (error) { core.setFailed(error.message); From 022e86d5c9c279e4a8e17c9d69fb4dd9912e4dbd Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Wed, 24 Mar 2021 21:30:05 +0300 Subject: [PATCH 4/6] 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 Co-authored-by: Konrad Pabjan --- .github/workflows/e2e-versions.yml | 23 ++++ README.md | 23 +++- .../distributors/adopt-installer.test.ts | 23 ++-- __tests__/distributors/base-installer.test.ts | 129 ++++++++++++++---- .../distributors/local-installer.test.ts | 60 ++++++-- __tests__/distributors/zulu-installer.test.ts | 30 ++-- action.yml | 4 + dist/cleanup/index.js | 3 +- dist/setup/index.js | 27 +++- docs/advanced-usage.md | 8 ++ src/constants.ts | 1 + src/distributions/base-installer.ts | 18 ++- src/distributions/base-models.ts | 1 + src/setup-java.ts | 6 +- 14 files changed, 279 insertions(+), 77 deletions(-) diff --git a/.github/workflows/e2e-versions.yml b/.github/workflows/e2e-versions.yml index 9bd6dad..e8bb2d2 100644 --- a/.github/workflows/e2e-versions.yml +++ b/.github/workflows/e2e-versions.yml @@ -69,6 +69,29 @@ jobs: - 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 }} diff --git a/README.md b/README.md index 84429bd..b1942bc 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,26 @@ Currently, the following distributions are supported: **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. -#### Testing against different Java 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-preview + with: + distribution: 'adopt' + java-version: '11' + check-latest: true +- run: java -cp java HelloWorldApp +``` + +### Testing against different Java versions ```yaml jobs: build: @@ -89,7 +108,7 @@ jobs: - [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) ## License diff --git a/__tests__/distributors/adopt-installer.test.ts b/__tests__/distributors/adopt-installer.test.ts index 4b4a3c0..9e2825e 100644 --- a/__tests__/distributors/adopt-installer.test.ts +++ b/__tests__/distributors/adopt-installer.test.ts @@ -27,19 +27,19 @@ describe('getAvailableVersions', () => { it.each([ [ - { version: '11', architecture: 'x64', packageType: 'jdk' }, + { 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' }, + { 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' }, + { 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' }, + { version: '11-ea', architecture: 'x64', packageType: 'jdk', checkLatest: false }, 'os=mac&architecture=x64&image_type=jdk&release_type=ea&page_size=20&page=0' ] ])( @@ -79,7 +79,8 @@ describe('getAvailableVersions', () => { const distribution = new AdoptDistribution({ version: '11', architecture: 'x64', - packageType: 'jdk' + packageType: 'jdk', + checkLatest: false }); const availableVersions = await distribution['getAvailableVersions'](); expect(availableVersions).not.toBeNull(); @@ -104,7 +105,8 @@ describe('findPackageForDownload', () => { const distribution = new AdoptDistribution({ version: '11', architecture: 'x64', - packageType: 'jdk' + packageType: 'jdk', + checkLatest: false }); distribution['getAvailableVersions'] = async () => manifestData; const resolvedVersion = await distribution['findPackageForDownload'](input); @@ -115,7 +117,8 @@ describe('findPackageForDownload', () => { const distribution = new AdoptDistribution({ version: '11', architecture: 'x64', - packageType: 'jdk' + packageType: 'jdk', + checkLatest: false }); distribution['getAvailableVersions'] = async () => manifestData; await expect(distribution['findPackageForDownload']('9.0.8')).rejects.toThrowError( @@ -127,7 +130,8 @@ describe('findPackageForDownload', () => { const distribution = new AdoptDistribution({ version: '11', architecture: 'x64', - packageType: 'jdk' + packageType: 'jdk', + checkLatest: false }); distribution['getAvailableVersions'] = async () => manifestData; await expect(distribution['findPackageForDownload']('7.x')).rejects.toThrowError( @@ -139,7 +143,8 @@ describe('findPackageForDownload', () => { const distribution = new AdoptDistribution({ version: '11', architecture: 'x64', - packageType: 'jdk' + packageType: 'jdk', + checkLatest: false }); distribution['getAvailableVersions'] = async () => []; await expect(distribution['findPackageForDownload']('11')).rejects.toThrowError( diff --git a/__tests__/distributors/base-installer.test.ts b/__tests__/distributors/base-installer.test.ts index e23c972..a36393a 100644 --- a/__tests__/distributors/base-installer.test.ts +++ b/__tests__/distributors/base-installer.test.ts @@ -19,13 +19,13 @@ class EmptyJavaBase extends JavaBase { protected async downloadTool(javaRelease: JavaDownloadRelease): Promise { return { - version: '11.0.8', - path: `/toolcache/${this.toolcacheFolderName}/11.0.8/${this.architecture}` + version: '11.0.9', + path: path.join('toolcache', this.toolcacheFolderName, '11.0.9', this.architecture) }; } protected async findPackageForDownload(range: string): Promise { - const availableVersion = '11.0.8'; + const availableVersion = '11.0.9'; if (!semver.satisfies(availableVersion, range)) { throw new Error('Available version not found'); } @@ -38,7 +38,7 @@ class EmptyJavaBase extends JavaBase { } describe('findInToolcache', () => { - const actualJavaVersion = '11.1.10'; + const actualJavaVersion = '11.0.8'; const javaPath = path.join('Java_Empty_jdk', actualJavaVersion, 'x64'); let mockJavaBase: EmptyJavaBase; @@ -58,21 +58,33 @@ describe('findInToolcache', () => { it.each([ [ - { version: '11', architecture: 'x64', packageType: 'jdk' }, + { version: '11', architecture: 'x64', packageType: 'jdk', checkLatest: false }, { version: actualJavaVersion, path: javaPath } ], [ - { version: '11.1', architecture: 'x64', packageType: 'jdk' }, + { version: '11.0', architecture: 'x64', packageType: 'jdk', checkLatest: false }, { version: actualJavaVersion, path: javaPath } ], [ - { version: '11.1.10', architecture: 'x64', packageType: 'jdk' }, + { version: '11.0.8', architecture: 'x64', packageType: 'jdk', checkLatest: false }, { version: actualJavaVersion, path: javaPath } ], - [{ version: '11', architecture: 'x64', packageType: 'jre' }, null], - [{ version: '8', architecture: 'x64', packageType: 'jdk' }, null], - [{ version: '11', architecture: 'x86', packageType: 'jdk' }, null], - [{ version: '11', architecture: 'x86', packageType: 'jre' }, null] + [ + { 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( @@ -115,15 +127,22 @@ describe('findInToolcache', () => { (toolname: string, javaVersion: string, architecture: string) => `/hostedtoolcache/${toolname}/${javaVersion}/${architecture}` ); - mockJavaBase = new EmptyJavaBase({ version: input, architecture: 'x64', packageType: 'jdk' }); + mockJavaBase = new EmptyJavaBase({ + version: input, + architecture: 'x64', + packageType: 'jdk', + checkLatest: false + }); const foundVersion = mockJavaBase['findInToolcache'](); expect(foundVersion?.version).toEqual(expected); }); }); describe('setupJava', () => { - const actualJavaVersion = '11.1.10'; - const javaPath = path.join('Java_Empty_jdk', actualJavaVersion, 'x86'); + 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; @@ -145,12 +164,12 @@ describe('setupJava', () => { return ''; } - return semver.satisfies(actualJavaVersion, semverVersion) ? javaPath : ''; + return semver.satisfies(installedJavaVersion, semverVersion) ? javaPath : ''; } ); spyTcFindAllVersions = jest.spyOn(tc, 'findAllVersions'); - spyTcFindAllVersions.mockReturnValue([actualJavaVersion]); + spyTcFindAllVersions.mockReturnValue([installedJavaVersion]); // Spy on core methods spyCoreDebug = jest.spyOn(core, 'debug'); @@ -177,35 +196,41 @@ describe('setupJava', () => { it.each([ [ - { version: '11', architecture: 'x86', packageType: 'jdk' }, - { version: actualJavaVersion, path: javaPath } + { version: '11', architecture: 'x86', packageType: 'jdk', checkLatest: false }, + { version: installedJavaVersion, path: javaPath } ], [ - { version: '11.1', architecture: 'x86', packageType: 'jdk' }, - { version: actualJavaVersion, path: javaPath } + { version: '11.0', architecture: 'x86', packageType: 'jdk', checkLatest: false }, + { version: installedJavaVersion, path: javaPath } ], [ - { version: '11.1.10', architecture: 'x86', packageType: 'jdk' }, - { version: actualJavaVersion, 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' }, - { path: `/toolcache/Java_Empty_jre/11.0.8/x86`, version: '11.0.8' } + { 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' }, - { path: `/toolcache/Java_Empty_jdk/11.0.8/x64`, version: '11.0.8' } + { 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' }, - { path: `/toolcache/Java_Empty_jre/11.0.8/x64`, version: '11.0.8' } + { 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); @@ -214,11 +239,55 @@ describe('setupJava', () => { 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: '15', architecture: 'x86', packageType: 'jre' }], - [{ version: '11.0.7', architecture: 'x64', packageType: 'jre' }] + [ + { 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'); diff --git a/__tests__/distributors/local-installer.test.ts b/__tests__/distributors/local-installer.test.ts index c3b085b..c161897 100644 --- a/__tests__/distributors/local-installer.test.ts +++ b/__tests__/distributors/local-installer.test.ts @@ -93,7 +93,12 @@ describe('setupJava', () => { }); it('java is resolved from toolcache, jdkfile is untouched', async () => { - const inputs = { version: actualJavaVersion, architecture: 'x86', packageType: 'jdk' }; + const inputs = { + version: actualJavaVersion, + architecture: 'x86', + packageType: 'jdk', + checkLatest: false + }; const jdkFile = 'not_existing_one'; const expected = { version: actualJavaVersion, @@ -110,7 +115,12 @@ describe('setupJava', () => { }); it("java is resolved from toolcache, jdkfile doesn't exist", async () => { - const inputs = { version: actualJavaVersion, architecture: 'x86', packageType: 'jdk' }; + const inputs = { + version: actualJavaVersion, + architecture: 'x86', + packageType: 'jdk', + checkLatest: false + }; const jdkFile = undefined; const expected = { version: actualJavaVersion, @@ -127,7 +137,12 @@ describe('setupJava', () => { }); it('java is unpacked from jdkfile', async () => { - const inputs = { version: '11.0.289', architecture: 'x86', packageType: 'jdk' }; + const inputs = { + version: '11.0.289', + architecture: 'x86', + packageType: 'jdk', + checkLatest: false + }; const jdkFile = expectedJdkFile; const expected = { version: '11.0.289', @@ -147,7 +162,12 @@ describe('setupJava', () => { }); it('jdk file is not found', async () => { - const inputs = { version: '11.0.289', architecture: 'x86', packageType: 'jdk' }; + const inputs = { + version: '11.0.289', + architecture: 'x86', + packageType: 'jdk', + checkLatest: false + }; const jdkFile = 'not_existing_one'; const expected = { javaVersion: '11.0.289', @@ -170,10 +190,22 @@ describe('setupJava', () => { }); it.each([ - [{ version: '8.0.289', architecture: 'x64', packageType: 'jdk' }, 'otherJdkFile'], - [{ version: '11.0.289', architecture: 'x64', packageType: 'jdk' }, 'otherJdkFile'], - [{ version: '12.0.289', architecture: 'x64', packageType: 'jdk' }, 'otherJdkFile'], - [{ version: '11.1.11', architecture: 'x64', packageType: 'jdk' }, 'not_existing_one'] + [ + { 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) => { @@ -186,9 +218,15 @@ describe('setupJava', () => { ); it.each([ - [{ version: '8.0.289', architecture: 'x64', packageType: 'jdk' }, ''], - [{ version: '7.0.289', architecture: 'x64', packageType: 'jdk' }, undefined], - [{ version: '11.0.289', architecture: 'x64', packageType: 'jdk' }, undefined] + [{ 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"); diff --git a/__tests__/distributors/zulu-installer.test.ts b/__tests__/distributors/zulu-installer.test.ts index fe5958a..666cd90 100644 --- a/__tests__/distributors/zulu-installer.test.ts +++ b/__tests__/distributors/zulu-installer.test.ts @@ -30,27 +30,27 @@ describe('getAvailableVersions', () => { it.each([ [ - { version: '11', architecture: 'x86', packageType: 'jdk' }, + { 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' }, + { 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' }, + { 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' }, + { 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' }, + { 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' }, + { 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) => { @@ -68,7 +68,8 @@ describe('getAvailableVersions', () => { const distribution = new ZuluDistribution({ version: '11', architecture: 'x86', - packageType: 'jdk' + packageType: 'jdk', + checkLatest: false }); const availableVersions = await distribution['getAvailableVersions'](); expect(availableVersions).toHaveLength(manifestData.length); @@ -85,7 +86,8 @@ describe('getArchitectureOptions', () => { const distribution = new ZuluDistribution({ version: '11', architecture: input.architecture, - packageType: 'jdk' + packageType: 'jdk', + checkLatest: false }); expect(distribution['getArchitectureOptions']()).toEqual(expected); }); @@ -108,7 +110,8 @@ describe('findPackageForDownload', () => { const distribution = new ZuluDistribution({ version: input, architecture: 'x86', - packageType: 'jdk' + packageType: 'jdk', + checkLatest: false }); distribution['getAvailableVersions'] = async () => manifestData; const result = await distribution['findPackageForDownload'](distribution['version']); @@ -119,7 +122,8 @@ describe('findPackageForDownload', () => { const distribution = new ZuluDistribution({ version: '', architecture: 'x86', - packageType: 'jdk' + packageType: 'jdk', + checkLatest: false }); distribution['getAvailableVersions'] = async () => manifestData; const result = await distribution['findPackageForDownload']('11.0.5'); @@ -132,7 +136,8 @@ describe('findPackageForDownload', () => { const distribution = new ZuluDistribution({ version: '18', architecture: 'x86', - packageType: 'jdk' + packageType: 'jdk', + checkLatest: false }); await expect( distribution['findPackageForDownload'](distribution['version']) @@ -151,7 +156,8 @@ describe('convertVersionToSemver', () => { const distribution = new ZuluDistribution({ version: '18', architecture: 'x86', - packageType: 'jdk' + packageType: 'jdk', + checkLatest: false }); const actual = distribution['convertVersionToSemver'](input); expect(actual).toBe(expected); diff --git a/action.yml b/action.yml index 406ad3a..5ba8228 100644 --- a/action.yml +++ b/action.yml @@ -20,6 +20,10 @@ inputs: jdkFile: 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`' diff --git a/dist/cleanup/index.js b/dist/cleanup/index.js index ca595b1..be25b9b 100644 --- a/dist/cleanup/index.js +++ b/dist/cleanup/index.js @@ -6829,13 +6829,14 @@ function isUnixExecutable(stats) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0; +exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0; exports.MACOS_JAVA_CONTENT_POSTFIX = 'Contents/Home'; exports.INPUT_JAVA_VERSION = 'java-version'; exports.INPUT_ARCHITECTURE = 'architecture'; exports.INPUT_JAVA_PACKAGE = 'java-package'; exports.INPUT_DISTRIBUTION = 'distribution'; exports.INPUT_JDK_FILE = 'jdkFile'; +exports.INPUT_CHECK_LATEST = 'check-latest'; exports.INPUT_SERVER_ID = 'server-id'; exports.INPUT_SERVER_USERNAME = 'server-username'; exports.INPUT_SERVER_PASSWORD = 'server-password'; diff --git a/dist/setup/index.js b/dist/setup/index.js index 28da6b3..f329f2d 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -3967,18 +3967,29 @@ class JavaBase { ({ version: this.version, stable: this.stable } = this.normalizeVersion(installerOptions.version)); this.architecture = installerOptions.architecture; this.packageType = installerOptions.packageType; + this.checkLatest = installerOptions.checkLatest; } setupJava() { + var _a, _b; return __awaiter(this, void 0, void 0, function* () { let foundJava = this.findInToolcache(); - if (foundJava) { + if (foundJava && !this.checkLatest) { core.info(`Resolved Java ${foundJava.version} from tool-cache`); } else { - core.info(`Java ${this.version} was not found in tool-cache. Trying to download...`); + core.info('Trying to resolve the latest version from remote'); const javaRelease = yield this.findPackageForDownload(this.version); - foundJava = yield this.downloadTool(javaRelease); - core.info(`Java ${foundJava.version} was downloaded`); + core.info(`Resolved latest version as ${javaRelease.version}`); + core.info((_a = foundJava === null || foundJava === void 0 ? void 0 : foundJava.version) !== null && _a !== void 0 ? _a : ''); + core.info((_b = javaRelease.version) !== null && _b !== void 0 ? _b : ''); + if ((foundJava === null || foundJava === void 0 ? void 0 : foundJava.version) === javaRelease.version) { + core.info(`Resolved Java ${foundJava.version} from tool-cache`); + } + else { + core.info('Trying to download...'); + foundJava = yield this.downloadTool(javaRelease); + core.info(`Java ${foundJava.version} was downloaded`); + } } // JDK folder may contain postfix "Contents/Home" on macOS const macOSPostfixPath = path_1.default.join(foundJava.path, constants_1.MACOS_JAVA_CONTENT_POSTFIX); @@ -11309,13 +11320,14 @@ exports.HTMLCollectionImpl = HTMLCollectionImpl; "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0; +exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0; exports.MACOS_JAVA_CONTENT_POSTFIX = 'Contents/Home'; exports.INPUT_JAVA_VERSION = 'java-version'; exports.INPUT_ARCHITECTURE = 'architecture'; exports.INPUT_JAVA_PACKAGE = 'java-package'; exports.INPUT_DISTRIBUTION = 'distribution'; exports.INPUT_JDK_FILE = 'jdkFile'; +exports.INPUT_CHECK_LATEST = 'check-latest'; exports.INPUT_SERVER_ID = 'server-id'; exports.INPUT_SERVER_USERNAME = 'server-username'; exports.INPUT_SERVER_PASSWORD = 'server-password'; @@ -35646,6 +35658,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge Object.defineProperty(exports, "__esModule", { value: true }); const core = __importStar(__webpack_require__(470)); const auth = __importStar(__webpack_require__(331)); +const util_1 = __webpack_require__(322); const constants = __importStar(__webpack_require__(211)); const path = __importStar(__webpack_require__(622)); const distribution_factory_1 = __webpack_require__(24); @@ -35657,10 +35670,12 @@ function run() { 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 = util_1.getBooleanInput(constants.INPUT_CHECK_LATEST, false); const installerOptions = { architecture, packageType, - version + version, + checkLatest }; const distribution = distribution_factory_1.getJavaDistribution(distributionName, installerOptions, jdkFile); if (!distribution) { diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index c78ca68..214005e 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -9,6 +9,7 @@ - [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. @@ -291,3 +292,10 @@ jobs: 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). diff --git a/src/constants.ts b/src/constants.ts index 99c8351..63d748a 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -4,6 +4,7 @@ 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'; diff --git a/src/distributions/base-installer.ts b/src/distributions/base-installer.ts index 6f1312c..9c9ea3a 100644 --- a/src/distributions/base-installer.ts +++ b/src/distributions/base-installer.ts @@ -14,6 +14,7 @@ export abstract class JavaBase { 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, { @@ -26,6 +27,7 @@ export abstract class JavaBase { )); this.architecture = installerOptions.architecture; this.packageType = installerOptions.packageType; + this.checkLatest = installerOptions.checkLatest; } protected abstract downloadTool(javaRelease: JavaDownloadRelease): Promise; @@ -33,13 +35,21 @@ export abstract class JavaBase { public async setupJava(): Promise { let foundJava = this.findInToolcache(); - if (foundJava) { + if (foundJava && !this.checkLatest) { core.info(`Resolved Java ${foundJava.version} from tool-cache`); } else { - core.info(`Java ${this.version} was not found in tool-cache. Trying to download...`); + core.info('Trying to resolve the latest version from remote'); const javaRelease = await this.findPackageForDownload(this.version); - foundJava = await this.downloadTool(javaRelease); - core.info(`Java ${foundJava.version} was downloaded`); + core.info(`Resolved latest version as ${javaRelease.version}`); + core.info(foundJava?.version ?? ''); + core.info(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 diff --git a/src/distributions/base-models.ts b/src/distributions/base-models.ts index d7a7af7..82344d5 100644 --- a/src/distributions/base-models.ts +++ b/src/distributions/base-models.ts @@ -2,6 +2,7 @@ export interface JavaInstallerOptions { version: string; architecture: string; packageType: string; + checkLatest: boolean; } export interface JavaInstallerResults { diff --git a/src/setup-java.ts b/src/setup-java.ts index 1641b78..92a8619 100644 --- a/src/setup-java.ts +++ b/src/setup-java.ts @@ -1,6 +1,6 @@ import * as core from '@actions/core'; 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'; @@ -13,11 +13,13 @@ async function run() { 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 + version, + checkLatest }; const distribution = getJavaDistribution(distributionName, installerOptions, jdkFile); From 46d5f06eb12a23c55751f8020d02d2faa2367cda Mon Sep 17 00:00:00 2001 From: Maxim Lobanov Date: Sat, 27 Mar 2021 10:56:12 +0300 Subject: [PATCH 5/6] 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 --- .github/workflows/e2e-versions.yml | 5 +- README.md | 2 - __tests__/distributors/base-installer.test.ts | 57 ++++++++++++++----- dist/setup/index.js | 46 ++++++++++----- src/distributions/base-installer.ts | 50 +++++++++------- 5 files changed, 110 insertions(+), 50 deletions(-) diff --git a/.github/workflows/e2e-versions.yml b/.github/workflows/e2e-versions.yml index e8bb2d2..b7832e5 100644 --- a/.github/workflows/e2e-versions.yml +++ b/.github/workflows/e2e-versions.yml @@ -192,4 +192,7 @@ jobs: with: distribution: ${{ matrix.distribution }} java-version: ${{ matrix.version }} - architecture: x86 \ No newline at end of file + architecture: x86 + - name: Verify Java + run: bash __tests__/verify-java.sh "${{ matrix.version }}" "${{ steps.setup-java.outputs.path }}" + shell: bash \ No newline at end of file diff --git a/README.md b/README.md index b1942bc..d7c90e5 100644 --- a/README.md +++ b/README.md @@ -48,8 +48,6 @@ The `java-version` input supports an exact version or a version range using [Sem - 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` -**Note:** 4-digit notation will always force action to skip checking pre-cached versions and download version in runtime. - #### Supported distributions Currently, the following distributions are supported: | Keyword | Distribution | Official site | License | diff --git a/__tests__/distributors/base-installer.test.ts b/__tests__/distributors/base-installer.test.ts index a36393a..177c7ac 100644 --- a/__tests__/distributors/base-installer.test.ts +++ b/__tests__/distributors/base-installer.test.ts @@ -103,24 +103,27 @@ describe('findInToolcache', () => { }); it.each([ - ['11', '11.0.3'], - ['11.0', '11.0.3'], - ['11.0.1', '11.0.1'], - ['11.0.3', '11.0.3'], - ['15', '15.0.2'], - ['x', '15.0.2'], - ['x-ea', '17.4.4-ea'], - ['11-ea', '11.3.2-ea'], - ['11.2-ea', '11.2.1-ea'], - ['11.2.1-ea', '11.2.1-ea'] + ['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', - '11.0.3', + '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( @@ -134,7 +137,10 @@ describe('findInToolcache', () => { checkLatest: false }); const foundVersion = mockJavaBase['findInToolcache'](); - expect(foundVersion?.version).toEqual(expected); + expect(foundVersion).toEqual({ + version: expected.version, + path: `/hostedtoolcache/Java_Empty_jdk/${expected.versionInPath}/x64` + }); }); }); @@ -318,3 +324,28 @@ describe('normalizeVersion', () => { ); }); }); + +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); + }); +}); diff --git a/dist/setup/index.js b/dist/setup/index.js index f329f2d..fa160ea 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -3970,7 +3970,6 @@ class JavaBase { this.checkLatest = installerOptions.checkLatest; } setupJava() { - var _a, _b; return __awaiter(this, void 0, void 0, function* () { let foundJava = this.findInToolcache(); if (foundJava && !this.checkLatest) { @@ -3980,8 +3979,6 @@ class JavaBase { core.info('Trying to resolve the latest version from remote'); const javaRelease = yield this.findPackageForDownload(this.version); core.info(`Resolved latest version as ${javaRelease.version}`); - core.info((_a = foundJava === null || foundJava === void 0 ? void 0 : foundJava.version) !== null && _a !== void 0 ? _a : ''); - core.info((_b = javaRelease.version) !== null && _b !== void 0 ? _b : ''); if ((foundJava === null || foundJava === void 0 ? void 0 : foundJava.version) === javaRelease.version) { core.info(`Resolved Java ${foundJava.version} from tool-cache`); } @@ -4006,30 +4003,49 @@ class JavaBase { } getToolcacheVersionName(version) { if (!this.stable) { - const cleanVersion = semver_1.default.clean(version); - return `${cleanVersion}-ea`; + if (version.includes('+')) { + return version.replace('+', '-ea.'); + } + else { + return `${version}-ea`; + } } - return version; + // 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('+', '-'); } findInToolcache() { // 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) - .filter(item => item.endsWith('-ea') === !this.stable); + .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: util_1.getToolcachePath(this.toolcacheFolderName, item, this.architecture) || '', + stable: !item.includes('-ea') + }; + }) + .filter(item => item.stable === this.stable); const satisfiedVersions = availableVersions - .filter(item => util_1.isVersionSatisfies(this.version, item.replace(/-ea$/, ''))) - .sort(semver_1.default.rcompare); + .filter(item => util_1.isVersionSatisfies(this.version, item.version)) + .filter(item => item.path) + .sort((a, b) => { + return -semver_1.default.compareBuild(a.version, b.version); + }); if (!satisfiedVersions || satisfiedVersions.length === 0) { return null; } - const javaPath = util_1.getToolcachePath(this.toolcacheFolderName, satisfiedVersions[0], this.architecture); - if (!javaPath) { - return null; - } return { - version: util_1.getVersionFromToolcachePath(javaPath), - path: javaPath + version: satisfiedVersions[0].version, + path: satisfiedVersions[0].path }; } normalizeVersion(version) { diff --git a/src/distributions/base-installer.ts b/src/distributions/base-installer.ts index 9c9ea3a..7db3494 100644 --- a/src/distributions/base-installer.ts +++ b/src/distributions/base-installer.ts @@ -41,8 +41,6 @@ export abstract class JavaBase { 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}`); - core.info(foundJava?.version ?? ''); - core.info(javaRelease.version ?? ''); if (foundJava?.version === javaRelease.version) { core.info(`Resolved Java ${foundJava.version} from tool-cache`); } else { @@ -70,10 +68,17 @@ export abstract class JavaBase { protected getToolcacheVersionName(version: string): string { if (!this.stable) { - const cleanVersion = semver.clean(version); - return `${cleanVersion}-ea`; + if (version.includes('+')) { + return version.replace('+', '-ea.'); + } else { + return `${version}-ea`; + } } - return version; + + // 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 { @@ -81,27 +86,34 @@ export abstract class JavaBase { // if *-ea is provided, take only ea versions from toolcache, otherwise - only stable versions const availableVersions = tc .findAllVersions(this.toolcacheFolderName, this.architecture) - .filter(item => item.endsWith('-ea') === !this.stable); + .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.replace(/-ea$/, ''))) - .sort(semver.rcompare); + .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; } - const javaPath = getToolcachePath( - this.toolcacheFolderName, - satisfiedVersions[0], - this.architecture - ); - if (!javaPath) { - return null; - } - return { - version: getVersionFromToolcachePath(javaPath), - path: javaPath + version: satisfiedVersions[0].version, + path: satisfiedVersions[0].path }; } From 68e87bb527dc85ac8719b2ed9716ea4d748865ce Mon Sep 17 00:00:00 2001 From: Maxim Lobanov Date: Mon, 5 Apr 2021 11:46:36 +0300 Subject: [PATCH 6/6] update npm licenses --- .licenses/npm/@actions/exec.dep.yml | Bin 1336 -> 1336 bytes .licenses/npm/@actions/http-client.dep.yml | Bin 1386 -> 1386 bytes .licenses/npm/@actions/tool-cache.dep.yml | Bin 1348 -> 1321 bytes .licenses/npm/@oozcitak/dom.dep.yml | Bin 1384 -> 1332 bytes .licenses/npm/@oozcitak/infra-1.0.3.dep.yml | Bin 1406 -> 0 bytes .licenses/npm/@oozcitak/infra-1.0.5.dep.yml | Bin 1406 -> 0 bytes .licenses/npm/@oozcitak/infra.dep.yml | Bin 0 -> 1354 bytes .licenses/npm/@oozcitak/url.dep.yml | Bin 1400 -> 1348 bytes .licenses/npm/@oozcitak/util-1.0.1.dep.yml | Bin 1375 -> 0 bytes .licenses/npm/@oozcitak/util-1.0.2.dep.yml | Bin 1375 -> 0 bytes .licenses/npm/@oozcitak/util-8.0.0.dep.yml | Bin 1375 -> 0 bytes .licenses/npm/@oozcitak/util-8.3.3.dep.yml | Bin 1375 -> 0 bytes .licenses/npm/@oozcitak/util.dep.yml | Bin 0 -> 1323 bytes .licenses/npm/@types/node.dep.yml | Bin 0 -> 1436 bytes .licenses/npm/argparse.dep.yml | Bin 0 -> 1636 bytes .licenses/npm/esprima.dep.yml | Bin 0 -> 1593 bytes .licenses/npm/js-yaml.dep.yml | Bin 0 -> 1344 bytes .licenses/npm/lru-cache.dep.yml | Bin 0 -> 1048 bytes .../{semver.dep.yml => semver-6.3.0.dep.yml} | Bin .licenses/npm/semver-7.3.4.dep.yml | Bin 0 -> 1021 bytes .licenses/npm/sprintf-js.dep.yml | Bin 0 -> 1925 bytes .licenses/npm/xmlbuilder2.dep.yml | Bin 1386 -> 1334 bytes .licenses/npm/yallist.dep.yml | Bin 0 -> 1004 bytes 23 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .licenses/npm/@oozcitak/infra-1.0.3.dep.yml delete mode 100644 .licenses/npm/@oozcitak/infra-1.0.5.dep.yml create mode 100644 .licenses/npm/@oozcitak/infra.dep.yml delete mode 100644 .licenses/npm/@oozcitak/util-1.0.1.dep.yml delete mode 100644 .licenses/npm/@oozcitak/util-1.0.2.dep.yml delete mode 100644 .licenses/npm/@oozcitak/util-8.0.0.dep.yml delete mode 100644 .licenses/npm/@oozcitak/util-8.3.3.dep.yml create mode 100644 .licenses/npm/@oozcitak/util.dep.yml create mode 100644 .licenses/npm/@types/node.dep.yml create mode 100644 .licenses/npm/argparse.dep.yml create mode 100644 .licenses/npm/esprima.dep.yml create mode 100644 .licenses/npm/js-yaml.dep.yml create mode 100644 .licenses/npm/lru-cache.dep.yml rename .licenses/npm/{semver.dep.yml => semver-6.3.0.dep.yml} (100%) create mode 100644 .licenses/npm/semver-7.3.4.dep.yml create mode 100644 .licenses/npm/sprintf-js.dep.yml create mode 100644 .licenses/npm/yallist.dep.yml diff --git a/.licenses/npm/@actions/exec.dep.yml b/.licenses/npm/@actions/exec.dep.yml index bf804631fc2b86ccb9031c35f148082149b6ee25..b1effd3d3a24dd8a8a5e7131bc61c9b98ba242ca 100644 GIT binary patch delta 12 TcmdnNwS#MdI-|)(4FOgF8lVGT delta 12 TcmdnNwS#MdI-~JM4FOgF8k+-N diff --git a/.licenses/npm/@actions/http-client.dep.yml b/.licenses/npm/@actions/http-client.dep.yml index d18a24ff96c5b636388ec3743aacd15d45d64961..2e3a424310e1f81f8949f970617ddf96742d976c 100644 GIT binary patch delta 12 TcmaFG^@?kP9;4+(eQQ<#AE5*R delta 12 TcmaFG^@?kP9;3xZeQQ<#ADjdL diff --git a/.licenses/npm/@actions/tool-cache.dep.yml b/.licenses/npm/@actions/tool-cache.dep.yml index 9bc438ffe8bec1ac5083710f30003f7be1095aec..16376d871547400b2641838180a171274463cc2e 100644 GIT binary patch delta 163 zcmX@YwUTRsHlx`@okX$BJpF>iS0V z6ckEQD@v>sYIK221%;4|R0Utp5Cxyi}5inl$lu(BwcyzsZXkeJ6im^qTC%KNp KHW2HwiUR<^J~b8q delta 222 zcmZ3VFIxD>#Yl|l`Wr2v-pfk;mlU<_gb2~JL8^n)-qF#19me;K_X z40k3s2&0#&7s8NYZh$amF?&K7kC}ZS41E@N2&0SzYTywTKWVVN!TxR`;f_JBdR%$= NB|!U&trVhTxd4^bJKX>P diff --git a/.licenses/npm/@oozcitak/dom.dep.yml b/.licenses/npm/@oozcitak/dom.dep.yml index 6f41b691e527c4259eeb0f32a86683c78cd734d7..a810093aaf6edf511c4f4ad73dcde332089b1bc4 100644 GIT binary patch delta 426 zcmXw!%}T>S6opCJx(J9rMG7i%DHK}_bth6QHns^JNHZmwTBW$C>68XyBApZw+_@CN zI`5$yH*Q?J^(}l1he`E=^i z>21JR5JwO&t|(_)G7yg;nFI`2JWlS1Q_3%uO1bDQRI#E%62piNLzxaDk*2V;`MYwu zDGd>tF{*R-6P^$~|qVDkzb$cZ(#DCRl38FX=eSuAeVF))Ag2)eN zBRUcT2$Wv4pE)e0OQdarhb_`KToaH7T^C=Vmf3=$;R(&3G6$=22X(qOGFv+T&NS8~ zu@G@g&jSm)d?VXflhEjqHg-J_%+J;flG(^OM>Zl?I`rG7c+urw*^^!A;T{2Oi8vq! cn%Hs7CPCQY`P|Wt3@po4we)AK27_zuABmH2{{R30 delta 471 zcmYL`ze>YE9LGtTK{AN=2egC!$Ye3ClY&~Yu}$bnnk&iGBF3TCD+V-?UPK&x0v#;f zbo3S6d;}lEMIC(r@$S;#aBzG+-|zkIxL5sCe_T~IMy30CqlE~#QJ=<)hQlxxYxE9F z`Mynuml0!85<|pv02ux5Eee?oAU%&5uw;6%eMgq(Dv~mYS;}34J+Uv9G@1}W<&$E+Agvi+1#f> zZB9T35zh_+aIi1ud>3l7f?FNZ#C`x1yror(0=vlCM=l~qCUl!NpP#iJv>o|U+#!G+ lUIOGn9ebW#CkT7;tznx|vI*;pkI0qNfAat{tT!B@b@HoKR8`kQgWo_bOe ziSf+u-fiAS8U5JN90&Twdb}ESX&rp1 zKf-UHK7WP$=VdbZ>z&Shdue)Q$t);~hyblL@^poZ5rdOW2xlWDnX6l2E;0nCK@3+I zF(Pt(azYK{RX~lLgzJ+~76qT(n=sPDVh|v#)wL1`3yrR)|FS!)PFnat`5hPKeeAgS z=-C=6I)YV$4|qQIsBajfo*Woyol!L{A_O(m-PDk#`M6UU=50;H;e)Y+iDo8?rbv3| z5qsUJ^EHHCdbi_r>XdCmXcRG=CWqaYiazcTvuIY@fR&vWi9iai+%Lnd^#)B5AR#7) zYVHAAs=VR#_{AIUg4CTSGaxy}g-wmdKt1>0vUXVUa>>qFcb$GCzqKA3MIqQV&C|ES z2657_(tEsJi9tJ*PtuVU7v&ZCOW-l@$F>z+2Pb*Y6II{_utcb{O*B58EZ%abLbZY_1d{aF~1p{8fzR17xgeAE7sKml?5yCUCw)vp~>?xwGdVzccQT77g zc$S2~{@53+EFmulm+$r|XUQ#Mp2g`Q;n@>B;&_(hd%^MTK=dkyYRhIs&TxDKJ66P7 zB#0h)%Bz=<@HV{42z`?mUTXyVsHk{+NTUMwhhm?X48hHVt)0h5@OLBgUGA#sJ-?0fF_`(FgNdxd{sfBqHx3m}QbzyJUM diff --git a/.licenses/npm/@oozcitak/infra-1.0.5.dep.yml b/.licenses/npm/@oozcitak/infra-1.0.5.dep.yml deleted file mode 100644 index acee98bbcacc6aafccf400d7aae7cc5fc2c70ccc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1406 zcmZ8hUyqwO5P#=WjPle;-)W*Gk}o0I7Oa!v#twhDMksXmu|~aY2;UxpBQ(U6gC5)3Vn6 z>R0lhQ?(o{cJ|864|W|qfYpW}c-r_Wy@|9P1V{(7f#-(H$tSuzXCA|gO5jXYi9V#MHN6T;a@N#^QSn2QX-X%NE| zMvRDDpPWzwc@A&pGs*@HzP=3cnc^^A2 zK6U<5Mm)`9-ojPUP5E?}cr^#WrrJ|2J#4MVXHehAvMIw+wEBDJVYrR2J1W1U< zp_+SumMU*}J$~_qyC8Mv$qY!2abZ)VF;LI_x2zpjyj-$#)?KIH$ZxHOMo|cMP4o1v zutA*ktMndkS7Oi(<&$(|#YK5V{t|f1`>}0B*TG5N^F$T60W1;fY!i)7CyTe-Dbc~G zjVJ%V{pGuuE!|pxGT&6sQNe(hurKoOJYflLJ}R+rT!iqXF1 z773z9p7QD?B)ko;GD6?vh1VLvJ}N36AJV9R{h`?BB||X@qGvqY6iCK)EUT8lGpqso zjt@|7qckN(f{YGmry#)|G0yid1%KLBu+7ti;lU$AozY{;h}Aod(}?dvNTOZzL|O~T z5zHH=&YN6#-ZH9sRAi6v6IVRX$XlFeRe_HoS}&@1glAr|5Tb&Yl+vciciuInjYG(T xI5?Uy59E<)8$P`EwP72DdB7xQWstBaMMzv>Hv69Y{r(rh?Ox#@*q?s|{{kyB#lipp diff --git a/.licenses/npm/@oozcitak/infra.dep.yml b/.licenses/npm/@oozcitak/infra.dep.yml new file mode 100644 index 0000000000000000000000000000000000000000..eeac49dd3c33f1fc758d12c7e173ef0c0dde987a GIT binary patch literal 1354 zcmZ8hUvJws5P#RFIQXdr6uaHi=BF_-9TSr!gOZyD!yagfwzx^8KvGFv?8EO!*%?~E zh{NOE@81!Acz8&(7~~ojzZ>(tQC|GBQu=JgB6*e8DWli$dHHGiYvQjXw&`(5+%ycr zUe`c0sA25oAhj1Bd%>K+cM@1YfLy&QeSyjg-3r?#of+gPE{M{3Kdx7+i}KxcS~g}_ z{Yakls*&1Z=b-%k;MU0lI5XKsx;5l1qeVp%058A!HT;YJ0qj|gv~f0xh0Kgst1g{~ z56wsT<{S=gL`l$_C?$^D-1n1oZ_!xzYfaqd!=q6}RVKA*a zhi@4zj?<}Eu1ld+0sb_3>~x_RvrU7am9gMtKg&ZDg&uDEzpIRWAur4db=)Fzq4I{W z;YUYm)^(n&MrsTRyIO-0M&`d|<3lC5IGesVZ^33`bgP1Qd>qkLjo0F2US;$(Z(bXZ zvf~PThf9fK=561uTqpV-PVyEYa%0?Bija3}=yp0ee9T^n9!6s$@6VQ(Hyt|)Rk^L7 z38%m+IPmfd+t3XxNQLJ`3eT+GmB$*egOj3ufpQC^c!57yu}Oh`J#bo8Q1YmO?GHJl zSZ76+A2+Ocf=8S!N__4NA3XxsCDcfIgJTqDx3H%?+aWr6WI3x}(g?O?brG<)B?kfr z!fTctbHd?pvt`SswB(Vu@M{{h%Drv(52 literal 0 HcmV?d00001 diff --git a/.licenses/npm/@oozcitak/url.dep.yml b/.licenses/npm/@oozcitak/url.dep.yml index 6a1c62a124b2ba05305a2049179ba64391590b4f..6f3ae3985f98768c5c88e5a81d0aaefc31eb1a67 100644 GIT binary patch delta 427 zcmXw!%}T>S6opCJx(J9>k%Ed`E5#N=-H3u#Y-|%ckY++MwTQUr&y)sZBApZwd2YL%5)HkG=+uD-<9(< zX^7C2Q5^>H!;{YQYAq)*chv&FQ>%0Jrta_$b#p0g#DCRl38FX=g@KKGVF-N+K{N=b zLpl@#2$WuPk~u7;OQdCjk1f(QJQI))u7|Hs(`-V~@P+0)bFeITP}{YU+0^-WrkevypL$Y(%bg=(bGpqQ}3oXWP=l9Rk=AaX=0< cu;Z8wg0RE)a>rXTuqap6(x0(YxVhE-0p`kbI{*Lx delta 472 zcmYL`&q~8E9LH(bgY+QcA5ahTM=v_;rY8?Nadm51ple2(In;WXGsA+m(p1EU5FESi z3H0bIc=Hi_3@_@*Bwg_k2%pdQn_oiS^>6)oQ`sGFO_z-hBH%_t8Z#QEVJz186V{4- zm!`K7V^I=A#B>0d%qvH$!X_igt|JC48D$THluCK2RH~s7%ur}lOvnzU?g@gb*q;L5)pa8l)K0z(J1)*UD9E6j!w7no2sMB?k-OA^_lp0F{ zI*5375P*YyIp??3SQOmqkv8@Nm|>*V*9CTwb&Om@PEF{yZ9YG5O|=90Qrshe9bN+D iK@)qP-6RNm^5idVPiBhC*2H;+9w!<9Jhl(#7y2K~f{#}K diff --git a/.licenses/npm/@oozcitak/util-1.0.1.dep.yml b/.licenses/npm/@oozcitak/util-1.0.1.dep.yml deleted file mode 100644 index 2d7a5a661d74c1d634bbc5ab791e6c33862ea3ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1375 zcmZ9ML2u(W5QXph6$77k0ma_*R-ej9bWBv13`*WKsC%F#+F~n-hDdGJ`|CSHM=7>| zZ9wGkoA=&Oet39@2G#2|EPk{0M{T_NXEk}#EuwFFbjA*AcwBy2K1Tj_#j4@jM{eqS zHQv^6z&hh^aGr+RW2uW;+v}^kU}5Y1b-h|$jBlsYvbO!|Cw$bIS`Q8jd*kN^w~ijb z*=ek`TSF!io|ilV@cO$)fjdz_c0YC;j{|)Zd%cb3(t7w*e}-SaJpKyBkIOXTZ?H1g z?e*9jM|QwCBm%U0)TbL&76c3zDryYFqt%l>Gd_Q(vd=A|jtvbS* z0kIn9?Ld9Q6z$|;)XtA4WF3PU>TYUC)4bgo4D;TK5Fr>xOf)k&G)2P#rj0=kzi-CsTf9u-gN{~x-&bI698~Ls6(3o)H)^wh}6&9$I{icJ* z`;{21NBJcEKB%B5T!O%S-*&C)IymX~JW&Ns0GEh5+eG8j$$7jgMs;wtV`%<=`^yh8 zTe`IXWwEJVnB*Wz*vsOpNO_8rXC*Ei7csnuYFivCz#7T&>J^F&u>2K%7kL^3|6?zC zSwbO+D|Y)#@bn(B$dl}liu@U#@OWO}dm-@cKzda`wdFHWa6G<&9hb=#8?YyliRv{b z-bPe8(Km$*S{dw_tVD9in1ua7?u(M6m=x)`$Tt$3@g2{rC5Rl?fPcjYD7P%js3RfS z0qsZ<9EeG=f0g2STfw%-QjQx>9Cfm%j8oU(G|8CQ#gMWcdnTGOEGrCWiB)`e}ojT*%7#c$zPLs!KM~h)fF=o-M>~|eJ z-mk=9J<2EP_dx|k;SvPq+qP>}*TG4@<%ueA0=Puf*(MsFPR`?1F{*>B9Ygb9?JwWO zZ0Xhll*OicW|D&_VK0lXBIPMgo|U+8T*UA!s%>$o0Ba=6s~0FX!15RPL*!`;{Lj7Q zWeJ5OuGsA}!P9%hB2ThID)J|I#N&B^?}fm(1L;)()t1jh!SVP8c3dV~Y``8xCaRa1 zcpFjWMBfxLXl1ZxvJ%N5V-ofUxi3nNVp62%BHu`C#&la@5HlGfrKD({J1Qc4?H?1F1b8xLV0G(vdq kW5Y5E^MFar${^(|LnMwcpMB5uVg8Hgey{Kk?Au?_e={Y!6951J diff --git a/.licenses/npm/@oozcitak/util-8.0.0.dep.yml b/.licenses/npm/@oozcitak/util-8.0.0.dep.yml deleted file mode 100644 index a8ff7da69ed805ab49045982d87195cb7a13708e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1375 zcmZ9ML2u(W5QXph6$77k0mV*xYJI9A(J@h3GAMb|pzeW|Xp5~x8X~n>@2~F+9i`X; zwgHjDZ{B-D`QhOqGICIBSo~(~_eOj9&ua3zUqoNk=(II!_+|OHe2o0{W6XC8?4NA zdo>Q)ksZ(ui2$7%)#(P8Q5vt>7|x?oV9(HWa=fS*yaj1)aK#YtkUe>+jW!pM&|pvE zVzKYEL&0bNCPx*p(zGC*vyGOBh1NFHpp2Ik51e(c9DMSfg5#okKXzPv4&7QMd%|ji zSOxQTpuS;>cJeSP=SLl~jzOEIpIXv1Z}%F*ytg7m2*wc;%}fqWk@Pqa2ixlNErvk_ zx7X>^YuCllYU*&BJXSke3{#3Ri*{v4aH>rw_Pu>0zl}Am4i|1s=jmHxfjrr-DtNqK z31dCVC+YV=1x4W!1m^p;>tx@!VBa)(ig>nN)@e055B8!3ju@|hW zpcKUAyM4}Cc8{1BX@1Cf@eEIRyeRR#;P`eRy)L2NvYE&k9^b%@iFAt%k|&C(#6WAxB=IJ3%1nduDUsepoWJoV~u@Tse?O0JSffu+2>guQ{N}wklph`*qEQZN4U6B6`POJJ|5;65_lxMOvQC?E4ZkiwEk8y6cEzgkIz(<7 z25E0=IAERjH#kpYbRF4}j~Y1x=z^&LLyb)!ayg@g9-NeH+L0a54v7Grvg&k$iQRpukkDXH z;$pGyv_rvX|0=BtSUI*JoimM=h=tZP)1XE#DIPfMUOD*SI|au@^>*yI_!zpiO7?`+ zBVrZI+kyIuDVoWHRnA)-vW`KIO+U4yY2NNNhIwyAh!Bh;CYqTXnj-0OAP%P0=UWVe z3U05{sn@QHq1DvkG2uoV;1eoSa7NjA`zs~N{HZpt#>p~qm@^@ z9p8DwS&+K(WJhd{abZzwFwoHZZ`F8Q33AEK+4Q}6CBKasTOBUkn$FX=#sYaVUsdpU zzY?SID4(R?2Ne{BOAwfE+pd#+4=44OC#t{+;1W@1n`nGGIgeLG%O0-AhUP!oU%rdk z(yaxk%1!;82nM`@y(mBPjAc0aq{4;cB8F#PZ_7gsSR<06et~iWN$~=I@FI(Wec20E zRZt4z^4&h?EW1a{i!?uEym*2~JYJOeUT}OnkY1NiZ`n-b43BSM$3(it2FWAOdHoU- zZ^P??=$ldmtqJTCQS%;sP(fwZGAK0INMgIY8q`Mvf diff --git a/.licenses/npm/@oozcitak/util.dep.yml b/.licenses/npm/@oozcitak/util.dep.yml new file mode 100644 index 0000000000000000000000000000000000000000..dcee45c0fe62e5892203bfe003f30e425563f154 GIT binary patch literal 1323 zcmZ8hO>f&c5WVYH418(;#cp>mS)Z!NbWE%)8I;^KSnNTTXp6g&Xoyr(7ya>lr0f(e zV8r2Y=6wy}`}_N#FFU!U*+;FvRmztCFGj1{S@1;;M(KV@5A#3g4}ra$(bb>3z>Hm2 z4wohE(WmT%j$>b0w3?vNojjK(G&a_rmy5+o*=9V@>+@w$r^eE|>W=<+|KTsnzMaMaf4!Tj zYbS?J8Rv(Tp+*k!aG}#s_Ey#*9S12%AE|1};Uq({n#%q{XC#0DeXynKRez$ADzJH4 zblV0{Mj!2KIY2b5X4>}k z$~0x$(m`GW1UKSF$p>|_2DjtESUd_Hrc))bciS|UMO2rl)lj4JY9vvKJNs}bIOF*z_+`EGt_w+C;JsopXd>@ zX@=*{@#q0uWK@9k3db2{*R*9K-T*y%M(N8|ViUExx(_^E7MzWB2}H)}c2)I(fC*j!Mz-nRNd5RbhJ>_@ zA|)QroH^&rz~kei*B6}#VD*o^48m-BRf(1NLueyaAHb)-)_<=*d+siPe&{?ic3q(_ z0dNfErIv$*O4PEK77Gm2N<)em>o?;ysuM$T#>&Rp!33MlS=weitxMHy;<-q)7l%~+ zdH$e9QFX#=Whr`t5S_HQg9*GxFlyALFaabqB56)M04x5p0sQ=of9KDha!6(XZwW?f zxM+E9EIgDSVJ}OqjH)d}N)JjGPR9D4eGs~n#+d=qKqIs`UEr*X-ipeHS_=WHhO#O2 zS@>WT6#WGTv=0l^$rfl#e})1|?7C3E3fmx@>-%14fkhP*#;8&jhzpe}$4>NiA_KK- zg@Fg#2w3IUiq*%dStW{gL6tqC3b>`fJDROV3tAYfW$A?ZAp5c%E63?}-Ac4}?&QiR zYs>X|&a zvz>CCf9M_ZxmsvkwCXMrE^va@yX)M#ACQ|bjT(3-1v@M*()llq@_G4%s{2~9BjpI84dA8**AtOL@II!#sjY$lvFvs)ChZo9s*^vWgurTGXkZmDMU*TVx z#y*g*2S)N7GPZD``$Iwr-qAEljxkN2;R);03?C1Q4+(4m*TT zG@<;}UjVn1r>@5~V-Uh2WSmCFBxGjOIo% k8MsUiQ=FkkG~>n%ViG2ZiDOKElYT4m=Hx(eWSO%5s*1fEG#n$(Re^Z>*9rs#M@m^y|C(QjrZ@d*~IjV~5 z4a77eNluW@@W0Il{=xqM7DdD1KnsW`fTiccksNMHTp9z5XbE2)pT0nOgI8f#dxPWn zU5S25JaW|uZ7l<#q2Y>S-bJzA@Y;v7;@s-58tj+*U?i{}%|ny1K$eDy-YREMA)#Z& zY||i=mS=Niieo_yOlw&QhL}*x%6W|jBg9#>T*Jbkh=+Wxcvw23nzPm+iXIU;+>hak zX3Eik;@T)tSsWikU$tXxd$}LC0q~#rgPAk(l~AkE%y% zGzqh6i55EMzj$SA#Hu*Uwv|^avyy!++yri>n=J5{l@h1c>Y6UUmj>H*SKuziH8b7z ze54!JwovlfK;*{BuqN5?T^gz#OKor{1Z&-+u#^9@`DSwW*y9A
mMH zgnL2o|GkuvaC;y@S7X||nO3eM`W(YWHSeI0A2!g}#V_{b;Fi-ea1a@9Iny|lV_$RS zUVz}BSN0M9~XCb z*S2$GACt3g)!^{#!F97=X6?C|oVxA0MKS|tCfh2vfP!VT6m-56c>>_o-+lrA;0ho! zb_9sC3;cq4%VS3Z)qi!RQ6dE*WRJPaNs}4qMo^*!`e`-8_ zf_dk&`4U`3qMZ(%UA)vQzqs%M_z~W6b6}1)QmyF}+V4DA@Vr&Zss3y>5)Qy=8@#U^2Q_c78?qo(wj9Wy_5WYVD?0{cn6iFv#^qTW8v- zSA%~UfIAH4G6Q|%mDSDJeGMQc7o@(m6?3b@|!>Yn8^hvfm}hC){D z4xFtw5;j$lQ!ap%IqsH{vt=zS+;~R>-h3C?g+o#vfPUU_Dg;y<*mhSi1jG)Ul#)@A z0xPqk&RMxm0YRXwBo6+TNi3698X8Bm@2^6&f-U9Q29d~;6-*u?p%s&5=(oa#1a^c= zmemE}u&ep55*N52F=rwx2;0(pjx4Y<(0f`+5F1hy@bO!@pI}Lm8d(O61*C+49^fiRmNB`n2H|)aPTDBpTd4aaUX*&FLObHF#_i!3#q=8VNVAGNRT4pq`sshrU3HlxgXUK3JV8cZ13HHTV!QNOCgyAxRy_sS39Pi$yeuUasMbU0g-qMPH?{N)K!JZTbBB@>ArlBc2XpAK9tzg}JWbNcJf_ zFF(U5jFkq&&;UM_=+rl9qE`2E6c?Ooog3|XwYn(RPN!w9`_-TuS&P-3ty8reEVlN_ zMYk8bjuv3`WNK;Gkg|kkC5-@_{MW7FJN^QAtXc_sRzW%gJVl|L=<#aQrFHO_Ji+Hr z&(90|`U6f^cvDVvS16`$Mh$a!Ax*EWcMHlwD~-gyixGp9O$=uvCFnEMtuPlEgVSjA z3M1x&1N!8I8q{zB0X4D)dhB*BLRo!wAHv9xjIdVMN+2dQx}JJDIN?0!S#{FFqeCYT z~IC)Qi7QIwr@wa6c?%G^aWnjO`SRTwx}8qe;Zop!!>CQ*{nhgF zrejB;%(vA$;S^X21<&8uhHl`2l=%J-!#k^X`Jn>r;3TV#kZ*xxNBEOvn;7U{1*c^R zIS)G6zDOCxI?IyuuwmINyx?q>~&YcE>AZUi!T%vl9!aubZ9V13ERi8A$#)bRdUD?Y4+(`XQlAIqrU8U34W4_ z<(apXHAct0`Z4~_N*V*pnAQA&Q58iszxWz+Pc;ZYxuIfTizx9Hsba$_KBPNUfJ6k2*i_M&OdeK z!8gi7tvl_t!-a-UE9XUr{w@y-UX0nxbYsgtf3qcbAuYdV9{Kh)~i9k$b zkk9%gKFrK`v+cF<@TvL?EX;*(OAuAlO&G(18fwVQ;B9-Jys>VU9kuOS7uo@D0CO#% zLZ=1vrfx5IMcK+&s9QHHHTKauM7;PHWi?!IQw_JsFiv(fPQwcp0Qfvy&E(;tHD-iH zTYbL4)vCekdI6&~&uxuO#=1kz>TI5MvYaF$*&<>!wF5tHs z-^*Opo`NX1@{w?goxzcp4{Sp>@PPQOINcGBni6Gb_-;u9-Z1)tu2XdcN*p@tck>Ux&k!FnK3qP`_qGWArI7T5yf8 dAasH>k%Mw9<3OVG_WxJ1Oy=(c|D*3el0Vw$I?@0D literal 0 HcmV?d00001 diff --git a/.licenses/npm/semver.dep.yml b/.licenses/npm/semver-6.3.0.dep.yml similarity index 100% rename from .licenses/npm/semver.dep.yml rename to .licenses/npm/semver-6.3.0.dep.yml diff --git a/.licenses/npm/semver-7.3.4.dep.yml b/.licenses/npm/semver-7.3.4.dep.yml new file mode 100644 index 0000000000000000000000000000000000000000..3062ac0780d21f549acfcfd1196ce66ff184889b GIT binary patch literal 1021 zcmY+DL64g-5QXpjicx!MrGy+>sZwrU;v|-c+1k#owp9-fH~}eOWSiYa>W}Z(>}uOX z0><;+d~Yzz19wz71jY>(%Pgg?2jSwe43}u^Mb+mUG{a&giB$*|n?9 z;8D`~`fcIY*%G{+Ty6XsN>)%VX$BC?@34kHcn1lJ$pXq*pQVR|9dE9?v;jWVpMiO; zYxt3atlR5k0^;hSfx-^Kb*Cv<=V#fyaee3G6d>3bX#q7lEugnecg8EqR@On&`B`Zo zw4F!9b9m9tz!^97a7zs1Va+O20jpp>kmNq24WF8s(mG3gL5qjJ4hg938)f;D@J8vdSq%3g6@bwO@%Tvd^hJs zdE79*OGIJB3-oxq!#qWW$LISI{jdf$*0&Ya<>vGPvCrVb> zSztnWELBXh71aUCN}^&5M@g{>Q6$Q7jtDIm@VKXlC?YxGGgP5i#iIh7D?uU?r@NBv zC@*LfS4p8NfrUq$bP_Cp2qt6K>ZqdnH6t3M565WHHNAp36QoHTRNycUBsp*YeG0&NS-xn+|f(Mw{05=?Mam zHsN0%T!3kH-E5jFXx69FDB3I2HqNP<_C`N8H5P7LI{YXAf$me&Jy4~)y7855NNSZE z1-xtek(edDIWwwst*AX%hhAI>rXI3f>qiB+lWYNmsM8LU=wnA?X@^EV%-fo1_eVld z1Ji0+WrqJk1O?ydaVCN$>qDjfCoX;-;Cbq**45#~p?*L&n1)8&P+K}>nsR4fRS)Cx zO}-uUxw%wfn8@>Se}23^K`g5`?#a)w1NJ!@rqDR+B|LgY8;hFHv_5l#c_67K)zydr z&v+)Sc5p67yUVOJjUZi(HJCMTQR-Od|8b2ZGEjT@nAh z$hnl1mHL=>w)Xd;T#*PEaqqXo+g5iJvz(_)z~GRX<;1*llaC}CpG;~`j}GVwc}79?jZ zNkU<^EM~qfApNuXF$YmLPPni1(rqkq9u>Z=*Hr`+!7=HRT<}Qv1^>*U1DH3`G$ z)BTLYHyC?*bP4mqNVp~PGk)2InlMlCQ@@n*X(FaPjksr(d8B(G`4#3Tz;Nneed&9K zx^NC^dzXUUaVd@po*fO%Ft<8 literal 0 HcmV?d00001 diff --git a/.licenses/npm/xmlbuilder2.dep.yml b/.licenses/npm/xmlbuilder2.dep.yml index 53c33f67fb3e37a91fbae4d022a6b12c4578ef35..fecc99a6edba19d1f67a195bc9a45865b3362446 100644 GIT binary patch delta 420 zcmYL`PfNov7{*za-DsfDc(Ln5Dtw8;aSj z!^SsU2%f~ig*0==B^^jckX~^CA{nLkgE5omx$0JhOjV_7Lz=)P8(ix&k5!t%%$9Gt zqa|&q(4Am543pajTN*}fRbwSN6QGCum)Wv!I0YS$&&Ha3H3mswxb#78vr2mv2QvY4+g zXy|rn3r7SLWBFQHvjDj#C_wbghF;546C?SVKg=G2yA-gm;($VE;4t(W6yZ>o3i~U% Sc($Bl#Yw7uKpenD-}(a`RBk)~ delta 455 zcmYL`%SyvQ6o$!VAz2kKcvha z>e5$m=OgG_xKWorfHRW@7X!oh{Xgdn^J;xrkL$*Ed1tgSp0`_wfX{j~<}?~cu{@)9 zSkCWlI=o_>vm^$_EdUs62TM{W14u6z2c8Vl+wPD`Hz8WF6xn!+BD?57nn0g+FJ*Rufp+rcVkIj2asY@Ju81;d>!7ns#H1 z;hg)O3!YA=MPGMj0oVF+u^|>O#s};A1$>>|&+dzO9dNN9x+08SSNrP%o=pVOyVx2J zmF<6-BMzu+U1x^+jN987hp?E>&o;K>Vb-{AZbMx+Vg6R-lQ;FTGsVR=rVpsFp?RN# zMKOioM&FpQfQprrD_Q_V^E)o!5558D)&Nr_*3J4Ne=OZ__4eFG_}qK}mI}i68K|bc zj3y#%-5;TJef0J)M(4v#wllu7A!UZ>U<_sg4LVJrb4Po^5oL4d;fNWt(m-r&K*Upg zt-XO0F4p}uGYq32Trlv8$pOEo(Tx#K#$ZOkmYKs9&c5!WIZj~k?!_Llfw8S4J`B_c z_hPbDg1E)OUSrOTpDPa^#P3VPU}_Jx2Ry}uZ%vrp;^_?qC06>0NQym!ofMC3NtbX( z6wdE}@Fk>8WUn_u!V>#h5w=x8stQmg3D=CO%=E2zRpUv z-Bk?Bd^mtuWs@zHIaO)~i~|=yA1T+MHVNS$wg-y$fjm?cRzhYk z!k=nf#M3W@PJ|eW5z|)2zqDEh8GE565W9H6KCh3DRT^DzO<`lATxoAIYq^-4Fbae*7%{ E0(zh;F#rGn literal 0 HcmV?d00001