From 193eb36eb33bd078a74d54e479f7e40a7b646369 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Fri, 1 May 2026 17:21:17 +0000 Subject: [PATCH] feat: support assigning a worker tag to app inline scripts (#9002) * feat: support assigning a worker tag to app/raw-app inline scripts Co-Authored-By: Claude Opus 4.5 * fix: omit empty tag field from inline script raw_code payload Co-Authored-By: Claude Opus 4.5 * style: shrink tag popover width --------- Co-authored-by: Claude Opus 4.5 --- backend/tests/agent_workers.rs | 1 + backend/tests/bun_jobs.rs | 27 +++++++++ backend/tests/list_jobs.rs | 17 ++++++ backend/tests/nativets_jobs.rs | 1 + backend/tests/nativets_stress.rs | 1 + backend/tests/python_jobs.rs | 7 +++ backend/tests/script_modules.rs | 3 + backend/tests/volume_tests.rs | 1 + backend/tests/worker.rs | 32 +++++++++++ .../tests/sensitive_log_masking.rs | 2 + backend/windmill-api/openapi.yaml | 2 + backend/windmill-api/src/apps.rs | 9 ++- backend/windmill-api/src/jobs.rs | 4 ++ backend/windmill-queue/src/jobs.rs | 3 + backend/windmill-test-utils/src/lib.rs | 1 + backend/windmill-types/src/jobs.rs | 1 + backend/windmill-worker/src/bun_executor.rs | 2 + backend/windmill-worker/src/worker_flow.rs | 1 + .../components/helpers/executeRunnable.ts | 5 +- .../InlineScriptEditor.svelte | 7 +++ .../editor/inlineScriptsPanel/TagPopup.svelte | 57 +++++++++++++++++++ .../src/lib/components/apps/sharedTypes.ts | 1 + .../raw_apps/RawAppInlineScriptEditor.svelte | 2 + 23 files changed, 182 insertions(+), 5 deletions(-) create mode 100644 frontend/src/lib/components/apps/editor/inlineScriptsPanel/TagPopup.svelte diff --git a/backend/tests/agent_workers.rs b/backend/tests/agent_workers.rs index f422ed3a12..6ec3f9e410 100644 --- a/backend/tests/agent_workers.rs +++ b/backend/tests/agent_workers.rs @@ -22,6 +22,7 @@ fn bun_code(code: &str) -> RawCode { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, } } diff --git a/backend/tests/bun_jobs.rs b/backend/tests/bun_jobs.rs index cf937bc931..170bf9573b 100644 --- a/backend/tests/bun_jobs.rs +++ b/backend/tests/bun_jobs.rs @@ -35,6 +35,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -72,6 +73,7 @@ export function main(name: string, count: number) { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = RunJob::from(job) @@ -115,6 +117,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -148,6 +151,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -182,6 +186,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -223,6 +228,7 @@ export async function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -263,6 +269,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -296,6 +303,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -339,6 +347,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let completed = run_job_in_new_worker_until_complete(&db, false, job, port).await; @@ -380,6 +389,7 @@ export function notMain() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let completed = run_job_in_new_worker_until_complete(&db, false, job, port).await; @@ -421,6 +431,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let completed = run_job_in_new_worker_until_complete(&db, false, job, port).await; @@ -459,6 +470,7 @@ export async function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let completed = run_job_in_new_worker_until_complete(&db, false, job, port).await; @@ -514,6 +526,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -552,6 +565,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -595,6 +609,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -694,6 +709,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -730,6 +746,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -777,6 +794,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -826,6 +844,7 @@ export function main(x: number) { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); // x=5, main adds 10 = 15 @@ -877,6 +896,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -923,6 +943,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -1963,6 +1984,7 @@ export function main(name: string) { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = RunJob::from(job) @@ -2027,6 +2049,7 @@ export function main(name: string) { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = RunJob::from(job) @@ -2304,6 +2327,7 @@ module.exports.main = function() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = RunJob::from(job) @@ -2346,6 +2370,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = RunJob::from(job) @@ -2397,6 +2422,7 @@ module.exports.main = function() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); use std::sync::atomic::Ordering; @@ -2458,6 +2484,7 @@ export function main() { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); use std::sync::atomic::Ordering; diff --git a/backend/tests/list_jobs.rs b/backend/tests/list_jobs.rs index 7d3c874882..82a9e197cc 100644 --- a/backend/tests/list_jobs.rs +++ b/backend/tests/list_jobs.rs @@ -68,6 +68,7 @@ async fn test_list_jobs_without_include_args(db: Pool) -> anyhow::Resu .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("x", json!(42)) .push(&db) @@ -125,6 +126,7 @@ async fn test_list_jobs_with_include_args(db: Pool) -> anyhow::Result< .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("x", json!(42)) .push(&db) @@ -196,6 +198,7 @@ async fn test_list_jobs_completed_with_include_args(db: Pool) -> anyho .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("x", json!(42)) .run_until_complete(&db, false, port) @@ -269,6 +272,7 @@ async fn test_list_jobs_mixed_queue_and_completed(db: Pool) -> anyhow: .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("completed_arg", json!("completed_value")) .run_until_complete(&db, false, port) @@ -290,6 +294,7 @@ async fn test_list_jobs_mixed_queue_and_completed(db: Pool) -> anyhow: .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("queued_arg", json!("queued_value")) .push(&db) @@ -375,6 +380,7 @@ async fn test_list_jobs_multiple_queued_with_include_args( .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("x", json!(1)) .push(&db) @@ -393,6 +399,7 @@ async fn test_list_jobs_multiple_queued_with_include_args( .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("y", json!(2)) .push(&db) @@ -471,6 +478,7 @@ async fn test_queue_list_without_include_args(db: Pool) -> anyhow::Res .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("x", json!(42)) .push(&db) @@ -531,6 +539,7 @@ async fn test_queue_list_with_include_args(db: Pool) -> anyhow::Result .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("x", json!(42)) .push(&db) @@ -601,6 +610,7 @@ async fn test_queue_list_multiple_jobs_with_include_args(db: Pool) -> .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("a", json!("value_a")) .push(&db) @@ -619,6 +629,7 @@ async fn test_queue_list_multiple_jobs_with_include_args(db: Pool) -> .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("b", json!("value_b")) .push(&db) @@ -698,6 +709,7 @@ async fn test_completed_list_without_include_args(db: Pool) -> anyhow: .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("x", json!(42)) .run_until_complete(&db, false, port) @@ -764,6 +776,7 @@ async fn test_completed_list_with_include_args(db: Pool) -> anyhow::Re .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("x", json!(42)) .run_until_complete(&db, false, port) @@ -839,6 +852,7 @@ async fn test_completed_list_multiple_jobs_with_include_args( .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("a", json!("completed_a")) .run_until_complete(&db, false, port) @@ -860,6 +874,7 @@ async fn test_completed_list_multiple_jobs_with_include_args( .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("b", json!("completed_b")) .run_until_complete(&db, false, port) @@ -992,6 +1007,7 @@ async fn test_job_without_labels_has_no_labels_field(db: Pool) -> anyh .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .push(&db) .await; @@ -1135,6 +1151,7 @@ async fn test_wm_labels_from_result_merged_with_static_labels( .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })); let completed = job diff --git a/backend/tests/nativets_jobs.rs b/backend/tests/nativets_jobs.rs index 5c57e5c0c8..610d0c5ea8 100644 --- a/backend/tests/nativets_jobs.rs +++ b/backend/tests/nativets_jobs.rs @@ -40,6 +40,7 @@ fn nativets_code(content: &str) -> JobPayload { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }) } diff --git a/backend/tests/nativets_stress.rs b/backend/tests/nativets_stress.rs index 8b0884a3ea..1a8827b486 100644 --- a/backend/tests/nativets_stress.rs +++ b/backend/tests/nativets_stress.rs @@ -157,6 +157,7 @@ async fn push_job(db: &Pool, content: &str, args: &serde_json::Value) cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let tx = PushIsolationLevel::IsolatedRoot(db.clone()); diff --git a/backend/tests/python_jobs.rs b/backend/tests/python_jobs.rs index e8fbb1670f..81fe2c3b55 100644 --- a/backend/tests/python_jobs.rs +++ b/backend/tests/python_jobs.rs @@ -748,6 +748,7 @@ def main(): cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -800,6 +801,7 @@ def main(): cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -837,6 +839,7 @@ def main(): cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -878,6 +881,7 @@ def main(): cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -917,6 +921,7 @@ def main(): cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port) @@ -1003,6 +1008,7 @@ async def main(item: str, qty: int, email: str): language: ScriptLang::Python3, content, ..RawCode::default() + tag: None, })) .arg("item", json!("widget")) .arg("qty", json!(5)) @@ -1188,6 +1194,7 @@ async def main(n: int): language: ScriptLang::Python3, content, ..RawCode::default() + tag: None, })) .arg("n", json!(1)) .run_until_complete(db, false, port), diff --git a/backend/tests/script_modules.rs b/backend/tests/script_modules.rs index 068555c7df..c3cc9ed87a 100644 --- a/backend/tests/script_modules.rs +++ b/backend/tests/script_modules.rs @@ -41,6 +41,7 @@ def main(name: str): language: ScriptLang::Python3, modules: Some(modules), ..RawCode::default() + tag: None, }); let result = RunJob::from(job) @@ -93,6 +94,7 @@ def main(a: int, b: int): language: ScriptLang::Python3, modules: Some(modules), ..RawCode::default() + tag: None, }); let result = RunJob::from(job) @@ -144,6 +146,7 @@ export function main(name: string) { language: ScriptLang::Bun, modules: Some(modules), ..RawCode::default() + tag: None, }); let result = RunJob::from(job) diff --git a/backend/tests/volume_tests.rs b/backend/tests/volume_tests.rs index 439bfa595a..8ecf6e98b6 100644 --- a/backend/tests/volume_tests.rs +++ b/backend/tests/volume_tests.rs @@ -597,6 +597,7 @@ export function main() { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, }); let result = run_job_in_new_worker_until_complete(&db, false, job, port).await; diff --git a/backend/tests/worker.rs b/backend/tests/worker.rs index 9f17f7223e..deef1331ea 100644 --- a/backend/tests/worker.rs +++ b/backend/tests/worker.rs @@ -885,6 +885,7 @@ func main(derp string) (string, error) { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("derp", json!("world")) .run_until_complete(&db, false, port) @@ -924,6 +925,7 @@ fn main(world: String) -> Result { cache_ttl: None, dedicated_worker: None, modules: None, + tag: None, })) .arg("world", json!("Hyrule")) .run_until_complete(&db, false, port) @@ -969,6 +971,7 @@ class Script .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("world", json!("Arakis")) .arg("b", json!(3)) @@ -1006,6 +1009,7 @@ echo "hello $msg" .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("msg", json!("world")) .run_until_complete(&db, false, port) @@ -1044,6 +1048,7 @@ echo "$result" .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .run_until_complete(&db, false, port) .await; @@ -1079,6 +1084,7 @@ echo "$result" .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .run_until_complete(&db, false, port) .await; @@ -1117,6 +1123,7 @@ main <- function(msg) { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("msg", json!("world")) .run_until_complete(&db, false, port) @@ -1155,6 +1162,7 @@ main <- function() { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .run_until_complete(&db, false, port) .await @@ -1192,6 +1200,7 @@ main <- function() { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .run_until_complete(&db, false, port) .await @@ -1229,6 +1238,7 @@ def main [ msg: string ] { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("msg", json!("world")) .run_until_complete(&db, false, port) @@ -1284,6 +1294,7 @@ def main [ .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("a", json!("3")) .arg("b", json!("null")) @@ -1348,6 +1359,7 @@ public class Main { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("a", json!(3)) .arg("b", json!(3.0)) @@ -1386,6 +1398,7 @@ export async function main(name: string): Promise { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("name", json!("world")) .run_until_complete(&db, false, port) @@ -1424,6 +1437,7 @@ export async function main(a: number, b: number): Promise { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("a", json!(3)) .arg("b", json!(7)) @@ -1463,6 +1477,7 @@ export async function main(items: string[]): Promise<{ count: number; items: str .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("items", json!(["a", "b", "c"])) .run_until_complete(&db, false, port) @@ -1502,6 +1517,7 @@ export async function main(a: Date) { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("a", json!("2024-09-24T10:00:00.000Z")) .run_until_complete(&db, false, port) @@ -1540,6 +1556,7 @@ SELECT 'hello ' || $1::text AS result; .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("name", json!("world")) .arg( @@ -1590,6 +1607,7 @@ async fn test_postgresql_cached_connection_resets_session( .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("database", db_arg.clone()) }; @@ -1676,6 +1694,7 @@ async fn test_postgresql_single_worker_session_isolation(db: Pool) -> .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("database", db_arg.clone()) }; @@ -1781,6 +1800,7 @@ async fn test_postgresql_100_jobs_cached(db: Pool) -> anyhow::Result<( .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("database", db_arg.clone()) }; @@ -2817,6 +2837,7 @@ SELECT ? AS result; .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("name", json!("world")) .arg( @@ -2858,6 +2879,7 @@ export async function main(name: string): Promise { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("name", json!("world")) .run_until_complete(&db, false, port) @@ -2894,6 +2916,7 @@ Write-Output "hello $msg" .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("msg", json!("world")) .run_until_complete(&db, false, port) @@ -2931,6 +2954,7 @@ Write-Output "$Name-$Count" .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("Name", json!("test")) .arg("Count", json!(7)) @@ -2966,6 +2990,7 @@ throw "intentional error" .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("x", json!(1)) .run_until_complete(&db, false, port) @@ -3019,6 +3044,7 @@ function main(string $name): string { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("name", json!("world")) .run_until_complete(&db, false, port) @@ -3057,6 +3083,7 @@ end .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("name", json!("world")) .run_until_complete(&db, false, port) @@ -3094,6 +3121,7 @@ export async function main(a: Date) { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("a", json!("2024-09-24T10:00:00.000Z")) .run_until_complete(&db, false, port) @@ -3131,6 +3159,7 @@ export async function main(a: Date) { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("a", json!("2024-09-24T10:00:00.000Z")) .run_until_complete(&db, false, port) @@ -3184,6 +3213,7 @@ export function main(name: string) { cache_ignore_s3_path: None, dedicated_worker: None, modules: None, + tag: None, })) .arg("name", json!("World")) .run_until_complete(&db, false, port) @@ -3230,6 +3260,7 @@ def main(a: datetime, b: bytes): .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .arg("a", json!("2024-09-24T10:00:00.000Z")) .arg("b", json!("dGVzdA==")) @@ -4872,6 +4903,7 @@ async fn test_workflow_as_code(db: Pool) -> anyhow::Result<()> { language: ScriptLang::Python3, content: WORKFLOW_AS_CODE.into(), ..RawCode::default() + tag: None, })) .arg("n", json!(3)) .run_until_complete(db, false, port), diff --git a/backend/windmill-api-integration-tests/tests/sensitive_log_masking.rs b/backend/windmill-api-integration-tests/tests/sensitive_log_masking.rs index d174f3759b..6667e3a48a 100644 --- a/backend/windmill-api-integration-tests/tests/sensitive_log_masking.rs +++ b/backend/windmill-api-integration-tests/tests/sensitive_log_masking.rs @@ -95,6 +95,7 @@ async fn push_bun_job(db: &Pool, code: String) -> Uuid { .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .push(db) .await @@ -141,6 +142,7 @@ async fn push_bun_job_with_encrypted_arg( .into(), debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .job_id(job_id) .arg(arg_name, json!(arg_value)) diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index c4ac9b4c94..d03de1e61c 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -10527,6 +10527,8 @@ paths: type: string cache_ttl: type: integer + tag: + type: string required: - content - language diff --git a/backend/windmill-api/src/apps.rs b/backend/windmill-api/src/apps.rs index bd3c53cdda..0704501953 100644 --- a/backend/windmill-api/src/apps.rs +++ b/backend/windmill-api/src/apps.rs @@ -2268,11 +2268,14 @@ async fn execute_component( // flow or script: (Some(path), None, None) => get_payload_tag_from_prefixed_path(&path, &db, &w_id).await?, // inline script: in "preview" mode or without entry in the `app_script` table. - (None, Some(raw_code), None) => (JobPayload::Code(raw_code), None, None), + (None, Some(raw_code), None) => { + let tag = raw_code.tag.clone().filter(|t| !t.is_empty()); + (JobPayload::Code(raw_code), tag, None) + } // inline script: in "run" mode and with an entry in the `app_script` table. - (None, Some(RawCode { language, path, cache_ttl, .. }), Some(id)) => ( + (None, Some(RawCode { language, path, cache_ttl, tag, .. }), Some(id)) => ( JobPayload::AppScript { id: AppScriptId(id), cache_ttl, language, path }, - None, + tag.filter(|t| !t.is_empty()), None, ), _ => unreachable!(), diff --git a/backend/windmill-api/src/jobs.rs b/backend/windmill-api/src/jobs.rs index 4afbaa12df..9907e35529 100644 --- a/backend/windmill-api/src/jobs.rs +++ b/backend/windmill-api/src/jobs.rs @@ -4595,6 +4595,7 @@ pub async fn run_workflow_as_code( // TODO(debouncing): enable for this mode debouncing_settings: DebouncingSettings::default(), modules: None, + tag: None, }), Some(job.tag.clone()), None, @@ -5716,6 +5717,7 @@ async fn run_preview_script( cache_ignore_s3_path: None, dedicated_worker: preview.dedicated_worker, modules: preview.modules, + tag: None, }), }, push_args, @@ -6058,6 +6060,7 @@ async fn run_bundle_preview_script( concurrency_settings: ConcurrencySettingsWithCustom::default(), debouncing_settings: DebouncingSettings::default(), modules: None, + tag: None, }), PushArgs::from(&args), authed.display_username(), @@ -6892,6 +6895,7 @@ async fn run_dynamic_select( concurrency_settings: ConcurrencySettings::default().into(), debouncing_settings: DebouncingSettings::default(), modules: None, + tag: None, }), PushArgs::from(&request.args.unwrap_or_default()), authed.display_username(), diff --git a/backend/windmill-queue/src/jobs.rs b/backend/windmill-queue/src/jobs.rs index 9aa3128287..998529e17e 100644 --- a/backend/windmill-queue/src/jobs.rs +++ b/backend/windmill-queue/src/jobs.rs @@ -471,6 +471,7 @@ pub async fn push_init_job<'c>( concurrency_settings: ConcurrencySettingsWithCustom::default(), debouncing_settings: DebouncingSettings::default(), modules: None, + tag: None, }), PushArgs::from(&ehm), worker_name, @@ -529,6 +530,7 @@ pub async fn push_periodic_bash_job<'c>( concurrency_settings: ConcurrencySettingsWithCustom::default(), debouncing_settings: DebouncingSettings::default(), modules: None, + tag: None, }), PushArgs::from(&ehm), worker_name, @@ -4893,6 +4895,7 @@ async fn push_inner<'c, 'd>( cache_ttl, cache_ignore_s3_path, dedicated_worker, + tag: _, concurrency_settings, debouncing_settings, modules, diff --git a/backend/windmill-test-utils/src/lib.rs b/backend/windmill-test-utils/src/lib.rs index b26eb622fa..79dcc3bd84 100644 --- a/backend/windmill-test-utils/src/lib.rs +++ b/backend/windmill-test-utils/src/lib.rs @@ -981,6 +981,7 @@ pub async fn run_preview_relative_imports( debouncing_settings: windmill_common::runnable_settings::DebouncingSettings::default(), modules: None, + tag: None, })) .push(&db2) .await; diff --git a/backend/windmill-types/src/jobs.rs b/backend/windmill-types/src/jobs.rs index 36790ffaa2..03e38d9db3 100644 --- a/backend/windmill-types/src/jobs.rs +++ b/backend/windmill-types/src/jobs.rs @@ -516,6 +516,7 @@ pub struct RawCode { pub cache_ttl: Option, pub cache_ignore_s3_path: Option, pub dedicated_worker: Option, + pub tag: Option, #[serde(flatten)] pub concurrency_settings: ConcurrencySettingsWithCustom, #[serde(flatten)] diff --git a/backend/windmill-worker/src/bun_executor.rs b/backend/windmill-worker/src/bun_executor.rs index 090b929648..be842e28b4 100644 --- a/backend/windmill-worker/src/bun_executor.rs +++ b/backend/windmill-worker/src/bun_executor.rs @@ -2511,6 +2511,7 @@ pub async fn handle_wac_v2_output( concurrency_settings: ConcurrencySettingsWithCustom::default(), debouncing_settings: DebouncingSettings::default(), modules: None, + tag: None, })) } _ => Err(error::Error::internal_err(format!( @@ -2620,6 +2621,7 @@ pub async fn handle_wac_v2_output( concurrency_settings: ConcurrencySettingsWithCustom::default(), debouncing_settings: DebouncingSettings::default(), modules: None, + tag: None, }); let step_args: HashMap> = step .args diff --git a/backend/windmill-worker/src/worker_flow.rs b/backend/windmill-worker/src/worker_flow.rs index a348ef8774..7b0038795f 100644 --- a/backend/windmill-worker/src/worker_flow.rs +++ b/backend/windmill-worker/src/worker_flow.rs @@ -5483,6 +5483,7 @@ pub fn raw_script_to_payload( // TODO: Should this have debouncing? debouncing_settings: DebouncingSettings::default(), modules: None, + tag: None, }), tag, delete_after_use, diff --git a/frontend/src/lib/components/apps/components/helpers/executeRunnable.ts b/frontend/src/lib/components/apps/components/helpers/executeRunnable.ts index 133af15153..a59f10b66b 100644 --- a/frontend/src/lib/components/apps/components/helpers/executeRunnable.ts +++ b/frontend/src/lib/components/apps/components/helpers/executeRunnable.ts @@ -12,7 +12,7 @@ export async function executeRunnable( id: string, requestBody: ExecuteComponentData['requestBody'], inlineScriptOverride?: InlineScript, - queryParams?: Record, + queryParams?: Record ) { let appPath = defaultIfEmptyString(path, `u/${username ?? 'unknown'}/newapp`) if (isRunnableByName(runnable)) { @@ -29,7 +29,8 @@ export async function executeRunnable( language: inlineScript.language ?? '', path: appPath + '/' + id, lock: inlineScript.id === undefined ? inlineScript.lock : undefined, - cache_ttl: inlineScript.cache_ttl + cache_ttl: inlineScript.cache_ttl, + ...(inlineScript.tag ? { tag: inlineScript.tag } : {}) } } } else if (isRunnableByPath(runnable)) { diff --git a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte index 802d51116f..b1af1c20f7 100644 --- a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +++ b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte @@ -22,6 +22,7 @@ import ScriptGen from '$lib/components/copilot/ScriptGen.svelte' import DiffEditor from '$lib/components/DiffEditor.svelte' import CacheTtlPopup from './CacheTtlPopup.svelte' + import TagPopup from './TagPopup.svelte' import EditorSettings from '$lib/components/EditorSettings.svelte' import { userStore, workspaceStore } from '$lib/stores' import TextInput from '$lib/components/text_input/TextInput.svelte' @@ -255,6 +256,12 @@ {/if}
{#if inlineScript} + {#if inlineScript.language != 'frontend'} + + {/if} + import { Button } from '$lib/components/common' + import { Tag } from 'lucide-svelte' + import Popover from '$lib/components/meltComponents/Popover.svelte' + import { autoPlacement } from '@floating-ui/core' + import type { ComponentProps } from 'svelte' + import WorkerTagSelect from '$lib/components/WorkerTagSelect.svelte' + + interface Props { + tag: string | undefined + btnProps?: ComponentProps + } + + let { tag = $bindable(), btnProps }: Props = $props() + + $effect(() => { + if (tag === '') tag = undefined + }) + + + + {#snippet trigger()} +