Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add the possibility to choose the python version #1686

Merged
merged 1 commit into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/commands/analyze/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
packageManagers,
PYTHON_DEFAULT_PACKAGE_MANAGER,
} from "../../packageManagers/packageManager.js";
import { SSRFrameworkComponentType } from "../../models/projectOptions.js";
import { DEFAULT_PYTHON_RUNTIME, SSRFrameworkComponentType } from "../../models/projectOptions.js";
import { RawYamlProjectConfiguration, YAMLLanguage } from "../../projectConfiguration/yaml/v2.js";
import {
addBackendComponentToConfig,
Expand Down Expand Up @@ -415,6 +415,7 @@ export async function analyzeCommand(options: GenezioAnalyzeOptions) {
language: {
name: Language.python,
packageManager: packageManagerType,
runtime: DEFAULT_PYTHON_RUNTIME,
} as YAMLLanguage,
environment: mapEnvironmentVariableToConfig(
resultEnvironmentAnalysis.get(componentPath)?.environmentVariables,
Expand Down Expand Up @@ -453,6 +454,7 @@ export async function analyzeCommand(options: GenezioAnalyzeOptions) {
language: {
name: Language.python,
packageManager: packageManagerType,
runtime: DEFAULT_PYTHON_RUNTIME,
} as YAMLLanguage,
environment: mapEnvironmentVariableToConfig(
resultEnvironmentAnalysis.get(componentPath)?.environmentVariables,
Expand Down Expand Up @@ -494,6 +496,7 @@ export async function analyzeCommand(options: GenezioAnalyzeOptions) {
language: {
name: Language.python,
packageManager: packageManagerType,
runtime: DEFAULT_PYTHON_RUNTIME,
} as YAMLLanguage,
environment: mapEnvironmentVariableToConfig(
resultEnvironmentAnalysis.get(componentPath)?.environmentVariables,
Expand Down Expand Up @@ -532,6 +535,7 @@ export async function analyzeCommand(options: GenezioAnalyzeOptions) {
language: {
name: Language.python,
packageManager: packageManagerType,
runtime: DEFAULT_PYTHON_RUNTIME,
} as YAMLLanguage,
environment: mapEnvironmentVariableToConfig(
resultEnvironmentAnalysis.get(componentPath)?.environmentVariables,
Expand Down
45 changes: 41 additions & 4 deletions src/commands/deploy/genezio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ import {
packageManagers,
PYTHON_DEFAULT_PACKAGE_MANAGER,
} from "../../packageManagers/packageManager.js";
import { supportedPythonDepsInstallVersion } from "../../models/projectOptions.js";
import { DEFAULT_PYTHON_VERSION_INSTALL } from "../../models/projectOptions.js";
import { detectPythonVersion } from "../../utils/detectPythonCommand.js";

export async function genezioDeploy(options: GenezioDeployOptions) {
const configIOController = new YamlConfigurationIOController(options.config, {
Expand Down Expand Up @@ -495,7 +496,13 @@ export async function deployClasses(
);

const functionsResultArray: Promise<GenezioCloudInput>[] = projectConfiguration.functions.map(
(f) => functionToCloudInput(f, backend.path, /* outputDir */ undefined),
(f) =>
functionToCloudInput(
f,
backend.path,
/* outputDir */ undefined,
backend.language.runtime,
),
);

const cloudAdapterDeployInput = await Promise.all([
Expand Down Expand Up @@ -578,6 +585,7 @@ export async function functionToCloudInput(
functionElement: FunctionConfiguration,
backendPath: string,
outputDir?: string,
runtime?: string,
): Promise<GenezioCloudInput> {
const supportedFunctionLanguages = ["js", "ts", "python"];

Expand Down Expand Up @@ -636,6 +644,35 @@ export async function functionToCloudInput(
const pathForDependencies = path.join(tmpFolderPath, "packages");
const packageManager = packageManagers[PYTHON_DEFAULT_PACKAGE_MANAGER];
let installCommand;
const versionMatch = runtime!.match(/\d+\.\d+/);
const pythonVersion = versionMatch ? versionMatch[0] : DEFAULT_PYTHON_VERSION_INSTALL;

// check pythonVersion matches with local python version
const localPythonVersion =
(await detectPythonVersion())?.match(/\d+\.\d+/)?.[0] ||
DEFAULT_PYTHON_VERSION_INSTALL;

if (pythonVersion !== localPythonVersion) {
const warningMessage = [
`Python Version Mismatch`,
``,
`We noticed you're using different Python versions locally and in production:`,
`Local Environment: Python ${localPythonVersion}`,
`Production Runtime: Python ${pythonVersion}`,
``,
`This might lead to unexpected behavior. To ensure consistency, update your genezio.yaml configuration to match your local version:`,
``,
`language:`,
` name: python`,
` packageManager: pip`,
` runtime: python${localPythonVersion}.x`,
``,
`This will help prevent potential compatibility issues!`,
`For complete yaml configuration, visit: https://genezio.com/docs/project-structure/genezio-configuration-file/`,
].join("\n");

log.warn(colors.yellow(warningMessage));
}

if (packageManager.command === "pip" || packageManager.command === "pip3") {
if (fs.existsSync(requirementsPath)) {
Expand All @@ -644,10 +681,10 @@ export async function functionToCloudInput(
.readFileSync(requirementsOutputPath, "utf8")
.trim();
if (requirementsContent) {
installCommand = `${packageManager.command} install -r ${requirementsOutputPath} --platform manylinux2014_x86_64 --only-binary=:all: --python-version ${supportedPythonDepsInstallVersion} -t ${pathForDependencies} --no-user`;
installCommand = `${packageManager.command} install -r ${requirementsOutputPath} --platform manylinux2014_x86_64 --only-binary=:all: --python-version ${pythonVersion} -t ${pathForDependencies} --no-user`;
}
} else if (fs.existsSync(pyProjectTomlPath)) {
installCommand = `${packageManager.command} install . --platform manylinux2014_x86_64 --only-binary=:all: --python-version ${supportedPythonDepsInstallVersion} -t ${pathForDependencies}`;
installCommand = `${packageManager.command} install . --platform manylinux2014_x86_64 --only-binary=:all: --python-version ${pythonVersion} -t ${pathForDependencies}`;
}
} else if (packageManager.command === "poetry") {
installCommand = `${packageManager.command} install --no-root --directory ${pathForDependencies}`;
Expand Down
15 changes: 11 additions & 4 deletions src/models/projectOptions.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
export type NodeRuntime = "nodejs20.x";
export type PythonRuntime = "python3.9.x";
export type PythonRuntime = "python3.11.x";
export type Architecture = "arm64" | "x86_64";
export const DEFAULT_NODE_RUNTIME: NodeRuntime = "nodejs20.x";
export const DEFAULT_ARCHITECTURE: Architecture = "arm64";
export const DEFAULT_PYTHON_RUNTIME: PythonRuntime = "python3.9.x";
export const DEFAULT_PYTHON_RUNTIME: PythonRuntime = "python3.11.x";
export const DEFAULT_PYTHON_VERSION_INSTALL: string = "3.11";

export const CONTAINER_IMAGE_NODE20 = "node:20.11.1-alpine3.19";

Expand Down Expand Up @@ -46,7 +47,13 @@ export enum ContainerComponentType {
}

export const supportedNodeRuntimes = ["nodejs20.x"] as const;
export const supportedPythonRuntimes = ["python3.9.x"] as const;
export const supportedPythonRuntimes = [
cristim67 marked this conversation as resolved.
Show resolved Hide resolved
"python3.9.x",
"python3.10.x",
"python3.11.x",
"python3.12.x",
"python3.13.x",
] as const;
export const supportedArchitectures = ["arm64", "x86_64"] as const;
export const supportedSSRFrameworks = ["nextjs", "nitro", "nuxt"] as const;
export const supportedPythonDepsInstallVersion = "3.11" as const;
export const supportedPythonDepsInstallVersion = ["3.9", "3.10", "3.11", "3.12", "3.13"] as const;
14 changes: 14 additions & 0 deletions src/utils/detectPythonCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,17 @@ export async function detectPipCommand() {
}
}
}

export async function detectPythonVersion(): Promise<string | undefined> {
try {
const { stdout } = await $`python3 --version`;
return stdout.replace("Python ", "").trim();
} catch {
try {
const { stdout } = await $`python --version`;
return stdout.replace("Python ", "").trim();
} catch {
return;
}
}
}