8000 graalpy: add graalpy early-access and windows builds · actions/setup-python@fc9bcb4 · GitHub
[go: up one dir, main page]

Skip to content

Commit fc9bcb4

Browse files
committed
graalpy: add graalpy early-access and windows builds
1 parent 82c7e63 commit fc9bcb4

File tree

8 files changed

+1562
-1608
lines changed

8 files changed

+1562
-1608
lines changed

.github/workflows/test-graalpy.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
matrix:
2020
os: [macos-latest, ubuntu-20.04, ubuntu-latest]
2121
graalpy:
22+
- 'graalpy-24.0'
2223
- 'graalpy-23.0'
2324
- 'graalpy-22.3'
2425

@@ -87,14 +88,14 @@ jobs:
8788
strategy:
8889
fail-fast: false
8990
matrix:
90-
os: [ubuntu-latest, macos-latest]
91+
os: [ubuntu-latest, windows-latest, macos-latest]
9192
steps:
9293
- uses: actions/checkout@v4
9394
- name: Setup GraalPy and check latest
9495
uses: ./
9596
id: graalpy
9697
with:
97-
python-version: 'graalpy-23.x'
98+
python-version: 'graalpy-24.x'
9899
check-latest: true
99100
- name: GraalPy and Python version
100101
run: python --version

__tests__/data/graalpy.json

Lines changed: 1470 additions & 1550 deletions
Large diffs are not rendered by default.

__tests__/find-graalpy.test.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import * as path from 'path';
1010
import * as semver from 'semver';
1111

1212
import * as finder from '../src/find-graalpy';
13-
import {IGraalPyManifestRelease, IS_WINDOWS} from '../src/utils';
13+
import {IGraalPyManifestRelease} from '../src/utils';
1414

1515
import manifestData from './data/graalpy.json';
1616

@@ -19,9 +19,6 @@ const architecture = 'x64';
1919
const toolDir = path.join(__dirname, 'runner', 'tools');
2020
const tempDir = path.join(__dirname, 'runner', 'temp');
2121

