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>
This commit is contained in:
Bruno Borges
2026-07-09 17:19:16 -04:00
parent 28eade3106
commit da3bbf55d2
3 changed files with 40 additions and 6 deletions

View File

@@ -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` `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', () => { describe('createVersionNotFoundError', () => {

21
dist/setup/index.js vendored
View File

@@ -131274,13 +131274,22 @@ class JavaBase {
// Support the `latest` alias (case-insensitive), which floats to the newest // Support the `latest` alias (case-insensitive), which floats to the newest
// available stable/GA release. It is translated to the SemVer wildcard `x` // available stable/GA release. It is translated to the SemVer wildcard `x`
// so the existing "newest satisfying version wins" resolution applies. // so the existing "newest satisfying version wins" resolution applies.
if (version.trim().toLowerCase() === 'latest') { const normalized = version.trim().toLowerCase();
if (normalized === 'latest') {
return { return {
version: 'x', version: 'x',
stable: true, stable: true,
latest: 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')) { if (version.endsWith('-ea')) {
version = version.replace(/-ea$/, ''); version = version.replace(/-ea$/, '');
stable = false; stable = false;
@@ -132401,11 +132410,13 @@ class CorrettoDistribution extends JavaBase {
// matches on an exact major version, so resolve it to the newest available // matches on an exact major version, so resolve it to the newest available
// major from Corretto's own list. // major from Corretto's own list.
if (this.latest) { if (this.latest) {
const latestMajor = availableVersions const majors = availableVersions
.map(item => parseInt(item.version, 10)) .map(item => parseInt(item.version, 10))
.filter(major => !Number.isNaN(major)) .filter(major => Number.isFinite(major) && major > 0);
.reduce((max, current) => (current > max ? current : max), 0); if (majors.length === 0) {
version = latestMajor.toString(); throw new Error('Could not determine the latest available Corretto major version from remote metadata');
}
version = Math.max(...majors).toString();
} }
if (version.includes('.')) { if (version.includes('.')) {
throw new Error('Only major versions are supported'); throw new Error('Only major versions are supported');

View File

@@ -275,7 +275,8 @@ export abstract class JavaBase {
// Support the `latest` alias (case-insensitive), which floats to the newest // Support the `latest` alias (case-insensitive), which floats to the newest
// available stable/GA release. It is translated to the SemVer wildcard `x` // available stable/GA release. It is translated to the SemVer wildcard `x`
// so the existing "newest satisfying version wins" resolution applies. // so the existing "newest satisfying version wins" resolution applies.
if (version.trim().toLowerCase() === 'latest') { const normalized = version.trim().toLowerCase();
if (normalized === 'latest') {
return { return {
version: 'x', version: 'x',
stable: true, 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')) { if (version.endsWith('-ea')) {
version = version.replace(/-ea$/, ''); version = version.replace(/-ea$/, '');
stable = false; stable = false;