graalpy: add graalpy early-access and windows builds
This commit is contained in:
parent
82c7e631bb
commit
fc9bcb4a04
|
@ -19,6 +19,7 @@ jobs:
|
|||
matrix:
|
||||
os: [macos-latest, ubuntu-20.04, ubuntu-latest]
|
||||
graalpy:
|
||||
- 'graalpy-24.0'
|
||||
- 'graalpy-23.0'
|
||||
- 'graalpy-22.3'
|
||||
|
||||
|
@ -87,14 +88,14 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup GraalPy and check latest
|
||||
uses: ./
|
||||
id: graalpy
|
||||
with:
|
||||
python-version: 'graalpy-23.x'
|
||||
python-version: 'graalpy-24.x'
|
||||
check-latest: true
|
||||
- name: GraalPy and Python version
|
||||
run: python --version
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,7 +10,7 @@ import * as path from 'path';
|
|||
import * as semver from 'semver';
|
||||
|
||||
import * as finder from '../src/find-graalpy';
|
||||
import {IGraalPyManifestRelease, IS_WINDOWS} from '../src/utils';
|
||||
import {IGraalPyManifestRelease} from '../src/utils';
|
||||
|
||||
import manifestData from './data/graalpy.json';
|
||||
|
||||
|
@ -19,9 +19,6 @@ const architecture = 'x64';
|
|||
const toolDir = path.join(__dirname, 'runner', 'tools');
|
||||
const tempDir = path.join(__dirname, 'runner', 'temp');
|
||||
|
||||
/* GraalPy doesn't have a windows release yet */
|
||||
const describeSkipOnWindows = IS_WINDOWS ? describe.skip : describe;
|
||||
|
||||
describe('parseGraalPyVersion', () => {
|
||||
it.each([
|
||||
['graalpy-23', '23'],
|
||||
|
@ -108,7 +105,7 @@ describe('findGraalPyToolCache', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describeSkipOnWindows('findGraalPyVersion', () => {
|
||||
describe('findGraalPyVersion', () => {
|
||||
let getBooleanInputSpy: jest.SpyInstance;
|
||||
let warningSpy: jest.SpyInstance;
|
||||
let debugSpy: jest.SpyInstance;
|
||||
|
@ -358,13 +355,13 @@ describeSkipOnWindows('findGraalPyVersion', () => {
|
|||
it('found and install successfully, pre-release fallback', async () => {
|
||||
spyCacheDir = jest.spyOn(tc, 'cacheDir');
|
||||
spyCacheDir.mockImplementation(() =>
|
||||
path.join(toolDir, 'GraalPy', '23.1', architecture)
|
||||
path.join(toolDir, 'GraalPy', '24.1', architecture)
|
||||
);
|
||||
spyChmodSync = jest.spyOn(fs, 'chmodSync');
|
||||
spyChmodSync.mockImplementation(() => undefined);
|
||||
await expect(
|
||||
finder.findGraalPyVersion(
|
||||
'graalpy23.1',
|
||||
'graalpy24.1',
|
||||
architecture,
|
||||
false,
|
||||
false,
|
||||
|
@ -372,7 +369,7 @@ describeSkipOnWindows('findGraalPyVersion', () => {
|
|||
)
|
||||
).rejects.toThrow();
|
||||
await expect(
|
||||
finder.findGraalPyVersion('graalpy23.1', architecture, false, false, true)
|
||||
).resolves.toEqual('23.1.0-a.1');
|
||||
finder.findGraalPyVersion('graalpy24.1', architecture, false, false, true)
|
||||
).resolves.toEqual('24.1.0-ea.9');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -21,24 +21,21 @@ const architecture = 'x64';
|
|||
const toolDir = path.join(__dirname, 'runner', 'tools');
|
||||
const tempDir = path.join(__dirname, 'runner', 'temp');
|
||||
|
||||
/* GraalPy doesn't have a windows release yet */
|
||||
const describeSkipOnWindows = IS_WINDOWS ? describe.skip : describe;
|
||||
|
||||
describe('graalpyVersionToSemantic', () => {
|
||||
it.each([
|
||||
['23.0.0a1', '23.0.0a1'],
|
||||
['23.0.0', '23.0.0'],
|
||||
['23.0.x', '23.0.x'],
|
||||
['23.x', '23.x']
|
||||
['graalpy-24.1.0-ea.09', '24.1.0-ea.9'],
|
||||
['graal-23.0.0', '23.0.0'],
|
||||
['vm-23.0.x', '23.0.x'],
|
||||
['graal-23.x', '23.x']
|
||||
])('%s -> %s', (input, expected) => {
|
||||
expect(installer.graalPyTagToVersion(input)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describeSkipOnWindows('findRelease', () => {
|
||||
describe('findRelease', () => {
|
||||
const result = JSON.stringify(manifestData);
|
||||
const releases = JSON.parse(result) as IGraalPyManifestRelease[];
|
||||
const extension = 'tar.gz';
|
||||
const extension = IS_WINDOWS ? 'zip' : 'tar.gz';
|
||||
const arch = installer.toGraalPyArchitecture(architecture);
|
||||
const platform = installer.toGraalPyPlatform(process.platform);
|
||||
const extensionName = `${platform}-${arch}.${extension}`;
|
||||
|
@ -47,8 +44,8 @@ describeSkipOnWindows('findRelease', () => {
|
|||
browser_download_url: `https://github.com/oracle/graalpython/releases/download/graal-23.0.0/graalpython-23.0.0-${extensionName}`
|
||||
};
|
||||
const filesRC1: IGraalPyManifestAsset = {
|
||||
name: `graalpython-23.1.0a1-${extensionName}`,
|
||||
browser_download_url: `https://github.com/oracle/graalpython/releases/download/graal-23.1.0a1/graalpython-23.1.0a1-${extensionName}`
|
||||
name: `graalpy-24.1.0-ea.09-${extensionName}`,
|
||||
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}`
|
||||
};
|
||||
|
||||
let warningSpy: jest.SpyInstance;
|
||||
|
@ -84,15 +81,15 @@ describeSkipOnWindows('findRelease', () => {
|
|||
});
|
||||
|
||||
it('Preview version of GraalPy is found', () => {
|
||||
const graalpyVersion = installer.graalPyTagToVersion('vm-23.1.0a1');
|
||||
const graalpyVersion = installer.graalPyTagToVersion('vm-24.1.0-ea.09');
|
||||
expect(
|
||||
installer.findRelease(releases, graalpyVersion, architecture, false)
|
||||
).toMatchObject({
|
||||
foundAsset: {
|
||||
name: `graalpython-23.1.0a1-${extensionName}`,
|
||||
browser_download_url: `https://github.com/oracle/graalpython/releases/download/graal-23.1.0a1/graalpython-23.1.0a1-${extensionName}`
|
||||
name: `graalpy-24.1.0-ea.09-${extensionName}`,
|
||||
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}`
|
||||
},
|
||||
resolvedGraalPyVersion: '23.1.0-a.1'
|
||||
resolvedGraalPyVersion: '24.1.0-ea.9'
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -107,7 +104,7 @@ describeSkipOnWindows('findRelease', () => {
|
|||
});
|
||||
|
||||
it('GraalPy version matches semver (pre-release)', () => {
|
||||
const graalpyVersion = '23.1.x';
|
||||
const graalpyVersion = '24.1.x';
|
||||
expect(
|
||||
installer.findRelease(releases, graalpyVersion, architecture, false)
|
||||
).toBeNull();
|
||||
|
@ -115,12 +112,12 @@ describeSkipOnWindows('findRelease', () => {
|
|||
installer.findRelease(releases, graalpyVersion, architecture, true)
|
||||
).toMatchObject({
|
||||
foundAsset: filesRC1,
|
||||
resolvedGraalPyVersion: '23.1.0-a.1'
|
||||
resolvedGraalPyVersion: '24.1.0-ea.9'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describeSkipOnWindows('installGraalPy', () => {
|
||||
describe('installGraalPy', () => {
|
||||
let tcFind: jest.SpyInstance;
|
||||
let warningSpy: jest.SpyInstance;
|
||||
let debugSpy: jest.SpyInstance;
|
||||
|
@ -232,20 +229,20 @@ describeSkipOnWindows('installGraalPy', () => {
|
|||
it('found and install GraalPy, pre-release fallback', async () => {
|
||||
spyCacheDir = jest.spyOn(tc, 'cacheDir');
|
||||
spyCacheDir.mockImplementation(() =>
|
||||
path.join(toolDir, 'GraalPy', '23.1.0', architecture)
|
||||
path.join(toolDir, 'GraalPy', '24.1.0', architecture)
|
||||
);
|
||||
|
||||
spyChmodSync = jest.spyOn(fs, 'chmodSync');
|
||||
spyChmodSync.mockImplementation(() => undefined);
|
||||
|
||||
await expect(
|
||||
installer.installGraalPy('23.1.x', architecture, false, undefined)
|
||||
installer.installGraalPy('24.1.x', architecture, false, undefined)
|
||||
).rejects.toThrow();
|
||||
await expect(
|
||||
installer.installGraalPy('23.1.x', architecture, true, undefined)
|
||||
installer.installGraalPy('24.1.x', architecture, true, undefined)
|
||||
).resolves.toEqual({
|
||||
installDir: path.join(toolDir, 'GraalPy', '23.1.0', architecture),
|
||||
resolvedGraalPyVersion: '23.1.0-a.1'
|
||||
installDir: path.join(toolDir, 'GraalPy', '24.1.0', architecture),
|
||||
resolvedGraalPyVersion: '24.1.0-ea.9'
|
||||
});
|
||||
|
||||
expect(spyHttpClient).toHaveBeenCalled();
|
||||
|
|
|
@ -90521,8 +90521,8 @@ function findGraalPyVersion(versionSpec, architecture, updateEnvironment, checkL
|
|||
const pipDir = utils_1.IS_WINDOWS ? 'Scripts' : 'bin';
|
||||
const _binDir = path.join(installDir, pipDir);
|
||||
const binaryExtension = utils_1.IS_WINDOWS ? '.exe' : '';
|
||||
const pythonPath = path.join(utils_1.IS_WINDOWS ? installDir : _binDir, `python${binaryExtension}`);
|
||||
const pythonLocation = (0, utils_1.getBinaryDirectory)(installDir);
|
||||
const pythonPath = path.join(_binDir, `python${binaryExtension}`);
|
||||
const pythonLocation = path.join(installDir, 'bin');
|
||||
if (updateEnvironment) {
|
||||
core.exportVariable('pythonLocation', installDir);
|
||||
// https://cmake.org/cmake/help/latest/module/FindPython.html#module:FindPython
|
||||
|
@ -90994,7 +90994,12 @@ function installGraalPy(graalpyVersion, architecture, allowPreReleases, releases
|
|||
try {
|
||||
const graalpyPath = yield tc.downloadTool(downloadUrl, undefined, AUTH);
|
||||
core.info('Extracting downloaded archive...');
|
||||
if (utils_1.IS_WINDOWS) {
|
||||
downloadDir = yield tc.extractZip(graalpyPath);
|
||||
}
|
||||
else {
|
||||
downloadDir = yield tc.extractTar(graalpyPath);
|
||||
}
|
||||
// root folder in archive can have unpredictable name so just take the first folder
|
||||
// downloadDir is unique folder under TEMP and can't contain any other folders
|
||||
const archiveName = fs_1.default.readdirSync(downloadDir)[0];
|
||||
|
@ -91003,7 +91008,7 @@ function installGraalPy(graalpyVersion, architecture, allowPreReleases, releases
|
|||
if (!(0, utils_1.isNightlyKeyword)(resolvedGraalPyVersion)) {
|
||||
installDir = yield tc.cacheDir(toolDir, 'GraalPy', resolvedGraalPyVersion, architecture);
|
||||
}
|
||||
const binaryPath = (0, utils_1.getBinaryDirectory)(installDir);
|
||||
const binaryPath = path.join(installDir, 'bin');
|
||||
yield createGraalPySymlink(binaryPath, resolvedGraalPyVersion);
|
||||
yield installPip(binaryPath);
|
||||
return { installDir, resolvedGraalPyVersion };
|
||||
|
@ -91034,6 +91039,9 @@ function getAvailableGraalPyVersions() {
|
|||
if (AUTH) {
|
||||
headers.authorization = AUTH;
|
||||
}
|
||||
/*
|
||||
Get releases first.
|
||||
*/
|
||||
let url = 'https://api.github.com/repos/oracle/graalpython/releases';
|
||||
const result = [];
|
||||
do {
|
||||
|
@ -91044,6 +91052,19 @@ function getAvailableGraalPyVersions() {
|
|||
result.push(...response.result);
|
||||
url = (0, utils_1.getNextPageUrl)(response);
|
||||
} while (url);
|
||||
/*
|
||||
Add pre-release builds.
|
||||
*/
|
||||
url =
|
||||
'https://api.github.com/repos/graalvm/graal-languages-ea-builds/releases';
|
||||
do {
|
||||
const response = yield http.getJson(url, headers);
|
||||
if (!response.result) {
|
||||
throw new Error(`Unable to retrieve the list of available GraalPy versions from '${url}'`);
|
||||
}
|
||||
result.push(...response.result);
|
||||
url = (0, utils_1.getNextPageUrl)(response);
|
||||
} while (url);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
@ -91069,7 +91090,7 @@ function installPip(pythonLocation) {
|
|||
});
|
||||
}
|
||||
function graalPyTagToVersion(tag) {
|
||||
const versionPattern = /.*-(\d+\.\d+\.\d+(?:\.\d+)?)((?:a|b|rc))?(\d*)?/;
|
||||
const versionPattern = /.*-(\d+\.\d+\.\d+(?:\.\d+)?)(?:-((?:ea|a|b|rc))\.0*(\d*))?/;
|
||||
const match = tag.match(versionPattern);
|
||||
if (match && match[2]) {
|
||||
return `${match[1]}-${match[2]}.${match[3]}`;
|
||||
|
@ -91123,8 +91144,9 @@ exports.toGraalPyArchitecture = toGraalPyArchitecture;
|
|||
function findAsset(item, architecture, platform) {
|
||||
const graalpyArch = toGraalPyArchitecture(architecture);
|
||||
const graalpyPlatform = toGraalPyPlatform(platform);
|
||||
const graalpyExt = platform == 'win32' ? 'zip' : 'tar.gz';
|
||||
const found = item.assets.filter(file => file.name.startsWith('graalpy') &&
|
||||
file.name.endsWith(`-${graalpyPlatform}-${graalpyArch}.tar.gz`));
|
||||
file.name.endsWith(`-${graalpyPlatform}-${graalpyArch}.${graalpyExt}`));
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
@ -91937,7 +91959,7 @@ function getVersionInputFromFile(versionFile) {
|
|||
}
|
||||
exports.getVersionInputFromFile = getVersionInputFromFile;
|
||||
/**
|
||||
* Get the directory containing interpreter binary from installation directory of PyPy or GraalPy
|
||||
* Get the directory containing interpreter binary from installation directory of PyPy
|
||||
* - On Linux and macOS, the Python interpreter is in 'bin'.
|
||||
* - On Windows, it is in the installation root.
|
||||
*/
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
import * as path from 'path';
|
||||
import * as graalpyInstall from './install-graalpy';
|
||||
import {
|
||||
IS_WINDOWS,
|
||||
validateVersion,
|
||||
IGraalPyManifestRelease,
|
||||
getBinaryDirectory
|
||||
} from './utils';
|
||||
import {IS_WINDOWS, validateVersion, IGraalPyManifestRelease} from './utils';
|
||||
|
||||
import * as semver from 'semver';
|
||||
import * as core from '@actions/core';
|
||||
|
@ -62,11 +57,8 @@ export async function findGraalPyVersion(
|
|||
const pipDir = IS_WINDOWS ? 'Scripts' : 'bin';
|
||||
const _binDir = path.join(installDir, pipDir);
|
||||
const binaryExtension = IS_WINDOWS ? '.exe' : '';
|
||||
const pythonPath = path.join(
|
||||
IS_WINDOWS ? installDir : _binDir,
|
||||
`python${binaryExtension}`
|
||||
);
|
||||
const pythonLocation = getBinaryDirectory(installDir);
|
||||
const pythonPath = path.join(_binDir, `python${binaryExtension}`);
|
||||
const pythonLocation = path.join(installDir, 'bin');
|
||||
if (updateEnvironment) {
|
||||
core.exportVariable('pythonLocation', installDir);
|
||||
// https://cmake.org/cmake/help/latest/module/FindPython.html#module:FindPython
|
||||
|
|
|
@ -15,7 +15,6 @@ import {
|
|||
IGraalPyManifestRelease,
|
||||
createSymlinkInFolder,
|
||||
isNightlyKeyword,
|
||||
getBinaryDirectory,
|
||||
getNextPageUrl
|
||||
} from './utils';
|
||||
|
||||
|
@ -64,7 +63,11 @@ export async function installGraalPy(
|
|||
const graalpyPath = await tc.downloadTool(downloadUrl, undefined, AUTH);
|
||||
|
||||
core.info('Extracting downloaded archive...');
|
||||
if (IS_WINDOWS) {
|
||||
downloadDir = await tc.extractZip(graalpyPath);
|
||||
} else {
|
||||
downloadDir = await tc.extractTar(graalpyPath);
|
||||
}
|
||||
|
||||
// root folder in archive can have unpredictable name so just take the first folder
|
||||
// downloadDir is unique folder under TEMP and can't contain any other folders
|
||||
|
@ -81,7 +84,7 @@ export async function installGraalPy(
|
|||
);
|
||||
}
|
||||
|
||||
const binaryPath = getBinaryDirectory(installDir);
|
||||
const binaryPath = path.join(installDir, 'bin');
|
||||
await createGraalPySymlink(binaryPath, resolvedGraalPyVersion);
|
||||
await installPip(binaryPath);
|
||||
|
||||
|
@ -115,6 +118,9 @@ export async function getAvailableGraalPyVersions() {
|
|||
headers.authorization = AUTH;
|
||||
}
|
||||
|
||||
/*
|
||||
Get releases first.
|
||||
*/
|
||||
let url: string | null =
|
||||
'https://api.github.com/repos/oracle/graalpython/releases';
|
||||
const result: IGraalPyManifestRelease[] = [];
|
||||
|
@ -130,6 +136,23 @@ export async function getAvailableGraalPyVersions() {
|
|||
url = getNextPageUrl(response);
|
||||
} while (url);
|
||||
|
||||
/*
|
||||
Add pre-release builds.
|
||||
*/
|
||||
url =
|
||||
'https://api.github.com/repos/graalvm/graal-languages-ea-builds/releases';
|
||||
do {
|
||||
const response: ifm.TypedResponse<IGraalPyManifestRelease[]> =
|
||||
await http.getJson(url, headers);
|
||||
if (!response.result) {
|
||||
throw new Error(
|
||||
`Unable to retrieve the list of available GraalPy versions from '${url}'`
|
||||
);
|
||||
}
|
||||
result.push(...response.result);
|
||||
url = getNextPageUrl(response);
|
||||
} while (url);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -175,7 +198,8 @@ async function installPip(pythonLocation: string) {
|
|||
}
|
||||
|
||||
export function graalPyTagToVersion(tag: string) {
|
||||
const versionPattern = /.*-(\d+\.\d+\.\d+(?:\.\d+)?)((?:a|b|rc))?(\d*)?/;
|
||||
const versionPattern =
|
||||
/.*-(\d+\.\d+\.\d+(?:\.\d+)?)(?:-((?:ea|a|b|rc))\.0*(\d*))?/;
|
||||
const match = tag.match(versionPattern);
|
||||
if (match && match[2]) {
|
||||
return `${match[1]}-${match[2]}.${match[3]}`;
|
||||
|
@ -251,10 +275,11 @@ export function findAsset(
|
|||
) {
|
||||
const graalpyArch = toGraalPyArchitecture(architecture);
|
||||
const graalpyPlatform = toGraalPyPlatform(platform);
|
||||
const graalpyExt = platform == 'win32' ? 'zip' : 'tar.gz';
|
||||
const found = item.assets.filter(
|
||||
file =>
|
||||
file.name.startsWith('graalpy') &&
|
||||
file.name.endsWith(`-${graalpyPlatform}-${graalpyArch}.tar.gz`)
|
||||
file.name.endsWith(`-${graalpyPlatform}-${graalpyArch}.${graalpyExt}`)
|
||||
);
|
||||
/*
|
||||
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.
|
||||
|
|
|
@ -281,7 +281,7 @@ export function getVersionInputFromFile(versionFile: string): string[] {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the directory containing interpreter binary from installation directory of PyPy or GraalPy
|
||||
* Get the directory containing interpreter binary from installation directory of PyPy
|
||||
* - On Linux and macOS, the Python interpreter is in 'bin'.
|
||||
* - On Windows, it is in the installation root.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue