refactor: record the instance python version in the setting itself

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Ruben Fiszel
2026-10-10 13:33:13 +02:00
co-authored by Claude Opus 5.5
parent 52537a6cb6
commit 9daee20959
10 changed files with 78 additions and 136 deletions
+18 -22
View File
@@ -9,8 +9,7 @@ use anyhow::Context;
use monitor::{
flush_pending_log_files_to_object_store, load_base_url, load_otel,
reload_critical_alerts_on_db_oversize, reload_delete_logs_periodically_setting,
reload_indexer_config, reload_instance_python_baseline_setting,
reload_instance_python_version_setting, reload_maven_repos_setting,
reload_indexer_config, reload_instance_python_version_setting, reload_maven_repos_setting,
reload_maven_settings_xml_setting, reload_no_default_maven_setting,
reload_nuget_config_setting, reload_powershell_repo_pat_setting,
reload_powershell_repo_url_setting, reload_ruby_repos_setting,
@@ -50,23 +49,23 @@ use windmill_common::{
EXTRA_PIP_INDEX_URL_SETTING, FORK_WORKSPACE_TAG_APPEND_FORK_SUFFIX_SETTING,
HTTP_ROUTE_DEFAULT_ALLOWED_ORIGINS_SETTING, HTTP_ROUTE_WORKSPACED_ROUTE_SETTING,
HUB_API_SECRET_SETTING, HUB_BASE_URL_SETTING, INDEXER_SETTING,
INSTANCE_EVENTS_WEBHOOK_SETTING, INSTANCE_PYTHON_BASELINE_SETTING,
INSTANCE_PYTHON_VERSION_SETTING, JOB_DEFAULT_TIMEOUT_SECS_SETTING, JOB_ISOLATION_SETTING,
JWT_SECRET_SETTING, KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING, MAVEN_REPOS_SETTING,
MAVEN_SETTINGS_XML_SETTING, MCP_DISABLE_TOKEN_QUERY_PARAM_SETTING,
MONITOR_LOGS_ON_OBJECT_STORE_SETTING, NO_DEFAULT_MAVEN_SETTING,
NPM_CONFIG_REGISTRY_SETTING, NSJAIL_TMPFS_SIZE_MB_SETTING, NSJAIL_TMP_BACKING_SETTING,
NUGET_CONFIG_SETTING, OAUTH_SETTING, OTEL_SETTING, OTEL_TRACES_RETENTION_SECS_SETTING,
OTEL_TRACING_PROXY_SETTING, PIP_INDEX_URL_SETTING, POWERSHELL_REPO_PAT_SETTING,
POWERSHELL_REPO_URL_SETTING, PREVIEW_TAGS_OVERRIDE_SETTING, REQUEST_SIZE_LIMIT_SETTING,
REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, RESTART_COORDINATION_SETTING,
RETENTION_PERIOD_SECS_OVERRIDES_SETTING, RETENTION_PERIOD_SECS_SETTING, RUBY_REPOS_SETTING,
SAML_METADATA_SETTING, SANDBOX_IMAGE_CACHE_MAX_MB_SETTING,
SANDBOX_IMAGE_DEFAULT_REGISTRY_SETTING, SANDBOX_IMAGE_MAX_SIZE_MB_SETTING,
SANDBOX_IMAGE_PULL_POLICY_SETTING, SANDBOX_REGISTRY_AUTH_SETTING, SCIM_TOKEN_SETTING,
SERVICE_LOG_RETENTION_SECS_SETTING, SMTP_SETTING, STORE_AUDIT_LOGS_S3_SETTING,
SYNC_HUB_RESOURCE_TYPES_DAILY_SETTING, TEAMS_SETTING, TIMEOUT_WAIT_RESULT_SETTING,
UV_EXCLUDE_NEWER_SETTING, UV_INDEX_STRATEGY_SETTING, UV_PYTHON_INSTALL_MIRROR_SETTING,
INSTANCE_EVENTS_WEBHOOK_SETTING, INSTANCE_PYTHON_VERSION_SETTING,
JOB_DEFAULT_TIMEOUT_SECS_SETTING, JOB_ISOLATION_SETTING, JWT_SECRET_SETTING,
KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING, MAVEN_REPOS_SETTING, MAVEN_SETTINGS_XML_SETTING,
MCP_DISABLE_TOKEN_QUERY_PARAM_SETTING, MONITOR_LOGS_ON_OBJECT_STORE_SETTING,
NO_DEFAULT_MAVEN_SETTING, NPM_CONFIG_REGISTRY_SETTING, NSJAIL_TMPFS_SIZE_MB_SETTING,
NSJAIL_TMP_BACKING_SETTING, NUGET_CONFIG_SETTING, OAUTH_SETTING, OTEL_SETTING,
OTEL_TRACES_RETENTION_SECS_SETTING, OTEL_TRACING_PROXY_SETTING, PIP_INDEX_URL_SETTING,
POWERSHELL_REPO_PAT_SETTING, POWERSHELL_REPO_URL_SETTING, PREVIEW_TAGS_OVERRIDE_SETTING,
REQUEST_SIZE_LIMIT_SETTING, REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING,
RESTART_COORDINATION_SETTING, RETENTION_PERIOD_SECS_OVERRIDES_SETTING,
RETENTION_PERIOD_SECS_SETTING, RUBY_REPOS_SETTING, SAML_METADATA_SETTING,
SANDBOX_IMAGE_CACHE_MAX_MB_SETTING, SANDBOX_IMAGE_DEFAULT_REGISTRY_SETTING,
SANDBOX_IMAGE_MAX_SIZE_MB_SETTING, SANDBOX_IMAGE_PULL_POLICY_SETTING,
SANDBOX_REGISTRY_AUTH_SETTING, SCIM_TOKEN_SETTING, SERVICE_LOG_RETENTION_SECS_SETTING,
SMTP_SETTING, STORE_AUDIT_LOGS_S3_SETTING, SYNC_HUB_RESOURCE_TYPES_DAILY_SETTING,
TEAMS_SETTING, TIMEOUT_WAIT_RESULT_SETTING, UV_EXCLUDE_NEWER_SETTING,
UV_INDEX_STRATEGY_SETTING, UV_PYTHON_INSTALL_MIRROR_SETTING,
WORKSPACE_FAIRNESS_DURATION_SECS_SETTING, WORKSPACE_FAIRNESS_ENABLED_SETTING,
WORKSPACE_FAIRNESS_MAX_PERCENT_SETTING, WORKSPACE_FAIRNESS_MIN_TOTAL_SETTING,
WORKSPACE_MAX_QUEUED_JOBS_SETTING, WORKSPACE_REGISTRIES_SETTING,
@@ -1922,9 +1921,6 @@ async fn process_notify_event(
INSTANCE_PYTHON_VERSION_SETTING => {
reload_instance_python_version_setting(conn).await
}
INSTANCE_PYTHON_BASELINE_SETTING => {
reload_instance_python_baseline_setting(conn).await
}
NPM_CONFIG_REGISTRY_SETTING => reload_npm_config_registry_setting(conn).await,
BUNFIG_INSTALL_SCOPES_SETTING => reload_bunfig_install_scopes_setting(conn).await,
NUGET_CONFIG_SETTING => reload_nuget_config_setting(conn).await,
+16 -32
View File
@@ -63,15 +63,14 @@ use windmill_common::{
DEFAULT_TAGS_WORKSPACES_SETTING, DEPENDENCY_JOB_TAG_SETTING, DISABLE_PASSWORD_LOGIN,
DISABLE_PASSWORD_LOGIN_SETTING, EXPOSE_DEBUG_METRICS_SETTING, EXPOSE_METRICS_SETTING,
EXTRA_PIP_INDEX_URL_SETTING, FORK_WORKSPACE_TAG_APPEND_FORK_SUFFIX_SETTING,
HUB_API_SECRET_SETTING, HUB_BASE_URL_SETTING, INSTANCE_PYTHON_BASELINE_SETTING,
INSTANCE_PYTHON_VERSION_SETTING, JOB_DEFAULT_TIMEOUT_SECS_SETTING, JOB_ISOLATION_SETTING,
JWT_SECRET_SETTING, KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING,
MCP_DISABLE_TOKEN_QUERY_PARAM, MCP_DISABLE_TOKEN_QUERY_PARAM_SETTING,
MONITOR_LOGS_ON_OBJECT_STORE_SETTING, NPMRC_SETTING, NPM_CONFIG_REGISTRY_SETTING,
NSJAIL_TMPFS_SIZE_MB_SETTING, NSJAIL_TMP_BACKING_SETTING, NUGET_CONFIG_SETTING,
OTEL_SETTING, OTEL_TRACES_RETENTION_SECS_SETTING, OTEL_TRACING_PROXY_SETTING,
PIP_INDEX_URL_SETTING, POWERSHELL_REPO_PAT_SETTING, POWERSHELL_REPO_URL_SETTING,
PREVIEW_TAGS_OVERRIDE_SETTING, REQUEST_SIZE_LIMIT_SETTING,
HUB_API_SECRET_SETTING, HUB_BASE_URL_SETTING, INSTANCE_PYTHON_VERSION_SETTING,
JOB_DEFAULT_TIMEOUT_SECS_SETTING, JOB_ISOLATION_SETTING, JWT_SECRET_SETTING,
KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING, MCP_DISABLE_TOKEN_QUERY_PARAM,
MCP_DISABLE_TOKEN_QUERY_PARAM_SETTING, MONITOR_LOGS_ON_OBJECT_STORE_SETTING, NPMRC_SETTING,
NPM_CONFIG_REGISTRY_SETTING, NSJAIL_TMPFS_SIZE_MB_SETTING, NSJAIL_TMP_BACKING_SETTING,
NUGET_CONFIG_SETTING, OTEL_SETTING, OTEL_TRACES_RETENTION_SECS_SETTING,
OTEL_TRACING_PROXY_SETTING, PIP_INDEX_URL_SETTING, POWERSHELL_REPO_PAT_SETTING,
POWERSHELL_REPO_URL_SETTING, PREVIEW_TAGS_OVERRIDE_SETTING, REQUEST_SIZE_LIMIT_SETTING,
REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, RETENTION_PERIOD_SECS_SETTING,
SAML_METADATA_SETTING, SANDBOX_IMAGE_CACHE_MAX_MB_SETTING,
SANDBOX_IMAGE_DEFAULT_REGISTRY_SETTING, SANDBOX_IMAGE_MAX_SIZE_MB_SETTING,
@@ -131,14 +130,14 @@ use windmill_store::resources::MAX_RESOURCE_VERSIONS;
use windmill_worker::{
result_processor::handle_job_error, JobCompletedSender, JobIsolationLevel,
OtelTracingProxySettings, SameWorkerSender, StepFailureKind, WorkspaceRegistryMap,
BUNFIG_INSTALL_SCOPES, BUN_INSTALL_MIN_RELEASE_AGE, CARGO_REGISTRIES, INSTANCE_PYTHON_BASELINE,
INSTANCE_PYTHON_VERSION, JAVA_HOME_DIR, JOB_DEFAULT_TIMEOUT, JOB_ISOLATION, KEEP_JOB_DIR,
MAVEN_REPOS, MAVEN_SETTINGS_XML, NO_DEFAULT_MAVEN, NPMRC, NPM_CONFIG_REGISTRY,
NSJAIL_AVAILABLE, NSJAIL_TMPFS_SIZE_MB, NSJAIL_TMP_BACKING, NUGET_CONFIG,
OTEL_TRACING_PROXY_SETTINGS, PIP_EXTRA_INDEX_URL, PIP_INDEX_URL, POWERSHELL_REPO_PAT,
POWERSHELL_REPO_URL, SANDBOX_IMAGE_CACHE_MAX_MB, SANDBOX_IMAGE_DEFAULT_REGISTRY,
SANDBOX_IMAGE_MAX_SIZE_MB, SANDBOX_IMAGE_PULL_POLICY, SANDBOX_REGISTRY_AUTH, UNSHARE_PATH,
UV_EXCLUDE_NEWER, UV_INDEX_STRATEGY, UV_PYTHON_INSTALL_MIRROR, WORKSPACE_REGISTRIES,
BUNFIG_INSTALL_SCOPES, BUN_INSTALL_MIN_RELEASE_AGE, CARGO_REGISTRIES, INSTANCE_PYTHON_VERSION,
JAVA_HOME_DIR, JOB_DEFAULT_TIMEOUT, JOB_ISOLATION, KEEP_JOB_DIR, MAVEN_REPOS,
MAVEN_SETTINGS_XML, NO_DEFAULT_MAVEN, NPMRC, NPM_CONFIG_REGISTRY, NSJAIL_AVAILABLE,
NSJAIL_TMPFS_SIZE_MB, NSJAIL_TMP_BACKING, NUGET_CONFIG, OTEL_TRACING_PROXY_SETTINGS,
PIP_EXTRA_INDEX_URL, PIP_INDEX_URL, POWERSHELL_REPO_PAT, POWERSHELL_REPO_URL,
SANDBOX_IMAGE_CACHE_MAX_MB, SANDBOX_IMAGE_DEFAULT_REGISTRY, SANDBOX_IMAGE_MAX_SIZE_MB,
SANDBOX_IMAGE_PULL_POLICY, SANDBOX_REGISTRY_AUTH, UNSHARE_PATH, UV_EXCLUDE_NEWER,
UV_INDEX_STRATEGY, UV_PYTHON_INSTALL_MIRROR, WORKSPACE_REGISTRIES,
};
#[cfg(feature = "parquet")]
@@ -714,11 +713,6 @@ pub async fn initial_load(
"INSTANCE_PYTHON_VERSION",
INSTANCE_PYTHON_VERSION.clone(),
);
pass.option_setting(
INSTANCE_PYTHON_BASELINE_SETTING,
"INSTANCE_PYTHON_BASELINE",
INSTANCE_PYTHON_BASELINE.clone(),
);
pass.option_setting(NUGET_CONFIG_SETTING, "NUGET_CONFIG", NUGET_CONFIG.clone());
pass.option_setting(
POWERSHELL_REPO_URL_SETTING,
@@ -2902,16 +2896,6 @@ pub async fn reload_instance_python_version_setting(conn: &Connection) {
.await;
}
pub async fn reload_instance_python_baseline_setting(conn: &Connection) {
reload_option_setting_with_tracing(
conn,
INSTANCE_PYTHON_BASELINE_SETTING,
"INSTANCE_PYTHON_BASELINE",
INSTANCE_PYTHON_BASELINE.clone(),
)
.await;
}
pub async fn reload_npm_config_registry_setting(conn: &Connection) {
reload_option_setting_with_tracing(
conn,
+22 -12
View File
@@ -17,7 +17,7 @@ use tokio::task::JoinHandle;
pub use windmill_common::db::DB;
use windmill_common::{
error::Error,
global_settings::INSTANCE_PYTHON_BASELINE_SETTING,
global_settings::INSTANCE_PYTHON_VERSION_SETTING,
utils::{generate_lock_id, GIT_VERSION},
worker::PyVAlias,
};
@@ -380,9 +380,8 @@ pub async fn migrate(
}
crate::live_migrations::custom_migrations(&mut custom_migrator).await?;
if let Err(e) = seed_instance_python_baseline(custom_migrator.connection(), new_instance).await
{
tracing::error!("Could not record the instance python baseline: {e:#}");
if let Err(e) = seed_instance_python_version(custom_migrator.connection(), new_instance).await {
tracing::error!("Could not record the instance python version: {e:#}");
}
Ok(Some(crate::live_migrations::spawn_background_migrations(
db.clone(),
@@ -390,13 +389,15 @@ pub async fn migrate(
)))
}
/// Records, once, which Python version this instance runs on while `instance_python_version`
/// is unset. Only the process that created the schema knows the instance is new, so its value
/// replaces whatever a server that started alongside it recorded; every other start leaves an
/// existing record alone and gives an instance that predates the record the frozen default.
/// Gives `instance_python_version` a concrete value when the instance has none, so the version
/// scripts resolve around is recorded per instance instead of following whatever a release
/// compiles in. Only the process that created the schema knows the instance is new, so its value
/// replaces what a server that started alongside it wrote; every other start fills in the frozen
/// default, and only where no version was chosen (`default` is what the settings page stored
/// for that).
///
/// Runs on the migration connection: a `DATABASE_CONNECTIONS=1` pool has no second one to give.
async fn seed_instance_python_baseline(
async fn seed_instance_python_version(
conn: &mut PgConnection,
new_instance: bool,
) -> Result<(), Error> {
@@ -406,14 +407,23 @@ async fn seed_instance_python_baseline(
"DO UPDATE SET value = EXCLUDED.value",
)
} else {
(PyVAlias::default(), "DO NOTHING")
(
PyVAlias::default(),
"DO UPDATE SET value = EXCLUDED.value WHERE global_settings.value = '\"default\"'::jsonb",
)
};
// The stored setting outranks the `INSTANCE_PYTHON_VERSION` environment variable, so an
// instance configured through it would otherwise be moved off its version by this write.
let version = std::env::var("INSTANCE_PYTHON_VERSION")
.ok()
.filter(|v| !v.is_empty() && v.split('.').all(|part| part.parse::<u32>().is_ok()))
.unwrap_or_else(|| version.version_string());
sqlx::query(&format!(
"INSERT INTO global_settings (name, value) VALUES ($1, to_jsonb($2::text))
ON CONFLICT (name) {on_conflict}"
))
.bind(INSTANCE_PYTHON_BASELINE_SETTING)
.bind(version.version_string())
.bind(INSTANCE_PYTHON_VERSION_SETTING)
.bind(version)
.execute(conn)
.await?;
Ok(())
@@ -52,9 +52,6 @@ pub const UV_EXCLUDE_NEWER_SETTING: &str = "uv_exclude_newer";
pub const UV_PYTHON_INSTALL_MIRROR_SETTING: &str = "uv_python_install_mirror";
pub const BUN_INSTALL_MIN_RELEASE_AGE_SETTING: &str = "bun_install_min_release_age";
pub const INSTANCE_PYTHON_VERSION_SETTING: &str = "instance_python_version";
/// The Python version an instance uses while `instance_python_version` is unset. Written once
/// by the server, so raising the version new instances start on never moves an existing one.
pub const INSTANCE_PYTHON_BASELINE_SETTING: &str = "instance_python_baseline";
pub const RUFF_CONFIG_SETTING: &str = "ruff_config";
pub const SCIM_TOKEN_SETTING: &str = "scim_token";
pub const SAML_METADATA_SETTING: &str = "saml_metadata";
@@ -1026,7 +1026,7 @@ pub const PROTECTED_SETTINGS: &[&str] = &[
"rsa_keys",
"jwt_secret",
"min_keep_alive_version",
"instance_python_baseline",
"instance_python_version",
];
/// Secrets the server signs with or generated for itself. `jwt_secret` signs API and job
@@ -1066,7 +1066,6 @@ pub fn is_withheld_server_secret(name: &str) -> bool {
pub const HIDDEN_SETTINGS: &[&str] = &[
"uid",
"min_keep_alive_version",
"instance_python_baseline",
"automate_username_creation",
"_restart_coordination",
// Legacy ghost: worker configs live in the `config` table with a
+6 -5
View File
@@ -2891,8 +2891,9 @@ pub fn lockfile_line_has_continuation(line: &str) -> bool {
pub enum PyVAlias {
Py310 = 10,
Py311,
// Frozen: what an instance with no recorded baseline and a lock with no `# py:` line run
// on. Raise `NEW_INSTANCE` instead, which existing instances never pick up.
// Frozen: what a lock with no `# py:` line runs on, and what the server writes into
// `instance_python_version` for an instance that never chose one. Raise `NEW_INSTANCE`
// instead, which existing instances never pick up.
#[default]
Py312,
Py313,
@@ -2913,9 +2914,9 @@ impl Into<u32> for PyVAlias {
}
impl PyVAlias {
/// The version a newly initialized instance records as its baseline. Raising it also
/// means the images must keep preinstalling every earlier value, or instances that
/// recorded one download their runtime on first use.
/// What the server writes into `instance_python_version` when it initializes an instance.
/// Raising it also means the images must keep preinstalling every earlier value, or
/// instances that started on one download their runtime on first use.
pub const NEW_INSTANCE: PyVAlias = PyVAlias::Py312;
pub fn all<T: From<PyVAlias>>() -> Vec<T> {
+14 -46
View File
@@ -26,8 +26,8 @@ use crate::{
common::{start_child_process, OccupancyMetrics},
handle_child::handle_child,
python_executor::PYTHON_PATH,
HOME_ENV, INDEX_CERT, INSTANCE_PYTHON_BASELINE, INSTANCE_PYTHON_VERSION, NATIVE_CERT, PATH_ENV,
PROXY_ENVS, PY_INSTALL_DIR, UV_CACHE_DIR, UV_PYTHON_INSTALL_MIRROR, WIN_ENVS,
HOME_ENV, INDEX_CERT, INSTANCE_PYTHON_VERSION, NATIVE_CERT, PATH_ENV, PROXY_ENVS,
PY_INSTALL_DIR, UV_CACHE_DIR, UV_PYTHON_INSTALL_MIRROR, WIN_ENVS,
};
impl From<PyV> for PyVAlias {
@@ -83,31 +83,6 @@ impl DerefMut for PyV {
}
}
/// The version scripts with no pin of their own resolve around: the admin's choice, else the
/// baseline the instance recorded, else the frozen default. A value that does not parse is
/// skipped and reported rather than failing the job.
fn instance_python_version(setting: Option<&str>, baseline: Option<&str>) -> (PyV, Option<String>) {
let mut err = None;
for (name, value) in [
(
"instance_python_version",
setting.filter(|v| *v != "default"),
),
("instance_python_baseline", baseline),
] {
let Some(value) = value else { continue };
match pep440_rs::Version::from_str(value) {
Ok(v) => return (v.into(), err),
Err(_) => {
err.get_or_insert_with(|| {
format!("\nCannot parse {name} ({value:?}), ignoring it")
});
}
}
}
(PyV::default(), err)
}
impl PyV {
pub async fn resolve(
version_specifiers: Vec<pep440_rs::VersionSpecifier>,
@@ -280,10 +255,17 @@ impl PyV {
w_id: &str,
conn: Option<Connection>,
) -> Self {
let (pyv, err) = instance_python_version(
INSTANCE_PYTHON_VERSION.read().await.as_deref(),
INSTANCE_PYTHON_BASELINE.read().await.as_deref(),
);
let mut err = None;
let pyv = match INSTANCE_PYTHON_VERSION.read().await.clone() {
Some(v) if &v == "default" => PyVAlias::default().into(),
Some(v) => pep440_rs::Version::from_str(&v).unwrap_or_else(|_| {
let v = PyVAlias::default().into();
err = Some(format!("\nCannot parse INSTANCE_PYTHON_VERSION ({:?}), fallback to latest_stable ({v:?})", *INSTANCE_PYTHON_VERSION));
v
}),
// Use latest stable
None => PyVAlias::default().into(),
};
if let Some(msg) = err {
if let Some(conn) = conn {
@@ -291,7 +273,7 @@ impl PyV {
}
tracing::error!(msg);
}
pyv
pyv.into()
}
pub async fn list_available_python_versions() -> Vec<Self> {
@@ -799,20 +781,6 @@ mod tests {
pep440_rs::Version::from_str(value).unwrap().into()
}
#[test]
fn instance_version_prefers_the_setting_then_the_baseline() {
let version = |setting, baseline| instance_python_version(setting, baseline).0;
assert_eq!(version(Some("3.11"), Some("3.13")), pyv("3.11"));
// "default" is what the settings UI stores for "no choice".
assert_eq!(version(Some("default"), Some("3.13")), pyv("3.13"));
assert_eq!(version(None, Some("3.13")), pyv("3.13"));
assert_eq!(version(None, None), PyV::default());
let (v, err) = instance_python_version(Some("nope"), Some("3.13"));
assert_eq!(v, pyv("3.13"));
assert!(err.is_some());
}
async fn assert_resolution(
instance_version: &str,
select_highest: bool,
-1
View File
@@ -667,7 +667,6 @@ lazy_static::lazy_static! {
pub static ref UV_EXCLUDE_NEWER: Arc<RwLock<Option<i64>>> = Arc::new(RwLock::new(None));
pub static ref BUN_INSTALL_MIN_RELEASE_AGE: Arc<RwLock<Option<i64>>> = Arc::new(RwLock::new(None));
pub static ref INSTANCE_PYTHON_VERSION: Arc<RwLock<Option<String>>> = Arc::new(RwLock::new(None));
pub static ref INSTANCE_PYTHON_BASELINE: Arc<RwLock<Option<String>>> = Arc::new(RwLock::new(None));
pub static ref JOB_DEFAULT_TIMEOUT: Arc<RwLock<Option<i32>>> = Arc::new(RwLock::new(None));
@@ -199,15 +199,10 @@
let pythonAvailableVersions: ListAvailablePythonVersionsResponse = $state([])
let pythonBaseline: string | undefined = $state()
let isPyFetching = $state(false)
async function fetch_available_python_versions() {
if (isPyFetching) return
isPyFetching = true
SettingService.getGlobal({ key: 'instance_python_baseline' })
.then((v) => (pythonBaseline = typeof v === 'string' ? v : undefined))
.catch((error) => console.error('Error fetching python baseline:', error))
try {
pythonAvailableVersions = await ConfigService.listAvailablePythonVersions()
} catch (error) {
@@ -274,9 +269,7 @@
{#each setting.select_items ?? [] as item}
<ToggleButton
value={item.value ?? item.label}
label={item.value == 'default' && pythonBaseline
? `${item.label} (${pythonBaseline})`
: item.label}
label={item.label}
tooltip={item.tooltip}
item={toggleButton}
/>
@@ -838,11 +838,6 @@ export const settings: Record<string, Setting[]> = {
fieldType: 'select_python',
placeholder: '3.10,3.11,3.12,3.13,3.14,3.15',
select_items: [
{
label: 'Instance default',
value: 'default',
tooltip: 'The version this instance was initialized with'
},
{
label: '3.10'
},