[VSC] Codeflash version compatibility (CF-785) (#1933)

Co-authored-by: Sarthak Agarwal <sarthak.saga@gmail.com>
This commit is contained in:
mohammed ahmed 2025-11-01 01:11:46 +02:00 committed by GitHub
parent 9b7fd21962
commit 756f2abfcc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 101 additions and 20 deletions

View file

@ -6,9 +6,38 @@ on:
- 'js/VSC-Extension/**'
jobs:
check-min-version:
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Extract MIN_CODEFLASH_VERSION from constants file
id: extract-version
run: |
FILE="js/VSC-Extension/src/constants/cf_min_version.ts"
VERSION=$(grep -oP 'MIN_CODEFLASH_VERSION\s*=\s*"\K[^"]+' $FILE)
if [ -z "$VERSION" ]; then
echo "❌ Could not find MIN_CODEFLASH_VERSION in $FILE"
exit 1
fi
echo "✅ Found MIN_CODEFLASH_VERSION=$VERSION"
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Check version exists on PyPI
run: |
# Check if this version exists on PyPI
VERSION="${{ steps.extract-version.outputs.version }}"
if pip index versions codeflash | grep -q "Available versions: .*$VERSION"; then
echo "✅ Version $VERSION exists on PyPI."
else
echo "❌ Version $VERSION not found on PyPI"
exit 1
fi
build:
runs-on: ubuntu-latest
needs: check-min-version
steps:
- name: Checkout repository
uses: actions/checkout@v4
@ -17,7 +46,7 @@ jobs:
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
cache: "npm"
cache-dependency-path: js/VSC-Extension/package-lock.json
- name: Install dependencies

View file

@ -19,6 +19,7 @@
"marked": "^15.0.12",
"p-queue": "^8.1.0",
"posthog-node": "^5.10.1",
"semver": "^7.7.3",
"vscode-languageclient": "^9.0.1"
},
"devDependencies": {
@ -26,6 +27,7 @@
"@shikijs/themes": "^3.12.2",
"@types/mocha": "^10.0.10",
"@types/node": "20.x",
"@types/semver": "^7.7.1",
"@types/split2": "^4.2.3",
"@types/vscode": "^1.94.0",
"@typescript-eslint/eslint-plugin": "^8.25.0",
@ -2980,6 +2982,13 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/semver": {
"version": "7.7.1",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/shimmer": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz",
@ -11329,9 +11338,9 @@
}
},
"node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"version": "7.7.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"

View file

@ -126,6 +126,7 @@
"@shikijs/themes": "^3.12.2",
"@types/mocha": "^10.0.10",
"@types/node": "20.x",
"@types/semver": "^7.7.1",
"@types/split2": "^4.2.3",
"@types/vscode": "^1.94.0",
"@typescript-eslint/eslint-plugin": "^8.25.0",
@ -154,6 +155,7 @@
"marked": "^15.0.12",
"p-queue": "^8.1.0",
"posthog-node": "^5.10.1",
"semver": "^7.7.3",
"vscode-languageclient": "^9.0.1"
},
"private": true,

View file

@ -10,11 +10,15 @@ import { Logger } from "../utils";
import {
getBareRepoError,
getCodeflashNotInstalledError,
getCodeflashVersionIncompatibleError,
getCodeflashVersionNotValidError,
getNoGitRepoError,
getNoInitCommitError,
getPythonNotSelectedError,
GIT_ERRORS,
} from "./stepErrors";
import semver from "semver";
import { MIN_CODEFLASH_VERSION } from "../constants/cf_min_version";
const execPromise = promisify(exec);
@ -49,11 +53,15 @@ export class CheckEnvironmentStep extends BaseStep {
result.pythonPath = pythonPath;
const [gitError, codeflashInstalled] = await Promise.all([
const [gitError, installationError] = await Promise.all([
this.isGitUsedInRepo(),
this.isCodeflashInstalled(pythonPath),
this.checkCodeflashInstallation(pythonPath),
]);
if (installationError) {
return installationError;
}
if (gitError) {
const message = gitError.message as keyof typeof GIT_ERRORS;
if (message === GIT_ERRORS.NO_REPO) {
@ -64,11 +72,6 @@ export class CheckEnvironmentStep extends BaseStep {
return getNoInitCommitError();
}
}
if (!codeflashInstalled) {
// const isUvProject = await this.isUvProject();
const installCmd = `${pythonPath} -m pip install codeflash`;
return getCodeflashNotInstalledError(pythonPath, installCmd);
}
return result;
}
@ -139,22 +142,30 @@ export class CheckEnvironmentStep extends BaseStep {
};
};
private isCodeflashInstalled = async (
private checkCodeflashInstallation = async (
pythonPath: string,
): Promise<boolean> => {
const cmd = `${pythonPath} -c "import importlib.metadata as m; print(m.version('codeflash'))"`;
): Promise<InitStepError | undefined> => {
const cmd = `${pythonPath} -c "from codeflash.version import __version__ as v; print(v)"`;
try {
// TODO: from the stdout get the codeflash version and check if it's compatible
await execPromise(cmd);
return true;
const { stdout } = await execPromise(cmd);
const version = stdout.trim();
const semVer = semver.valid(version);
if (!semVer) {
return getCodeflashVersionNotValidError(pythonPath);
}
if (semver.lt(semVer, MIN_CODEFLASH_VERSION)) {
return getCodeflashVersionIncompatibleError(version, pythonPath);
}
return undefined;
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
this.logger.debug("Error checking for codeflash installation " + message);
if (message.includes("PackageNotFoundError")) {
return false;
const installCmd = `${pythonPath} -m pip install codeflash`;
return getCodeflashNotInstalledError(pythonPath, installCmd);
}
// for other unexpected errors, we don't block the user
return true;
return undefined;
}
};
}

View file

@ -1,5 +1,6 @@
import { dirname, resolve } from "path";
import { InitStepError } from "./baseStep";
import { MIN_CODEFLASH_VERSION } from "../constants/cf_min_version";
export const GIT_ERRORS = {
NO_REPO: "NO_REPO",
@ -23,6 +24,34 @@ export const getPythonNotSelectedError = (): InitStepError => {
return err;
};
export const getCodeflashVersionNotValidError = (
interpreterPath: string,
): InitStepError => {
const err = new InitStepError("Codeflash version check failed");
err.details = `Failed to determine the installed Codeflash version in the current active Python environment (<code>${interpreterPath}</code>).`;
err.vscodeActionCommand = {
title: "Or you can select another interpreter:",
btnText: "Select interpreter",
command: "python.setInterpreter",
};
err.helperCmdText =
"You can try reinstalling Codeflash in your current Python environment using:";
err.helperCmd = "pip install --upgrade codeflash";
return err;
};
export const getCodeflashVersionIncompatibleError = (
installedVersion: string,
interpreterPath: string,
): InitStepError => {
const err = new InitStepError("Incompatible Codeflash version installed");
err.details = `The installed Codeflash version (<code>${installedVersion}</code>) is incompatible with this extension. Please upgrade to at least version <code>${MIN_CODEFLASH_VERSION}</code>.<br /><br />Your active Python interpreter is located at: <code>${interpreterPath}</code>.`;
err.helperCmdText =
"You can upgrade Codeflash in your current Python environment using:";
err.helperCmd = "pip install --upgrade codeflash";
return err;
};
export const getCodeflashNotInstalledError = (
interpreterPath: string,
installCmd: string,

View file

@ -0,0 +1 @@
export const MIN_CODEFLASH_VERSION = "0.18.1";