5
0
mirror of https://gitea.com/actions/setup-java.git synced 2026-08-07 02:31:20 +00:00

Add conditional JDK caching (#1201)

* Add JDK caching

Cache resolved JDK tool-cache entries by exact platform and release identity, with a default-on cache-jdk input and explicit opt-out.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Apply batched suggestions from code review

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Fix JDK cache CI validation

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Update brace-expansion security fix

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Refresh brace-expansion license metadata

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Refine JDK cache semantics

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Refine JDK cache documentation

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Simplify JDK cache identity

Use one normalized runner OS dimension, reset the internal cache key schema for the unreleased feature, and align documentation, tests, and bundles.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Align JDK cache OS identity

Use the established RUNNER_OS value directly and retain process.platform only as a non-Actions fallback.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Harden JDK cache saves and document tool-cache reuse

Bind each JDK cache key to the installation identity it was computed for,
keep post-job saves best-effort per entry, and state the real reuse and
verification guarantee in the documentation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* docs: restructure README caching section

Rename '## Caching dependencies' to '## Caching' and add a what-gets-cached
overview table covering the dependency, wrapper, and JDK caches. Lead with the
common 'cache: maven' example and the dependency-cache material, and demote JDK
caching into its own subsection.

Also corrects the IMPORTANT callout, which implied JDK caching required an
explicit opt-in; it is enabled implicitly whenever 'cache' is set.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* docs: fix caching documentation defects

- Remove pull-request framing that compared behavior to `main`; state the
  tool-cache and `jdkfile` behavior directly and unconditionally.
- Clarify that the JDK cache is a separate cache *entry* from the dependency
  and wrapper caches, while its *enablement* is coupled to `cache`, so the
  opening paragraph agrees with the enablement matrix.
- Cite the actions/setup-java-benchmarks repository instead of an open PR and
  a self-referential PR comment, keeping the measured figures and caveats.
- Keep the `cache`/`cache-jdk` matrix only in docs/advanced-usage.md and
  summarize the rules in prose in README.md to avoid divergence.
- Describe the guarantee that a cache key is only saved with the installation
  it was computed for, instead of documenting inode/size/timestamp internals.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* docs: add V6 what's new entry for JDK caching

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e2755464-4e83-47b6-ba71-731bb481b418

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot-Session: e2755464-4e83-47b6-ba71-731bb481b418
This commit is contained in:
Bruno Borges
2026-08-04 21:54:10 -04:00
committed by GitHub
parent 7a9a8b1dcc
commit 955f34f16f
26 changed files with 2756 additions and 827 deletions
+81 -3
View File
@@ -21,6 +21,7 @@ import {RetryingHttpClient} from '../retrying-http-client.js';
import os from 'os';
import {expectedDigestLength, verifyChecksum} from '../checksum.js';
import {normalizeArchitecture} from './platform-types.js';
import type {JdkCache} from '../jdk-cache.js';
export abstract class JavaBase {
protected http: httpm.HttpClient;
@@ -31,6 +32,7 @@ export abstract class JavaBase {
protected latest: boolean;
protected checkLatest: boolean;
protected forceDownload: boolean;
protected cacheJdk: boolean;
protected setDefault: boolean;
protected verifySignature: boolean;
protected verifySignaturePublicKey: string | undefined;
@@ -52,6 +54,7 @@ export abstract class JavaBase {
this.packageType = installerOptions.packageType;
this.checkLatest = installerOptions.checkLatest;
this.forceDownload = installerOptions.forceDownload ?? false;
this.cacheJdk = installerOptions.cacheJdk ?? false;
this.setDefault =
installerOptions.setDefault !== undefined
? installerOptions.setDefault
@@ -180,9 +183,48 @@ export abstract class JavaBase {
if (!this.forceDownload && 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`);
let jdkCache: JdkCache | undefined;
if (this.cacheJdk) {
const {getJdkVerificationIdentity} =
await import('../jdk-cache.js');
jdkCache = {
distribution: this.distribution,
packageType: this.packageType,
architecture: this.architecture,
version: javaRelease.version,
source: this.getJdkReleaseIdentity(javaRelease),
verification: getJdkVerificationIdentity(
this.verifySignature,
this.verifySignaturePublicKey
),
path: this.getJdkCachePath(javaRelease.version)
};
}
if (!this.forceDownload && jdkCache) {
const {restoreJdk} = await import('../jdk-cache.js');
const restored = await restoreJdk(jdkCache);
if (restored) {
const restoredPath = this.getRestoredJdkPath(javaRelease.version);
if (restoredPath) {
foundJava = {
version: javaRelease.version,
path: restoredPath
};
}
}
}
if (!foundJava || foundJava.version !== javaRelease.version) {
core.info('Trying to download...');
foundJava = await this.downloadTool(javaRelease);
core.info(`Java ${foundJava.version} was downloaded`);
if (jdkCache) {
// Register after the installation exists so its identity is
// captured; the post-job save refuses to upload a path whose
// installation was replaced afterwards.
const {registerJdk} = await import('../jdk-cache.js');
registerJdk(jdkCache);
}
}
}
} catch (error: any) {
this.logSetupError(error);
@@ -299,6 +341,42 @@ export abstract class JavaBase {
return version.replace('+', '-');
}
protected getJdkCachePath(version: string): string {
const toolCache = process.env['RUNNER_TOOL_CACHE'];
if (!toolCache) {
return '';
}
return path.join(
toolCache,
this.toolcacheFolderName,
this.getToolcacheVersionName(version)
);
}
protected getRestoredJdkPath(version: string): string | null {
const basePath = this.getJdkCachePath(version);
if (!basePath) {
return null;
}
const architecturePath = path.join(basePath, this.architecture);
return fs.existsSync(architecturePath) &&
fs.existsSync(`${architecturePath}.complete`)
? architecturePath
: null;
}
private getJdkReleaseIdentity(javaRelease: JavaDownloadRelease): string {
if (javaRelease.checksum) {
return `${javaRelease.checksum.algorithm}:${javaRelease.checksum.value}`;
}
try {
const url = new URL(javaRelease.url);
return `${url.origin}${url.pathname}`;
} catch {
return javaRelease.url;
}
}
protected findInToolcache(): JavaInstallerResults | null {
// we can't use tc.find directly because firstly, we need to filter versions by stability flag
// if *-ea is provided, take only ea versions from toolcache, otherwise - only stable versions