From 89fc91bed6d749ea0f050149d7fb7841153aac61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Wed, 3 Sep 2025 09:35:25 +0200 Subject: [PATCH] refactor: Add native Python runner runtime env var (#19109) --- .../@n8n/api-types/src/frontend-settings.ts | 1 + packages/cli/src/services/frontend.service.ts | 2 + .../editor-ui/src/__tests__/defaults.ts | 1 + .../src/components/ParameterInput.vue | 5 ++ .../editor-ui/src/stores/settings.store.ts | 3 + packages/nodes-base/nodes/Code/Code.node.ts | 70 ++++++++----------- 6 files changed, 42 insertions(+), 40 deletions(-) diff --git a/packages/@n8n/api-types/src/frontend-settings.ts b/packages/@n8n/api-types/src/frontend-settings.ts index fb37b7c28b..576bed5922 100644 --- a/packages/@n8n/api-types/src/frontend-settings.ts +++ b/packages/@n8n/api-types/src/frontend-settings.ts @@ -60,6 +60,7 @@ export interface FrontendSettings { versionCli: string; nodeJsVersion: string; concurrency: number; + isNativePythonRunnerEnabled: boolean; authCookie: { secure: boolean; }; diff --git a/packages/cli/src/services/frontend.service.ts b/packages/cli/src/services/frontend.service.ts index b9825ab950..b119542c19 100644 --- a/packages/cli/src/services/frontend.service.ts +++ b/packages/cli/src/services/frontend.service.ts @@ -131,6 +131,8 @@ export class FrontendService { nodeJsVersion: process.version.replace(/^v/, ''), versionCli: N8N_VERSION, concurrency: this.globalConfig.executions.concurrency.productionLimit, + isNativePythonRunnerEnabled: + this.globalConfig.taskRunners.enabled && process.env.N8N_NATIVE_PYTHON_RUNNER === 'true', authCookie: { secure: this.globalConfig.auth.cookie.secure, }, diff --git a/packages/frontend/editor-ui/src/__tests__/defaults.ts b/packages/frontend/editor-ui/src/__tests__/defaults.ts index 8cb572e313..68f9908aa1 100644 --- a/packages/frontend/editor-ui/src/__tests__/defaults.ts +++ b/packages/frontend/editor-ui/src/__tests__/defaults.ts @@ -102,6 +102,7 @@ export const defaultSettings: FrontendSettings = { versionCli: '', nodeJsVersion: '', concurrency: -1, + isNativePythonRunnerEnabled: false, versionNotifications: { enabled: true, endpoint: '', diff --git a/packages/frontend/editor-ui/src/components/ParameterInput.vue b/packages/frontend/editor-ui/src/components/ParameterInput.vue index 4beb074fa9..35188443ee 100644 --- a/packages/frontend/editor-ui/src/components/ParameterInput.vue +++ b/packages/frontend/editor-ui/src/components/ParameterInput.vue @@ -241,6 +241,11 @@ const parameterOptions = computed(() => { const options = hasRemoteMethod.value ? remoteParameterOptions.value : props.parameter.options; const safeOptions = (options ?? []).filter(isValidParameterOption); + // temporary filter until native Python runner is GA + if (props.parameter.name === 'language' && !settingsStore.isNativePythonRunnerEnabled) { + return safeOptions.filter((o) => o.value !== 'pythonNative'); + } + return safeOptions; }); diff --git a/packages/frontend/editor-ui/src/stores/settings.store.ts b/packages/frontend/editor-ui/src/stores/settings.store.ts index 3f998c9e19..7670abbb35 100644 --- a/packages/frontend/editor-ui/src/stores/settings.store.ts +++ b/packages/frontend/editor-ui/src/stores/settings.store.ts @@ -70,6 +70,8 @@ export const useSettingsStore = defineStore(STORES.SETTINGS, () => { const concurrency = computed(() => settings.value.concurrency); + const isNativePythonRunnerEnabled = computed(() => settings.value.isNativePythonRunnerEnabled); + const isConcurrencyEnabled = computed(() => concurrency.value !== -1); const isPublicApiEnabled = computed(() => api.value.enabled); @@ -329,6 +331,7 @@ export const useSettingsStore = defineStore(STORES.SETTINGS, () => { security, nodeJsVersion, concurrency, + isNativePythonRunnerEnabled, isConcurrencyEnabled, isPublicApiEnabled, isSwaggerUIEnabled, diff --git a/packages/nodes-base/nodes/Code/Code.node.ts b/packages/nodes-base/nodes/Code/Code.node.ts index 4a22182849..1ada7babe9 100644 --- a/packages/nodes-base/nodes/Code/Code.node.ts +++ b/packages/nodes-base/nodes/Code/Code.node.ts @@ -3,7 +3,6 @@ import { NodesConfig, TaskRunnersConfig } from '@n8n/config'; import { Container } from '@n8n/di'; import set from 'lodash/set'; import { - type INodeProperties, NodeConnectionTypes, UserError, type CodeExecutionMode, @@ -26,7 +25,7 @@ import { PythonTaskRunnerSandbox } from './PythonTaskRunnerSandbox'; import { getSandboxContext } from './Sandbox'; import { addPostExecutionWarning, standardizeOutput } from './utils'; -const { CODE_ENABLE_STDOUT, N8N_NATIVE_PYTHON_RUNNER } = process.env; +const { CODE_ENABLE_STDOUT } = process.env; class PythonDisabledError extends UserError { constructor() { @@ -36,43 +35,6 @@ class PythonDisabledError extends UserError { } } -const getV2LanguageProperty = (): INodeProperties => { - const options = [ - { - name: 'JavaScript', - value: 'javaScript', - action: 'Code in JavaScript', - }, - { - name: 'Python (Beta)', - value: 'python', - action: 'Code in Python (Beta)', - }, - ]; - - if (N8N_NATIVE_PYTHON_RUNNER === 'true') { - options.push({ - name: 'Python (Native) (Beta)', - value: 'pythonNative', - action: 'Code in Python (Native) (Beta)', - }); - } - - return { - displayName: 'Language', - name: 'language', - type: 'options', - noDataExpression: true, - displayOptions: { - show: { - '@version': [2], - }, - }, - options, - default: 'javaScript', - }; -}; - export class Code implements INodeType { description: INodeTypeDescription = { displayName: 'Code', @@ -108,7 +70,35 @@ export class Code implements INodeType { ], default: 'runOnceForAllItems', }, - getV2LanguageProperty(), + { + displayName: 'Language', + name: 'language', + type: 'options', + noDataExpression: true, + displayOptions: { + show: { + '@version': [2], + }, + }, + options: [ + { + name: 'JavaScript', + value: 'javaScript', + action: 'Code in JavaScript', + }, + { + name: 'Python (Beta)', + value: 'python', + action: 'Code in Python (Beta)', + }, + { + name: 'Python (Native) (Beta)', + value: 'pythonNative', + action: 'Code in Python (Native) (Beta)', + }, + ], + default: 'javaScript', + }, { displayName: 'Language', name: 'language',