diff --git a/.github/workflows/e2e-versions.yml b/.github/workflows/e2e-versions.yml index 9bd6dadd1..e8bb2d2e6 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 84429bd1a..b1942bc3d 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 4b4a3c0d8..9e2825e87 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 e23c972b1..a36393a85 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: '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' }], - [{ version: '11.0.7', architecture: 'x64', packageType: 'jre' }] + [{ 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 c3b085bfa..c1618971b 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 fe5958a92..666cd90d2 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 406ad3a3e..5ba822884 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 ca595b1bb..be25b9b22 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 28da6b311..f329f2d56 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 c78ca6811..214005e0c 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 99c8351c5..63d748abf 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 6f1312c7a..9c9ea3a3d 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 d7a7af760..82344d585 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 1641b7822..92a861979 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);