Skip to content

Report concrete versions for floating Oracle JDK downloads - #1213

Merged
brunoborges merged 11 commits into
actions:mainfrom
jdubois:jdubois-fix-oracle-graalvm-floating-versions
Aug 5, 2026
Merged

brunoborges merged 11 commits into
actions:mainfrom
jdubois:jdubois-fix-oracle-graalvm-floating-versions

Conversation

@jdubois

@jdubois jdubois commented Aug 5, 2026 •

Copy link
Copy Markdown
Contributor

Closes #1212

Summary

  • derive the concrete Java patch/build version from the extracted JDK release metadata for Oracle JDK and Oracle GraalVM /latest/ downloads
  • force floating requests through remote artifact fingerprinting and never trust source-less tool-cache matches
  • bind concrete-version resolution and JDK-cache reuse to the authoritative artifact checksum; when no checksum is available, bypass floating caches and download safely
  • preserve exact-version and GraalVM Community behavior while adding regression and scheduled multi-platform E2E output coverage
  • regenerate all required dist/ bundles with the repository CI toolchain

Validation

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings August 5, 2026 13:13
@jdubois
jdubois requested a review from a team as a code owner August 5, 2026 13:13
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes Oracle JDK and Oracle GraalVM “floating” (/latest/) downloads reporting and caching only the requested major version by deriving the concrete installed patch/build from the extracted JDK release metadata, and by binding floating resolution reuse to an immutable artifact identity (checksum).

Changes:

  • Add getJavaVersionFromReleaseFile() to read/normalize the concrete Java version from the extracted JDK release file (including macOS Contents/Home layout).
  • For Oracle JDK and Oracle GraalVM /latest/ downloads, cache toolcache/JDK-cache entries under the concrete installed version and record floating resolution mappings keyed by authoritative artifact identity.
  • Update E2E + unit/regression tests to validate output correctness, cache identities, and behavior across successive floating artifacts.
Show a summary per file
File Description
src/util.ts Adds release-file parsing + normalization to derive concrete installed Java versions.
src/jdk-resolution-cache.ts Extends resolution identity to include immutable artifact identity (source) and persists floating safely.
src/distributions/oracle/installer.ts Uses release metadata for floating installs and forces major-only stable requests through remote resolution.
src/distributions/graalvm/installer.ts Same as Oracle JDK: concrete version from release file for floating installs + remote resolution for major-only Oracle GraalVM.
src/distributions/base-installer.ts Adds floating-resolution restore/register flow keyed by artifact identity and integrates concrete-version validation for floating downloads.
.github/workflows/e2e-versions.yml Extends E2E version verification to assert concrete output for floating Oracle/GraalVM major-only requests.
tests/verify-java.sh Adds checks ensuring action output version matches installed Java, and requires concreteness for floating cases.
tests/util-install.test.ts Adds unit coverage for release-file parsing/normalization including macOS layout.
tests/jdk-resolution-cache.test.ts Adds coverage that different floating artifact identities produce distinct cache keys.
tests/distributors/oracle-installer.test.ts Adds coverage for remote-resolution requirement (but currently contains a Jest structure bug).
tests/distributors/graalvm-installer.test.ts Adds coverage for concrete caching of floating artifacts and remote-resolution requirement.
tests/distributors/base-installer.test.ts Adds regression test ensuring two different floating artifacts under one major install/cache distinctly.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 12/19 changed files
  • Comments generated: 1
  • Review effort level: Lite
jdubois and others added 9 commits August 5, 2026 15:18
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Oracle and Oracle GraalVM do not always publish a `.sha256` sibling next
to a `/latest/` artifact. Those floating releases were excluded from both
the resolution cache and the JDK cache, so `cache-jdk` users lost caching
entirely for them.

A floating URL is a constant string, so it cannot serve as a cache
identity on its own — a stale entry would be reused forever. Instead,
derive a validator from the headers of the HEAD request that already
resolves the artifact: the ETag when present, otherwise `Last-Modified`
combined with `Content-Length`. Republishing changes the validator, which
changes the cache key, so a new build is downloaded rather than masked.

`getJdkReleaseIdentity` now falls back to that fingerprint before the
URL, and the floating cache gates ask whether the release has a stable
identity (checksum or fingerprint) rather than a checksum specifically. A
floating release with neither is still left uncached.

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

Copy link
Copy Markdown
Contributor

I pushed one commit to this branch (f733709) — hope that's alright, happy to drop it if you'd rather handle it separately.

Context: I had a parallel implementation of #1212 and compared the two. Yours is the better design — preferring JAVA_RUNTIME_VERSION over JAVA_VERSION picks up the build number (21.0.8+12 rather than 21.0.8), which matches what the other distributions report, and keying the resolution cache on the artifact checksum is much cleaner than what I had.

The one gap I wanted to close is the checksum-less case. Oracle and Oracle GraalVM don't always publish a .sha256 sibling next to a /latest/ artifact, and fetchChecksum returns undefined on a 404. Those releases were excluded from both the resolution cache and the JDK cache, so cache-jdk users lose caching entirely for them.

The naive fix — falling back to the URL identity — doesn't work: a /latest/ URL is a constant string, so the key would never invalidate and a stale JDK would be restored forever, which is exactly the bug this PR fixes. So the commit derives a validator from the HEAD response both installers already make:

  • getArtifactFingerprint(headers) in util.ts — ETag when present, otherwise Last-Modified + Content-Length together (neither alone is enough: one-second granularity, and a same-size rebuild). Returns undefined when the response carries no validator.
  • JavaDownloadRelease.fingerprint, set by the Oracle and GraalVM resolvers for floating releases only. No extra requests.
  • getJdkReleaseIdentity falls back to the fingerprint before the URL, and a new hasStableReleaseIdentity() replaces the four javaRelease.checksum gates. A floating release with neither checksum nor fingerprint is still left uncached, as before.

Republishing changes the validator, which changes the key, so a new build is downloaded rather than masked.

41 suites / 1340 tests pass, along with format-check, lint, and a dist/ rebuild. I checked the guard is load-bearing: reverting hasStableReleaseIdentity to checksum-only fails exactly the two new caching tests.

@brunoborges
brunoborges merged commit f4bfb3d into actions:main Aug 5, 2026
84 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants