Skip to content

Commit 0173e6d

Browse files
brunoborgesCopilotCopilot
committed
Infer distribution from asdf .tool-versions vendor prefix (actions#1084)
* Infer distribution from asdf .tool-versions vendor prefix asdf-java encodes the JDK vendor as a prefix on the version string in .tool-versions (e.g. `java temurin-17.0.3+7`). Capture that prefix and map it to a setup-java distribution, mirroring the existing .sdkmanrc behavior. Unknown prefixes warn and fall back to the distribution input. Fixes actions#1081 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- 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> (cherry picked from commit 4db08ef)
1 parent f45cd82 commit 0173e6d

3 files changed

Lines changed: 157 additions & 2 deletions

File tree

‎__tests__/util.test.ts‎

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,72 @@ describe('getVersionFromFileContent', () => {
243243
);
244244
});
245245
});
246+
247+
describe('.tool-versions', () => {
248+
it.each([
249+
['java temurin-17.0.3+7', '17.0.3+7', 'temurin'],
250+
['java temurin-jre-17.0.3+7', '17.0.3+7', 'temurin'],
251+
['java adoptopenjdk-11.0.16+8', '11.0.16+8', 'temurin'],
252+
['java adoptopenjdk-openj9-11.0.16+8', '11.0.16+8', 'temurin'],
253+
['java zulu-11.56.19', '11.56.19', 'zulu'],
254+
['java corretto-17.0.13.11.1', '17', 'corretto'], // corretto -> major only
255+
['java liberica-11.0.15+10', '11.0.15+10', 'liberica'],
256+
['java microsoft-11.0.13.8.1', '11.0.13', 'microsoft'],
257+
['java semeru-openj9-11.0.25+9', '11.0.25+9', 'semeru'],
258+
['java ibm-openj9-11.0.25+9', '11.0.25+9', 'semeru'],
259+
['java dragonwell-17.0.13.0.13+11', '17.0.13', 'dragonwell'],
260+
['java graalvm-22.3.0+java17', '22.3.0+java17', 'graalvm'],
261+
['java graalvm-community-22.3.0', '22.3.0', 'graalvm-community'],
262+
['java oracle-graalvm-21.0.5', '21.0.5', 'graalvm'],
263+
['java oracle-21.0.5', '21.0.5', 'oracle'],
264+
['java sapmachine-21.0.5', '21.0.5', 'sapmachine'],
265+
['java kona-17.0.13', '17.0.13', 'kona'],
266+
['java jetbrains-21.0.5', '21.0.5', 'jetbrains']
267+
])(
268+
'parsing %s should return version %s and distribution %s',
269+
(content: string, expectedVersion: string, expectedDist: string) => {
270+
const actual = getVersionFromFileContent(
271+
content,
272+
'openjdk',
273+
'.tool-versions'
274+
);
275+
expect(actual?.version).toBe(expectedVersion);
276+
expect(actual?.distribution).toBe(expectedDist);
277+
}
278+
);
279+
280+
it.each([
281+
['java 17.0.7', '17.0.7'],
282+
['java 17', '17'],
283+
['java 1.8', '8'],
284+
['java 21-ea', '21-ea']
285+
])(
286+
'parsing prefix-less %s should return version %s and no distribution',
287+
(content: string, expectedVersion: string) => {
288+
const actual = getVersionFromFileContent(
289+
content,
290+
'temurin',
291+
'.tool-versions'
292+
);
293+
expect(actual?.version).toBe(expectedVersion);
294+
expect(actual?.distribution).toBeUndefined();
295+
}
296+
);
297+
298+
it('should warn and return undefined distribution for unsupported vendor', () => {
299+
const warnSpy = jest.spyOn(core, 'warning');
300+
const actual = getVersionFromFileContent(
301+
'java openjdk-17.0.7',
302+
'temurin',
303+
'.tool-versions'
304+
);
305+
expect(actual?.version).toBe('17.0.7');
306+
expect(actual?.distribution).toBeUndefined();
307+
expect(warnSpy).toHaveBeenCalledWith(
308+
expect.stringContaining('Unknown asdf distribution identifier')
309+
);
310+
});
311+
});
246312
});
247313