22-
/* GraalPy doesn't have a windows release yet */
23-
const describeSkipOnWindows = IS_WINDOWS ? describe.skip : describe;
24-
2522 F438
describe('parseGraalPyVersion', () => {
2623
it.each([
2724
['graalpy-23', '23'],
@@ -108,7 +105,7 @@ describe('findGraalPyToolCache', () => {
108105
});
109106
});
110107

111-
describeSkipOnWindows('findGraalPyVersion', () => {
108+
describe('findGraalPyVersion', () => {
112109
let getBooleanInputSpy: jest.SpyInstance;
113110
let warningSpy: jest.SpyInstance;
114111
let debugSpy: jest.SpyInstance;
@@ -358,21 +355,21 @@ describeSkipOnWindows('findGraalPyVersion', () => {
358355
it('found and install successfully, pre-release fallback', async () => {
359356
spyCacheDir = jest.spyOn(tc, 'cacheDir');
360357
spyCacheDir.mockImplementation(() =>
361-
path.join(toolDir, 'GraalPy', '23.1', architecture)
358+
path.join(toolDir, 'GraalPy', '24.1', architecture)
362359
);
363360
spyChmodSync = jest.spyOn(fs, 'chmodSync');
364361
spyChmodSync.mockImplementation(() => undefined);
365362
await expect(
366363
finder.findGraalPyVersion(
367-
'graalpy23.1',
364+
'graalpy24.1',
368365
architecture,
369366
false,
370367
false,
371368
false
372369
)
373370
).rejects.toThrow();
374371
await expect(
375-
finder.findGraalPyVersion('graalpy23.1', architecture, false, false, true)
376-
).resolves.toEqual('23.1.0-a.1');
372+
finder.findGraalPyVersion('graalpy24.1', architecture, false, false, true)
373+
).resolves.toEqual('24.1.0-ea.9');
377374
});
378375
});

__tests__/install-graalpy.test.ts

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,21 @@ const architecture = 'x64';
2121
const toolDir = path.join(__dirname, 'runner', 'tools');
2222
const tempDir = path.join(__dirname, 'runner', 'temp');
2323

24-
/* GraalPy doesn't have a windows release yet */
25-
const describeSkipOnWindows = IS_WINDOWS ? describe.skip : describe;
26-
2724
describe('graalpyVersionToSemantic', () => {
2825
it.each([
29-
['23.0.0a1', '23.0.0a1'],
30-
['23.0.0', '23.0.0'],
31-
['23.0.x', '23.0.x'],
32-
['23.x', '23.x']
26+
['graalpy-24.1.0-ea.09', '24.1.0-ea.9'],
27+
['graal-23.0.0', '23.0.0'],
28+
['vm-23.0.x', '23.0.x'],
29+
['graal-23.x', '23.x']
3330
])('%s -> %s', (input, expected) => {
3431
expect(installer.graalPyTagToVersion(input)).toEqual(expected);
3532
});
3633
});
3734

38-
describeSkipOnWindows('findRelease', () => {
35+
describe('findRelease', () => {
3936
const result = JSON.stringify(manifestData);
4037
const releases = JSON.parse(result) as IGraalPyManifestRelease[];
41-
const extension = 'tar.gz';
38+
const extension = IS_WINDOWS ? 'zip' : 'tar.gz';
4239
const arch = installer.toGraalPyArchitecture(architecture);
4340
const platform = installer.toGraalPyPlatform(process.platform);
4441
const extensionName = `${platform}-${arch}.${extension}`;
@@ -47,8 +44,8 @@ describeSkipOnWindows('findRelease', () => {
4744
browser_download_url: `https://github.com/oracle/graalpython/releases/download/graal-23.0.0/graalpython-23.0.0-${extensionName}`
4845
};
4946
const filesRC1: IGraalPyManifestAsset = {
50-
name: `graalpython-23.1.0a1-${extensionName}`,
51-
browser_download_url: `https://github.com/oracle/graalpython/releases/download/graal-23.1.0a1/graalpython-23.1.0a1-${extensionName}`
47+
name: `graalpy-24.1.0-ea.09-${extensionName}`,
48+
browser_download_url: `https://github.com/graalvm/graal-languages-ea-builds/releases/download/graalpy-24.1.0-ea.09/graalpy-24.1.0-ea.09-${extensionName}`
5249
};
5350

5451
let warningSpy: jest.SpyInstance;
@@ -84,15 +81,15 @@ describeSkipOnWindows('findRelease', () => {
8481
});
8582

8683
it('Preview version of GraalPy is found', () => {
87-
const graalpyVersion = installer.graalPyTagToVersion('vm-23.1.0a1');
84+
const graalpyVersion = installer.graalPyTagToVersion('vm-24.1.0-ea.09');
8885
expect(
8986
installer.findRelease(releases, graalpyVersion, architecture, false)
9087
).toMatchObject({
9188
foundAsset: {
92-
name: `graalpython-23.1.0a1-${extensionName}`,
93-
browser_download_url: `https://github.com/oracle/graalpython/releases/download/graal-23.1.0a1/graalpython-23.1.0a1-${extensionName}`
89+
name: `graalpy-24.1.0-ea.09-${extensionName}`,
90+
browser_download_url: `https://github.com/graalvm/graal-languages-ea-builds/releases/download/graalpy-24.1.0-ea.09/graalpy-24.1.0-ea.09-${extensionName}`
9491
},
95-
resolvedGraalPyVersion: '23.1.0-a.1'
92+
resolvedGraalPyVersion: '24.1.0-ea.9'
9693
});
9794
});
9895

@@ -107,20 +104,20 @@ describeSkipOnWindows('findRelease', () => {
107104
});
108105

109106
it('GraalPy version matches semver (pre-release)', () => {
110-
const graalpyVersion = '23.1.x';
107+
const graalpyVersion = '24.1.x';
111108
expect(
112109
installer.findRelease(releases, graalpyVersion, architecture, false)
113110
).toBeNull();
114111
expect(
115112
installer.findRelease(releases, graalpyVersion, architecture, true)
116113
).toMatchObject({
117114
foundAsset: filesRC1,
118-
resolvedGraalPyVersion: '23.1.0-a.1'
115+
resolvedGraalPyVersion: '24.1.0-ea.9'
119116
});
120117
});
121118
});
122119

123-
describeSkipOnWindows('installGraalPy', () => {
120+
describe('installGraalPy', () => {
124121
let tcFind: jest.SpyInstance;
125122
let warningSpy: jest.SpyInstance;
126123
let debugSpy: jest.SpyInstance;
@@ -232,20 +229,20 @@ describeSkipOnWindows('installGraalPy', () => {
232229
it('found and install GraalPy, pre-release fallback', async () => {
233230
spyCacheDir = jest.spyOn(tc, 'cacheDir');
234231
spyCacheDir.mockImplementation(() =>
235-
path.join(toolDir, 'GraalPy', '23.1.0', architecture)
232+
path.join(toolDir, 'GraalPy', '24.1.0', architecture)
236233
);
237234

238235
spyChmodSync = jest.spyOn(fs, 'chmodSync');
239236
spyChmodSync.mockImplementation(() => undefined);
240237

241238
await expect(
242-
installer.installGraalPy('23.1.x', architecture, false, undefined)
239+
installer.installGraalPy('24.1.x', architecture, false, undefined)
243240
).rejects.toThrow();
244241
await expect(
245-
installer.installGraalPy('23.1.x', architecture, true, undefined)
242+
installer.installGraalPy('24.1.x', architecture, true, undefined)
246243
).resolves.toEqual({
247-
installDir: path.join(toolDir, 'GraalPy', '23.1.0', architecture),
248-
resolvedGraalPyVersion: '23.1.0-a.1'
244+
installDir: path.join(toolDir, 'GraalPy', '24.1.0', architecture),
245+
resolvedGraalPyVersion: '24.1.0-ea.9'
249246
});
250247

251248
expect(spyHttpClient).toHaveBeenCalled();

dist/setup/index.js

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90521,8 +90521,8 @@ function findGraalPyVersion(versionSpec, architecture, updateEnvironment, checkL
9052190521
const pipDir = utils_1.IS_WINDOWS ? 'Scripts' : 'bin';
9052290522
const _binDir = path.join(installDir, pipDir);
9052390523
const binaryExtension = utils_1.IS_WINDOWS ? '.exe' : '';
90524-
const pythonPath = path.join(utils_1.IS_WINDOWS ? installDir : _binDir, `python${binaryExtension}`);
90525-
const pythonLocation = (0, utils_1.getBinaryDirectory)(installDir);
90524+
const pythonPath = path.join(_binDir, `python${binaryExtension}`);
90525+
const pythonLocation = path.join(installDir, 'bin');
9052690526
if (updateEnvironment) {
9052790527
core.exportVariable('pythonLocation', installDir);
9052890528
// https://cmake.org/cmake/help/latest/module/FindPython.html#module:FindPython
@@ -90994,7 +90994,12 @@ function installGraalPy(graalpyVersion, architecture, allowPreReleases, releases
9099490994
try {
9099590995
const graalpyPath = yield tc.downloadTool(downloadUrl, undefined, AUTH);
9099690996
core.info('Extracting downloaded archive...');
90997-
downloadDir = yield tc.extractTar(graalpyPath);
90997+
if (utils_1.IS_WINDOWS) {
90998+
downloadDir = yield tc.extractZip(graalpyPath);
90999+
}
91000+
else {
91001+
downloadDir = yield tc.extractTar(graalpyPath);
91002+
}
9099891003
// root folder in archive can have unpredictable name so just take the first folder
9099991004
// downloadDir is unique folder under TEMP and can't contain any other folders
9100091005
const archiveName = fs_1.default.readdirSync(downloadDir)[0];
@@ -91003,7 +91008,7 @@ function installGraalPy(graalpyVersion, architecture, allowPreReleases, releases
9100391008
if (!(0, utils_1.isNightlyKeyword)(resolvedGraalPyVersion)) {
9100491009
installDir = yield tc.cacheDir(toolDir, 'GraalPy', resolvedGraalPyVersion, architecture);
9100591010
}
91006-
const binaryPath = (0, utils_1.getBinaryDirectory)(installDir);
91011+
const binaryPath = path.join(installDir, 'bin');
9100791012
yield createGraalPySymlink(binaryPath, resolvedGraalPyVersion);
9100891013
yield installPip(binaryPath);
9100991014
return { installDir, resolvedGraalPyVersion };
@@ -91034,6 +91039,9 @@ function getAvailableGraalPyVersions() {
9103491039
if (AUTH) {
9103591040
headers.authorization = AUTH;
9103691041
}
91042+
/*
91043+
Get releases first.
91044+
*/
9103791045
let url = 'https://api.github.com/repos/oracle/graalpython/releases';
9103891046
const result = [];
9103991047
do {
@@ -91044,6 +91052,19 @@ function getAvailableGraalPyVersions() {
9104491052
result.push(...response.result);
9104591053
url = (0, utils_1.getNextPageUrl)(response);
9104691054
} while (url);
91055+
/*
91056+
Add pre-release builds.
91057+
*/
91058+
url =
91059+
'https://api.github.com/repos/graalvm/graal-languages-ea-builds/releases';
91060+
do {
91061+
const response = yield http.getJson(url, headers);
91062+
if (!response.result) {
91063+
throw new Error(`Unable to retrieve the list of available GraalPy versions from '${url}'`);
91064+
}
91065+
result.push(...response.result);
91066+
url = (0, utils_1.getNextPageUrl)(response);
91067+
} while (url);
9104791068
return result;
9104891069
});
9104991070
}
@@ -91069,7 +91090,7 @@ function installPip(pythonLocation) {
9106991090
});
9107091091
}
9107191092
function graalPyTagToVersion(tag) {
91072-
const versionPattern = /.*-(\d+\.\d+\.\d+(?:\.\d+)?)((?:a|b|rc))?(\d*)?/;
91093+
const versionPattern = /.*-(\d+\.\d+\.\d+(?:\.\d+)?)(?:-((?:ea|a|b|rc))\.0*(\d*))?/;
9107391094
const match = tag.match(versionPattern);
9107491095
if (match && match[2]) {
9107591096
return `${match[1]}-${match[2]}.${match[3]}`;
@@ -91123,8 +91144,9 @@ exports.toGraalPyArchitecture = toGraalPyArchitecture;
9112391144
function findAsset(item, architecture, platform) {
9112491145
const graalpyArch = toGraalPyArchitecture(architecture);
9112591146
const graalpyPlatform = toGraalPyPlatform(platform);
91147+
const graalpyExt = platform == 'win32' ? 'zip' : 'tar.gz';
9112691148
const found = item.assets.filter(file => file.name.startsWith('graalpy') &&
91127-
file.name.endsWith(`-${graalpyPlatform}-${graalpyArch}.tar.gz`));
91149+
file.name.endsWith(`-${graalpyPlatform}-${graalpyArch}.${graalpyExt}`));
9112891150
/*
9112991151
In the future there could be more variants of GraalPy for a single release. Pick the shortest name, that one is the most likely to be the primary variant.
9113091152
*/
@@ -91937,7 +91959,7 @@ function getVersionInputFromFile(versionFile) {
9193791959
}
9193891960
exports.getVersionInputFromFile = getVersionInputFromFile;
9193991961
/**
91940-
* Get the directory containing interpreter binary from installation directory of PyPy or GraalPy
91962+
* Get the directory containing interpreter binary from installation directory of PyPy
9194191963
* - On Linux and macOS, the Python interpreter is in 'bin'.
9194291964
* - On Windows, it is in the installation root.
9194391965
*/

src/find-graalpy.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
import * as path from 'path';
22
import * as graalpyInstall from './install-graalpy';
3-
import {
4-
IS_WINDOWS,
5-
validateVersion,
6-
IGraalPyManifestRelease,
7-
getBinaryDirectory
8-
} from './utils';
3+
import {IS_WINDOWS, validateVersion, IGraalPyManifestRelease} from './utils';
94

105
import * as semver from 'semver';
116
import * as core from '@actions/core';
@@ -62,11 +57,8 @@ export async function findGraalPyVersion(
6257
const pipDir = IS_WINDOWS ? 'Scripts' : 'bin';
6358
const _binDir = path.join(installDir, pipDir);
6459
const binaryExtension = IS_WINDOWS ? '.exe' : '';
65-
const pythonPath = path.join(
66-
IS_WINDOWS ? installDir : _binDir,
67-
`python${binaryExtension}`
68-
);
69-
const pythonLocation = getBinaryDirectory(installDir);
60+
const pythonPath = path.join(_binDir, `python${binaryExtension}`);
61+
const pythonLocation = path.join(installDir, 'bin');
7062
if (updateEnvironment) {
7163
core.exportVariable('pythonLocation', installDir);
7264
// https://cmake.org/cmake/help/latest/module/FindPython.html#module:FindPython

src/install-graalpy.ts

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import {
1515
IGraalPyManifestRelease,
1616
createSymlinkInFolder,
1717
isNightlyKeyword,
18-
getBinaryDirectory,
1918
getNextPageUrl
2019
} from './utils';
2120

@@ -64,7 +63,11 @@ export async function installGraalPy(
6463
const graalpyPath = await tc.downloadTool(downloadUrl, undefined, AUTH);
6564

6665
core.info('Extracting downloaded archive...');
67-
downloadDir = await tc.extractTar(graalpyPath);
66+
if (IS_WINDO 10000 WS) {
67+
downloadDir = await tc.extractZip(graalpyPath);
68+
} else {
69+
downloadDir = await tc.extractTar(graalpyPath);
70+
}
6871

6972
// root folder in archive can have unpredictable name so just take the first folder
7073
// downloadDir is unique folder under TEMP and can't contain any other folders
@@ -81,7 +84,7 @@ export async function installGraalPy(
8184
);
8285
}
8386

84-
const binaryPath = getBinaryDirectory(installDir);
87+
const binaryPath = path.join(installDir, 'bin');
8588
await createGraalPySymlink(binaryPath, resolvedGraalPyVersion);
8689
await installPip(binaryPath);
8790

@@ -115,6 +118,9 @@ export async function getAvailableGraalPyVersions() {
115118
headers.authorization = AUTH;
116119
}
117120

121+
/*
122+
Get releases first.
123+
*/
118124
let url: string | null =
119125
'https://api.github.com/repos/oracle/graalpython/releases';
120126
const result: IGraalPyManifestRelease[] = [];
@@ -130,6 +136,23 @@ export async function getAvailableGraalPyVersions() {
130136
url = getNextPageUrl(response);
131137
} while (url);
132138

139+
/*
140+
Add pre-release builds.
141+
*/
142+
url =
143+
'https://api.github.com/repos/graalvm/graal-languages-ea-builds/releases';
144+
do {
145+
const response: ifm.TypedResponse<IGraalPyManifestRelease[]> =
146+
await http.getJson(url, headers);
147+
if (!response.result) {
148+
throw new Error(
149+
`Unable to retrieve the list of available GraalPy versions from '${url}'`
150+
);
151+
}
152+
result.push(...response.result);
153+
url = getNextPageUrl(response);
154+
} while (url);
155+
133156
return result;
134157
}
135158

@@ -175,7 +198,8 @@ async function installPip(pythonLocation: string) {
175198
}
176199

177200
export function graalPyTagToVersion(tag: string) {
178-
const versionPattern = /.*-(\d+\.\d+\.\d+(?:\.\d+)?)((?:a|b|rc))?(\d*)?/;
201+
const versionPattern =
202+
/.*-(\d+\.\d+\.\d+(?:\.\d+)?)(?:-((?:ea|a|b|rc))\.0*(\d*))?/;
179203
const match = tag.match(versionPattern);
180204
if (match && match[2]) {
181205
return `${match[1]}-${match[2]}.${match[3]}`;
@@ -251,10 +275,11 @@ export function findAsset(
251275
) {
252276
const graalpyArch = toGraalPyArchitecture(architecture);
253277
const graalpyPlatform = toGraalPyPlatform(platform);
278+
const graalpyExt = platform == 'win32' ? 'zip' : 'tar.gz';
254279
const found = item.assets.filter(
255280
file =>
256281
file.name.startsWith('graalpy') &&
257-
file.name.endsWith(`-${graalpyPlatform}-${graalpyArch}.tar.gz`)
282+
file.name.endsWith(`-${graalpyPlatform}-${graalpyArch}.${graalpyExt}`)
258283
);
259284
/*
260285
In the future there could be more variants of GraalPy for a single release. Pick the shortest name, that one is the most likely to be the primary variant.

0 commit comments

Comments
 (0)
0