diff --git a/backend/src/main.rs b/backend/src/main.rs index a1398d21ca..2ac71aba57 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -51,7 +51,7 @@ use windmill_common::{ MONITOR_LOGS_ON_OBJECT_STORE_SETTING, NO_DEFAULT_MAVEN_SETTING, NPM_CONFIG_REGISTRY_SETTING, NUGET_CONFIG_SETTING, OAUTH_SETTING, OTEL_SETTING, OTEL_TRACING_PROXY_SETTING, PIP_INDEX_URL_SETTING, POWERSHELL_REPO_PAT_SETTING, - POWERSHELL_REPO_URL_SETTING, REQUEST_SIZE_LIMIT_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_SETTING, RUBY_REPOS_SETTING, SAML_METADATA_SETTING, SCIM_TOKEN_SETTING, SMTP_SETTING, TEAMS_SETTING, TIMEOUT_WAIT_RESULT_SETTING, @@ -99,16 +99,17 @@ use windmill_worker::{ }; use crate::monitor::{ - initial_load, load_keep_job_dir, load_metrics_debug_enabled, load_require_preexisting_user, - load_tag_per_workspace_enabled, load_tag_per_workspace_workspaces, monitor_db, - reload_app_workspaced_route_setting, reload_audit_log_retention_days_setting, - reload_base_url_setting, reload_bunfig_install_scopes_setting, - reload_critical_alert_mute_ui_setting, reload_critical_alerts_on_token_expiry_setting, - reload_critical_error_channels_setting, reload_extra_pip_index_url_setting, - reload_http_route_workspaced_route_setting, reload_hub_api_secret_setting, - reload_hub_base_url_setting, reload_instance_events_webhook_setting, - reload_job_default_timeout_setting, reload_job_isolation_setting, reload_jwt_secret_setting, - reload_license_key, reload_npm_config_registry_setting, reload_otel_tracing_proxy_setting, + initial_load, load_keep_job_dir, load_metrics_debug_enabled, load_preview_tags_override, + load_require_preexisting_user, load_tag_per_workspace_enabled, + load_tag_per_workspace_workspaces, monitor_db, reload_app_workspaced_route_setting, + reload_audit_log_retention_days_setting, reload_base_url_setting, + reload_bunfig_install_scopes_setting, reload_critical_alert_mute_ui_setting, + reload_critical_alerts_on_token_expiry_setting, reload_critical_error_channels_setting, + reload_extra_pip_index_url_setting, reload_http_route_workspaced_route_setting, + reload_hub_api_secret_setting, reload_hub_base_url_setting, + reload_instance_events_webhook_setting, reload_job_default_timeout_setting, + reload_job_isolation_setting, reload_jwt_secret_setting, reload_license_key, + reload_npm_config_registry_setting, reload_otel_tracing_proxy_setting, reload_pip_index_url_setting, reload_retention_period_setting, reload_scim_token_setting, reload_smtp_config, reload_uv_index_strategy_setting, reload_worker_config, MonitorIteration, }; @@ -1742,6 +1743,11 @@ async fn process_notify_event( ); } } + PREVIEW_TAGS_OVERRIDE_SETTING => { + if let Err(e) = load_preview_tags_override(db).await { + tracing::error!("Error loading preview tags override: {e:#}"); + } + } SMTP_SETTING => { reload_smtp_config(db).await; } diff --git a/backend/src/monitor.rs b/backend/src/monitor.rs index 2b1196c8c2..5e87f3d161 100644 --- a/backend/src/monitor.rs +++ b/backend/src/monitor.rs @@ -62,7 +62,7 @@ use windmill_common::{ KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING, MONITOR_LOGS_ON_OBJECT_STORE_SETTING, NPMRC_SETTING, NPM_CONFIG_REGISTRY_SETTING, NUGET_CONFIG_SETTING, OTEL_SETTING, OTEL_TRACING_PROXY_SETTING, PIP_INDEX_URL_SETTING, POWERSHELL_REPO_PAT_SETTING, - POWERSHELL_REPO_URL_SETTING, REQUEST_SIZE_LIMIT_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, SCIM_TOKEN_SETTING, TIMEOUT_WAIT_RESULT_SETTING, UV_INDEX_STRATEGY_SETTING, @@ -79,8 +79,8 @@ use windmill_common::{ load_periodic_bash_script_interval_from_env, load_whitelist_env_vars_from_env, load_worker_config, reload_custom_tags_setting, store_pull_query, store_suspended_pull_query, Connection, WorkerConfig, DEFAULT_TAGS_PER_WORKSPACE, - DEFAULT_TAGS_WORKSPACES, INDEXER_CONFIG, SCRIPT_TOKEN_EXPIRY, SMTP_CONFIG, WINDMILL_DIR, - WORKER_CONFIG, WORKER_GROUP, + DEFAULT_TAGS_WORKSPACES, INDEXER_CONFIG, PREVIEW_TAGS_OVERRIDE, SCRIPT_TOKEN_EXPIRY, + SMTP_CONFIG, WINDMILL_DIR, WORKER_CONFIG, WORKER_GROUP, }, KillpillSender, AUDIT_LOG_RETENTION_DAYS, BASE_URL, CRITICAL_ALERTS_ON_DB_OVERSIZE, CRITICAL_ALERTS_ON_TOKEN_EXPIRY, CRITICAL_ALERT_MUTE_UI_ENABLED, CRITICAL_ERROR_CHANNELS, DB, @@ -235,6 +235,10 @@ pub async fn initial_load( if let Err(e) = load_tag_per_workspace_workspaces(db).await { tracing::error!("Error loading default tag per workpsace workspaces: {e:#}"); } + + if let Err(e) = load_preview_tags_override(db).await { + tracing::error!("Error loading preview tags override: {e:#}"); + } } if server_mode { @@ -499,6 +503,16 @@ pub async fn load_tag_per_workspace_workspaces(db: &DB) -> error::Result<()> { Ok(()) } +pub async fn load_preview_tags_override(db: &DB) -> error::Result<()> { + let value = load_value_from_global_settings(db, PREVIEW_TAGS_OVERRIDE_SETTING).await; + + match value { + Ok(Some(serde_json::Value::Bool(t))) => PREVIEW_TAGS_OVERRIDE.store(t, Ordering::Relaxed), + _ => (), + }; + Ok(()) +} + pub async fn reload_critical_alert_mute_ui_setting(conn: &Connection) -> error::Result<()> { if let Ok(Some(serde_json::Value::Bool(t))) = load_value_from_global_settings_with_conn(conn, CRITICAL_ALERT_MUTE_UI_SETTING, true).await diff --git a/backend/windmill-common/src/global_settings.rs b/backend/windmill-common/src/global_settings.rs index bdedcbd7bb..62a4bdc700 100644 --- a/backend/windmill-common/src/global_settings.rs +++ b/backend/windmill-common/src/global_settings.rs @@ -1,6 +1,7 @@ pub const CUSTOM_TAGS_SETTING: &str = "custom_tags"; pub const DEFAULT_TAGS_PER_WORKSPACE_SETTING: &str = "default_tags_per_workspace"; pub const DEFAULT_TAGS_WORKSPACES_SETTING: &str = "default_tags_workspaces"; +pub const PREVIEW_TAGS_OVERRIDE_SETTING: &str = "preview_tags_override"; pub const BASE_URL_SETTING: &str = "base_url"; pub const WS_BASE_URL_SETTING: &str = "ws_base_url"; pub const OAUTH_SETTING: &str = "oauths"; diff --git a/backend/windmill-common/src/instance_config.rs b/backend/windmill-common/src/instance_config.rs index dfa0dd6454..3023a5ab33 100644 --- a/backend/windmill-common/src/instance_config.rs +++ b/backend/windmill-common/src/instance_config.rs @@ -243,6 +243,8 @@ pub struct GlobalSettings { #[serde(skip_serializing_if = "Option::is_none")] pub default_tags_per_workspace: Option, #[serde(skip_serializing_if = "Option::is_none")] + pub preview_tags_override: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub disable_hub: Option, // String settings diff --git a/backend/windmill-common/src/worker.rs b/backend/windmill-common/src/worker.rs index b1ba371ea2..026f60da75 100644 --- a/backend/windmill-common/src/worker.rs +++ b/backend/windmill-common/src/worker.rs @@ -205,6 +205,7 @@ lazy_static::lazy_static! { pub static ref DEFAULT_TAGS_PER_WORKSPACE: AtomicBool = AtomicBool::new(false); pub static ref DEFAULT_TAGS_WORKSPACES: Arc>>> = Arc::new(RwLock::new(None)); + pub static ref PREVIEW_TAGS_OVERRIDE: AtomicBool = AtomicBool::new(false); pub static ref MAX_TIMEOUT: u64 = std::env::var("TIMEOUT") .ok() diff --git a/backend/windmill-queue/src/jobs.rs b/backend/windmill-queue/src/jobs.rs index a6ba745c24..53c7460c4e 100644 --- a/backend/windmill-queue/src/jobs.rs +++ b/backend/windmill-queue/src/jobs.rs @@ -77,8 +77,8 @@ use windmill_common::{ users::{SUPERADMIN_NOTIFICATION_EMAIL, SUPERADMIN_SECRET_EMAIL}, utils::{not_found_if_none, report_critical_error, StripPath, WarnAfterExt}, worker::{ - to_raw_value, CLOUD_HOSTED, DISABLE_FLOW_SCRIPT, NO_LOGS, WORKER_PULL_QUERIES, - WORKER_SUSPENDED_PULL_QUERY, + to_raw_value, CLOUD_HOSTED, DISABLE_FLOW_SCRIPT, NO_LOGS, PREVIEW_TAGS_OVERRIDE, + WORKER_PULL_QUERIES, WORKER_SUSPENDED_PULL_QUERY, }, DB, METRICS_ENABLED, }; @@ -3302,7 +3302,10 @@ pub async fn pull( }; if let Some(job) = job.as_ref() { - if job.is_flow() || job.is_dependency() { + if (job.is_flow() || job.is_dependency()) + && !(job.kind.is_preview() + && PREVIEW_TAGS_OVERRIDE.load(std::sync::atomic::Ordering::Relaxed)) + { let per_workspace = per_workspace_tag(&job.workspace_id).await; let base_tag = if job.is_flow() { "flow".to_string() @@ -5493,25 +5496,35 @@ async fn push_inner<'c, 'd>( }; interpolated_tag.unwrap_or_else(|| { - language - .as_ref() - .map(|x| { - let tag_lang = if x == &ScriptLang::Bunnative { - if job_kind == JobKind::Dependencies { - ScriptLang::Bun.as_str() + if job_kind.is_preview() + && PREVIEW_TAGS_OVERRIDE.load(std::sync::atomic::Ordering::Relaxed) + { + if per_workspace { + format!("preview-{}", workspace_id) + } else { + "preview".to_string() + } + } else { + language + .as_ref() + .map(|x| { + let tag_lang = if x == &ScriptLang::Bunnative { + if job_kind == JobKind::Dependencies { + ScriptLang::Bun.as_str() + } else { + ScriptLang::Nativets.as_str() + } } else { - ScriptLang::Nativets.as_str() + x.as_str() + }; + if per_workspace { + format!("{}-{}", tag_lang, workspace_id) + } else { + tag_lang.to_string() } - } else { - x.as_str() - }; - if per_workspace { - format!("{}-{}", tag_lang, workspace_id) - } else { - tag_lang.to_string() - } - }) - .unwrap_or_else(default) + }) + .unwrap_or_else(default) + } }) }; diff --git a/backend/windmill-types/src/jobs.rs b/backend/windmill-types/src/jobs.rs index 28c3242695..99a5607508 100644 --- a/backend/windmill-types/src/jobs.rs +++ b/backend/windmill-types/src/jobs.rs @@ -118,6 +118,10 @@ impl JobKind { JobKind::FlowDependencies | JobKind::AppDependencies | JobKind::Dependencies ) } + + pub fn is_preview(&self) -> bool { + matches!(self, JobKind::Preview | JobKind::FlowPreview) + } } #[derive(sqlx::FromRow, Debug, Serialize, Clone)] diff --git a/frontend/src/lib/components/DefaultTagsInner.svelte b/frontend/src/lib/components/DefaultTagsInner.svelte index ab2d403ec8..e57afd9659 100644 --- a/frontend/src/lib/components/DefaultTagsInner.svelte +++ b/frontend/src/lib/components/DefaultTagsInner.svelte @@ -4,7 +4,11 @@ import { SettingService, WorkerService, WorkspaceService } from '$lib/gen' import { sendUserToast } from '$lib/toast' import { enterpriseLicense, superadmin } from '$lib/stores' - import { DEFAULT_TAGS_PER_WORKSPACE_SETTING, DEFAULT_TAGS_WORKSPACES_SETTING } from '$lib/consts' + import { + DEFAULT_TAGS_PER_WORKSPACE_SETTING, + DEFAULT_TAGS_WORKSPACES_SETTING, + PREVIEW_TAGS_OVERRIDE_SETTING + } from '$lib/consts' import Toggle from './Toggle.svelte' import MultiSelect from './select/MultiSelect.svelte' import { safeSelectItems } from './select/utils.svelte' @@ -22,16 +26,19 @@ let defaultTags = $state(undefined) let limitToWorkspaces = $state(false) + let previewTagsOverride = $state(false) // Change detection let originalDefaultTagPerWorkspace = $state(defaultTagPerWorkspace) let originalDefaultTagWorkspaces = $state(defaultTagWorkspaces) + let originalPreviewTagsOverride = $state(false) // Detect changes let hasChanges = $derived( originalDefaultTagPerWorkspace !== defaultTagPerWorkspace || JSON.stringify($state.snapshot(originalDefaultTagWorkspaces)?.sort() || []) !== - JSON.stringify($state.snapshot(defaultTagWorkspaces)?.sort() || []) + JSON.stringify($state.snapshot(defaultTagWorkspaces)?.sort() || []) || + originalPreviewTagsOverride !== previewTagsOverride ) let workspaces: string[] = $state([]) @@ -47,6 +54,11 @@ key: DEFAULT_TAGS_WORKSPACES_SETTING })) as any) ?? [] limitToWorkspaces = defaultTagWorkspaces ? defaultTagWorkspaces.length > 0 : false + previewTagsOverride = + ((await SettingService.getGlobal({ + key: PREVIEW_TAGS_OVERRIDE_SETTING + })) as any) ?? false + originalPreviewTagsOverride = previewTagsOverride } catch (err) { sendUserToast(`Could not load default tags: ${err}`, true) } @@ -68,10 +80,17 @@ : undefined } }) + await SettingService.setGlobal({ + key: PREVIEW_TAGS_OVERRIDE_SETTING, + requestBody: { + value: previewTagsOverride + } + }) // Update original state after save originalDefaultTagPerWorkspace = defaultTagPerWorkspace originalDefaultTagWorkspaces = [...(defaultTagWorkspaces || [])] + originalPreviewTagsOverride = previewTagsOverride loadDefaultTags() sendUserToast('Saved') @@ -146,6 +165,18 @@ /> {/if} {/if} +
+ +
@@ -168,6 +199,17 @@
{/each} + {#if previewTagsOverride} +
+
+ preview +
+
+
+ {defaultTagPerWorkspace ? 'preview-$workspace' : 'preview'} +
+
+ {/if} {/if} diff --git a/frontend/src/lib/consts.ts b/frontend/src/lib/consts.ts index 677ffa8ad4..dcd2b2b559 100644 --- a/frontend/src/lib/consts.ts +++ b/frontend/src/lib/consts.ts @@ -41,6 +41,7 @@ export const WORKER_S3_BUCKET_SYNC_SETTING = 'worker_s3_bucket_sync' export const CUSTOM_TAGS_SETTING = 'custom_tags' export const DEFAULT_TAGS_PER_WORKSPACE_SETTING = 'default_tags_per_workspace' export const DEFAULT_TAGS_WORKSPACES_SETTING = 'default_tags_workspaces' +export const PREVIEW_TAGS_OVERRIDE_SETTING = 'preview_tags_override' export const WORKSPACE_SLACK_BOT_TOKEN_PATH = 'f/slack_bot/bot_token'