248314
describe('isGhes', () => {

‎docs/advanced-usage.md‎

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,27 @@ steps:
780780

781781
Supported files are `.java-version`, `.tool-versions` and `.sdkmanrc`.
782782
* In `.java-version` file, only the version should be specified (e.g., 17.0.7). The `.java-version` file recognizes all variants of the version description according to [jenv](https://github.com/jenv/jenv).
783-
* In `.tool-versions` file, java version should be preceded by the java keyword (e.g., java 17.0.7). The `.tool-versions` file supports version specifications in accordance with [asdf](https://github.com/asdf-vm/asdf) standards, adhering to Semantic Versioning ([semver](https://semver.org/)).
783+
* In `.tool-versions` file, java version should be preceded by the java keyword (e.g., java 17.0.7). The `.tool-versions` file supports version specifications in accordance with [asdf](https://github.com/asdf-vm/asdf) standards, adhering to Semantic Versioning ([semver](https://semver.org/)). When the entry includes an [asdf-java](https://github.com/halcyon/asdf-java) vendor prefix (e.g. `java temurin-17.0.3+7`), setup-java can infer the `distribution` input automatically. Unrecognized vendor prefixes require setting `distribution` explicitly.
784+
785+
Supported asdf-java vendor prefix mappings (packaging variants such as `-jre`, `-musl`, `-openj9`, `-crac`, `-javafx` are collapsed onto the base vendor):
786+
787+
| asdf-java vendor prefix | setup-java distribution |
788+
| ----------------------- | ----------------------- |
789+
| `temurin` | `temurin` |
790+
| `adoptopenjdk` | `temurin` |
791+
| `zulu` | `zulu` |
792+
| `corretto` | `corretto` |
793+
| `liberica` | `liberica` |
794+
| `microsoft` | `microsoft` |
795+
| `semeru`, `ibm` | `semeru` |
796+
| `dragonwell` | `dragonwell` |
797+
| `graalvm`, `oracle-graalvm` | `graalvm` |
798+
| `graalvm-community` | `graalvm-community` |
799+
| `oracle` | `oracle` |
800+
| `sapmachine` | `sapmachine` |
801+
| `kona` | `kona` |
802+
| `jetbrains` | `jetbrains` |
803+
784804
* In `.sdkmanrc` file, java version should be preceded by the `java=` prefix (e.g., `java=17.0.7-tem`). When a recognized SDKMAN distribution suffix is present, setup-java can infer the `distribution` input automatically. Unrecognized suffixes require setting `distribution` explicitly. The `.sdkmanrc` file supports version specifications in accordance with [file format](https://sdkman.io/usage#env-command), see [Sdkman! documentation](https://sdkman.io/jdks) for more information.
785805

786806
Supported SDKMAN suffix mappings:
@@ -816,6 +836,19 @@ steps:
816836
java=17.0.7-tem
817837
```
818838
839+
**Example step using `asdf`** (distribution inferred from `.tool-versions`):
840+
```yml
841+
- name: Setup java
842+
uses: actions/setup-java@v5
843+
with:
844+
java-version-file: '.tool-versions'
845+
```
846+
847+
**Example `.tool-versions`**:
848+
```
849+
java temurin-17.0.7+7
850+
```
851+
819852
Valid entry options (does not apply to `.sdkmanrc`):
820853
```
821854
major versions: 8, 11, 16, 17, 21

‎src/util.ts‎

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,10 @@ export function getVersionFromFileContent(
146146

147147
const versionFileName = getFileName(versionFile);
148148
if (versionFileName == '.tool-versions') {
149+
// Capture an optional asdf-java vendor prefix (e.g. `temurin-`, `corretto-`)
150+
// in the `distribution` group so it can be mapped to a setup-java distribution.
149151
javaVersionRegExp =
150-
/^java\s+(?:\S*-)?(?<version>\d+(?:\.\d+)*([+_.-](?:openj9[-._]?\d[\w.-]*|java\d+|jre[-_\w]*|OpenJDK\d+[\w_.-]*|[a-z0-9]+))*)/im;
152+
/^java\s+(?:(?<distribution>\S*)-)?(?<version>\d+(?:\.\d+)*([+_.-](?:openj9[-._]?\d[\w.-]*|java\d+|jre[-_\w]*|OpenJDK\d+[\w_.-]*|[a-z0-9]+))*)/im;
151153
} else if (versionFileName == '.sdkmanrc') {
152154
// Match both version and optional distribution identifier
153155
javaVersionRegExp =
@@ -170,6 +172,17 @@ export function getVersionFromFileContent(
170172
);
171173
}
172174

175+
// Extract distribution from asdf .tool-versions file
176+
if (versionFileName == '.tool-versions' && match?.groups?.distribution) {
177+
const asdfDist = match.groups.distribution;
178+
extractedDistribution = mapAsdfDistribution(asdfDist);
179+
if (extractedDistribution) {
180+
core.debug(
181+
`Parsed distribution '${extractedDistribution}' from asdf identifier '${asdfDist}'`
182+
);
183+
}
184+
}
185+
173186
core.debug(
174187
`Parsed version '${capturedVersion}' from file '${versionFileName}'`
175188
);
@@ -235,6 +248,49 @@ function mapSdkmanDistribution(sdkmanDist: string): string | undefined {
235248
return mapped;
236249
}
237250

251+
// Map asdf-java (.tool-versions) vendor identifiers to setup-java distribution names.
252+
// asdf-java encodes the vendor as a prefix on the version string, e.g.
253+
// `java temurin-17.0.3+7` or `java semeru-openj9-11.0.25+9`. Packaging variants
254+
// (`-jre`, `-musl`, `-openj9`, `-crac`, `-javafx`, ...) are collapsed onto the
255+
// base vendor since setup-java does not distinguish them here.
256+
function mapAsdfDistribution(asdfDist: string): string | undefined {
257+
const normalized = asdfDist.toLowerCase();
258+
259+
// Multi-segment vendors that map to a distinct setup-java distribution.
260+
if (normalized.startsWith('graalvm-community')) {
261+
return 'graalvm-community';
262+
}
263+
if (normalized.startsWith('oracle-graalvm')) {
264+
return 'graalvm';
265+
}
266+
267+
const baseVendor = normalized.split('-')[0];
268+
const distributionMap: Record<string, string> = {
269+
temurin: 'temurin',
270+
adoptopenjdk: 'temurin',
271+
zulu: 'zulu',
272+
corretto: 'corretto',
273+
liberica: 'liberica',
274+
microsoft: 'microsoft',
275+
semeru: 'semeru',
276+
ibm: 'semeru',
277+
dragonwell: 'dragonwell',
278+
graalvm: 'graalvm',
279+
oracle: 'oracle',
280+
sapmachine: 'sapmachine',
281+
kona: 'kona',
282+
jetbrains: 'jetbrains'
283+
};
284+
285+
const mapped = distributionMap[baseVendor];
286+
if (!mapped) {
287+
core.warning(
288+
`Unknown asdf distribution identifier '${asdfDist}'. Please specify the distribution explicitly.`
289+
);
290+
}
291+
return mapped;
292+
}
293+
238294
// By convention, action expects version 8 in the format `8.*` instead of `1.8`
239295
function avoidOldNotation(content: string): string {
240296
return content.startsWith('1.') ? content.substring(2) : content;

0 commit comments

Comments
 (0)