From da3bbf55d272afbaf4fa76603f81e835b2936b04 Mon Sep 17 00:00:00 2001 From: Bruno Borges Date: Thu, 9 Jul 2026 17:19:16 -0400 Subject: [PATCH] Give latest+qualifier inputs (e.g. latest-ea) a targeted error Inputs like 'latest-ea' had their '-ea' suffix stripped and fell through to the generic SemVer validation, failing with a confusing "'latest' is not valid SemVer" message even though 'latest' is supported. Add an explicit guard so any 'latest*' value other than exactly 'latest' throws a targeted error explaining that 'latest' resolves GA releases only and cannot be combined with '-ea' or other qualifiers. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- __tests__/distributors/base-installer.test.ts | 11 ++++++++++ dist/setup/index.js | 21 ++++++++++++++----- src/distributions/base-installer.ts | 14 ++++++++++++- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/__tests__/distributors/base-installer.test.ts b/__tests__/distributors/base-installer.test.ts index a3cef10c..ad3b0afc 100644 --- a/__tests__/distributors/base-installer.test.ts +++ b/__tests__/distributors/base-installer.test.ts @@ -793,6 +793,17 @@ describe('normalizeVersion', () => { `The string '${version}' is not valid SemVer notation for a Java version. Please check README file for code snippets and more detailed information` ); }); + + it.each(['latest-ea', 'latest.1', 'LATEST-EA', ' latest-ea '])( + 'normalizeVersion should throw a targeted error for latest combined with a qualifier (%s)', + version => { + expect( + DummyJavaBase.prototype.normalizeVersion.bind(null, version) + ).toThrow( + `The 'latest' alias resolves stable (GA) releases only and cannot be combined with '-ea' or other qualifiers (received '${version}'). Use 'latest' on its own, or specify a concrete version.` + ); + } + ); }); describe('createVersionNotFoundError', () => { diff --git a/dist/setup/index.js b/dist/setup/index.js index f6e21597..b3e2cb67 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -131274,13 +131274,22 @@ class JavaBase { // Support the `latest` alias (case-insensitive), which floats to the newest // available stable/GA release. It is translated to the SemVer wildcard `x` // so the existing "newest satisfying version wins" resolution applies. - if (version.trim().toLowerCase() === 'latest') { + const normalized = version.trim().toLowerCase(); + if (normalized === 'latest') { return { version: 'x', stable: true, latest: true }; } + // Reject `latest` combined with any qualifier (e.g. `latest-ea`). Such inputs + // would otherwise have their `-ea` suffix stripped and fall through to the + // generic SemVer check, which fails with a confusing "'latest' is not valid + // SemVer" message even though `latest` is a supported value. Fail early with a + // targeted explanation instead. + if (normalized.startsWith('latest')) { + throw new Error(`The 'latest' alias resolves stable (GA) releases only and cannot be combined with '-ea' or other qualifiers (received '${version}'). Use 'latest' on its own, or specify a concrete version.`); + } if (version.endsWith('-ea')) { version = version.replace(/-ea$/, ''); stable = false; @@ -132401,11 +132410,13 @@ class CorrettoDistribution extends JavaBase { // matches on an exact major version, so resolve it to the newest available // major from Corretto's own list. if (this.latest) { - const latestMajor = availableVersions + const majors = availableVersions .map(item => parseInt(item.version, 10)) - .filter(major => !Number.isNaN(major)) - .reduce((max, current) => (current > max ? current : max), 0); - version = latestMajor.toString(); + .filter(major => Number.isFinite(major) && major > 0); + if (majors.length === 0) { + throw new Error('Could not determine the latest available Corretto major version from remote metadata'); + } + version = Math.max(...majors).toString(); } if (version.includes('.')) { throw new Error('Only major versions are supported'); diff --git a/src/distributions/base-installer.ts b/src/distributions/base-installer.ts index 9ed68600..07e7c444 100644 --- a/src/distributions/base-installer.ts +++ b/src/distributions/base-installer.ts @@ -275,7 +275,8 @@ export abstract class JavaBase { // Support the `latest` alias (case-insensitive), which floats to the newest // available stable/GA release. It is translated to the SemVer wildcard `x` // so the existing "newest satisfying version wins" resolution applies. - if (version.trim().toLowerCase() === 'latest') { + const normalized = version.trim().toLowerCase(); + if (normalized === 'latest') { return { version: 'x', stable: true, @@ -283,6 +284,17 @@ export abstract class JavaBase { }; } + // Reject `latest` combined with any qualifier (e.g. `latest-ea`). Such inputs + // would otherwise have their `-ea` suffix stripped and fall through to the + // generic SemVer check, which fails with a confusing "'latest' is not valid + // SemVer" message even though `latest` is a supported value. Fail early with a + // targeted explanation instead. + if (normalized.startsWith('latest')) { + throw new Error( + `The 'latest' alias resolves stable (GA) releases only and cannot be combined with '-ea' or other qualifiers (received '${version}'). Use 'latest' on its own, or specify a concrete version.` + ); + } + if (version.endsWith('-ea')) { version = version.replace(/-ea$/, ''); stable = false;