mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-12 16:02:56 +00:00
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:
co-authored by
Claude Opus 5.5
parent
52537a6cb6
commit
9daee20959
+18
-22
@@ -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
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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'
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user