From a83bf174b173dce6576312c64bcfec78601f54c3 Mon Sep 17 00:00:00 2001 From: Jeremy Tuloup Date: Sun, 22 Dec 2024 12:10:42 +0100 Subject: [PATCH] better handle pre-releases --- buildutils/package.json | 2 + buildutils/src/get-latest-lab-version.ts | 56 +++++++++++++++++++----- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/buildutils/package.json b/buildutils/package.json index f043a5a11b..e71a9dda84 100644 --- a/buildutils/package.json +++ b/buildutils/package.json @@ -32,11 +32,13 @@ "@jupyterlab/buildutils": "~4.4.0-alpha.1", "commander": "^6.2.0", "fs-extra": "^9.1.0", + "semver": "^7.5.4", "typescript": "~5.0.2" }, "devDependencies": { "@types/fs-extra": "^9.0.10", "@types/node": "^14.6.1", + "@types/semver": "^7.5.6", "rimraf": "^3.0.2" } } diff --git a/buildutils/src/get-latest-lab-version.ts b/buildutils/src/get-latest-lab-version.ts index 166e035a59..df8469e8e0 100644 --- a/buildutils/src/get-latest-lab-version.ts +++ b/buildutils/src/get-latest-lab-version.ts @@ -1,18 +1,46 @@ +import * as fs from 'fs-extra'; +import * as semver from 'semver'; + +function convertPythonVersion(version: string): string { + return version + .replace('a', '-alpha') + .replace('b', '-beta') + .replace('rc', '-rc'); +} + function extractVersionFromReleases( releases: any, - versionTag: string + versionTag: string, + currentVersion: string ): string | null { - for (const release of releases) { - const tagName: string = release['tag_name']; - if (versionTag === 'latest') { - if (!release['prerelease'] && !release['draft']) { - return tagName; - } - } else if (versionTag === tagName) { - return tagName; - } + const npmCurrentVersion = convertPythonVersion(currentVersion); + const isCurrentPreRelease = semver.prerelease(npmCurrentVersion) !== null; + + if (versionTag === 'latest') { + // Find first version that is newer than current and matches pre-release criteria + const release = releases.find((r: any) => { + const version = r['tag_name'].substring(1); // Remove 'v' prefix for semver + const npmVersion = convertPythonVersion(version); + return ( + (isCurrentPreRelease || !r['prerelease']) && + semver.gte(npmVersion, npmCurrentVersion) + ); + }); + return release ? release['tag_name'] : null; + } else { + // Find exact version match + const release = releases.find((r: any) => r['tag_name'] === versionTag); + return release ? release['tag_name'] : null; } - return null; +} + +function extractCurrentJupyterLabVersion(): string { + const toml = fs.readFileSync('pyproject.toml', 'utf8'); + const match = toml.match(/jupyterlab>=([^,]+)/); + if (!match) { + throw new Error('Could not find JupyterLab version in pyproject.toml'); + } + return match[1]; } async function findVersion(versionTag: string): Promise { @@ -22,10 +50,14 @@ async function findVersion(versionTag: string): Promise { const error_message = `Failed to fetch package.json from ${url}. HTTP status code: ${response.status}`; throw new Error(error_message); } + + const currentVersion = extractCurrentJupyterLabVersion(); + const releases: any = await response.json(); const version: string | null = extractVersionFromReleases( releases, - versionTag + versionTag, + currentVersion ); if (version === null) { const error_message = 'Invalid release tag';