diff --git a/CHANGELOG.md b/CHANGELOG.md index 08f7c83c7c..4ffa8c6630 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## [1.419.0](https://github.com/windmill-labs/windmill/compare/v1.418.0...v1.419.0) (2024-11-06) + + +### Features + +* Add full-text search on windmill service logs ([#4576](https://github.com/windmill-labs/windmill/issues/4576)) ([77735d8](https://github.com/windmill-labs/windmill/commit/77735d859cfee9204f67a8e4f9885228d657a41d)) +* show path in flow script picker ([#4574](https://github.com/windmill-labs/windmill/issues/4574)) ([8e27392](https://github.com/windmill-labs/windmill/commit/8e27392afacbb725aaf9f9f892ab8a6171b59ce5)) +* websocket authentication ([#4635](https://github.com/windmill-labs/windmill/issues/4635)) ([4dda0fb](https://github.com/windmill-labs/windmill/commit/4dda0fb8cd8262ad3a2ab2b9d27e7043ac3bb891)) + + +### Bug Fixes + +* clarify error messages when job timeout or cancelled with more details ([771d740](https://github.com/windmill-labs/windmill/commit/771d740701902166f8b4e3f77aa9c5579237cb15)) +* **cli:** improve handling of deleted items on windows ([9a8dcc9](https://github.com/windmill-labs/windmill/commit/9a8dcc9a250caefa0b7c9523e1321599b7471c8b)) +* display logs in native mode when script fails ([#4655](https://github.com/windmill-labs/windmill/issues/4655)) ([7578ceb](https://github.com/windmill-labs/windmill/commit/7578cebaf92e729a26fd665e4b6f8357d34f59eb)) +* **frontend:** arg input json handling when the value is not of the same type as schema ([#4479](https://github.com/windmill-labs/windmill/issues/4479)) ([8d8156b](https://github.com/windmill-labs/windmill/commit/8d8156bd0773da3ddec81c46ad5fda114ecd3dda)) +* **frontend:** improve flow prop picker design ([323912c](https://github.com/windmill-labs/windmill/commit/323912c73c18d3bb6d136f2e6458389270364a0e)) + ## [1.418.0](https://github.com/windmill-labs/windmill/compare/v1.417.3...v1.418.0) (2024-11-04) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 1c2f6b1fc2..116bdc3899 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -166,9 +166,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arc-swap" @@ -966,9 +966,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.7.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e086682a53d3aa241192aa110fa8dfce98f2f5ac2ead0de84d41582c7e8fdb96" +checksum = "92165296a47a812b267b4f41032ff8069ab7ff783696d217f0994a0d7ab585cd" dependencies = [ "aws-smithy-async", "aws-smithy-types", @@ -983,9 +983,9 @@ dependencies = [ [[package]] name = "aws-smithy-types" -version = "1.2.8" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c9cdc179e6afbf5d391ab08c85eac817b51c87e1892a5edb5f7bbdc64314b4" +checksum = "4fbd94a32b3a7d55d3806fe27d98d3ad393050439dd05eb53ece36ec5e3d3510" dependencies = [ "base64-simd 0.8.0", "bytes", @@ -1599,9 +1599,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.34" +version = "1.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b9470d453346108f93a59222a9a1a5724db32d0a4727b7ab7ace4b4d822dc9" +checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70" dependencies = [ "jobserver", "libc", @@ -2554,7 +2554,7 @@ dependencies = [ "once_cell", "percent-encoding", "serde", - "sourcemap 9.0.0", + "sourcemap 9.0.1", "swc_atoms", "swc_common", "swc_config", @@ -6537,9 +6537,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e346e016eacfff12233c243718197ca12f148c84e1e84268a896699b41c71780" +checksum = "7d5a626c6807713b15cac82a6acaccd6043c9a5408c24baae07611fec3f243da" dependencies = [ "cfg_aliases", "libc", @@ -7173,9 +7173,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.38" +version = "0.38.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" dependencies = [ "bitflags 2.6.0", "errno", @@ -8016,9 +8016,9 @@ dependencies = [ [[package]] name = "sourcemap" -version = "9.0.0" +version = "9.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dab08a862c70980b8e23698b507e272317ae52a608a164a844111f5372374f1f" +checksum = "86721155737d89818020dc35713595c6e7b21016073c101e6590c47ca58c2d16" dependencies = [ "base64-simd 0.7.0", "bitvec", @@ -8506,7 +8506,7 @@ dependencies = [ "rustc-hash 1.1.0", "serde", "siphasher", - "sourcemap 9.0.0", + "sourcemap 9.0.1", "swc_allocator", "swc_atoms", "swc_eq_ignore_macros", @@ -8570,7 +8570,7 @@ dependencies = [ "num-bigint", "once_cell", "serde", - "sourcemap 9.0.0", + "sourcemap 9.0.1", "swc_allocator", "swc_atoms", "swc_common", @@ -10563,7 +10563,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windmill" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "axum", @@ -10605,7 +10605,7 @@ dependencies = [ [[package]] name = "windmill-api" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "argon2", @@ -10690,7 +10690,7 @@ dependencies = [ [[package]] name = "windmill-api-client" -version = "1.418.0" +version = "1.419.0" dependencies = [ "base64 0.22.1", "chrono", @@ -10708,7 +10708,7 @@ dependencies = [ [[package]] name = "windmill-audit" -version = "1.418.0" +version = "1.419.0" dependencies = [ "chrono", "serde", @@ -10721,7 +10721,7 @@ dependencies = [ [[package]] name = "windmill-autoscaling" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "rsmq_async", @@ -10736,7 +10736,7 @@ dependencies = [ [[package]] name = "windmill-common" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "async-stream", @@ -10782,7 +10782,7 @@ dependencies = [ [[package]] name = "windmill-git-sync" -version = "1.418.0" +version = "1.419.0" dependencies = [ "regex", "rsmq_async", @@ -10797,7 +10797,7 @@ dependencies = [ [[package]] name = "windmill-indexer" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "bytes", @@ -10819,7 +10819,7 @@ dependencies = [ [[package]] name = "windmill-macros" -version = "1.418.0" +version = "1.419.0" dependencies = [ "itertools 0.13.0", "lazy_static", @@ -10831,7 +10831,7 @@ dependencies = [ [[package]] name = "windmill-parser" -version = "1.418.0" +version = "1.419.0" dependencies = [ "convert_case 0.6.0", "serde", @@ -10840,7 +10840,7 @@ dependencies = [ [[package]] name = "windmill-parser-bash" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "lazy_static", @@ -10852,7 +10852,7 @@ dependencies = [ [[package]] name = "windmill-parser-go" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "gosyn", @@ -10864,7 +10864,7 @@ dependencies = [ [[package]] name = "windmill-parser-graphql" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "lazy_static", @@ -10876,7 +10876,7 @@ dependencies = [ [[package]] name = "windmill-parser-php" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "itertools 0.13.0", @@ -10887,7 +10887,7 @@ dependencies = [ [[package]] name = "windmill-parser-py" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "itertools 0.13.0", @@ -10898,7 +10898,7 @@ dependencies = [ [[package]] name = "windmill-parser-py-imports" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "async-recursion", @@ -10916,7 +10916,7 @@ dependencies = [ [[package]] name = "windmill-parser-rust" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "convert_case 0.6.0", @@ -10933,7 +10933,7 @@ dependencies = [ [[package]] name = "windmill-parser-sql" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "lazy_static", @@ -10945,7 +10945,7 @@ dependencies = [ [[package]] name = "windmill-parser-ts" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "lazy_static", @@ -10963,7 +10963,7 @@ dependencies = [ [[package]] name = "windmill-parser-wasm" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "getrandom 0.2.15", @@ -10984,7 +10984,7 @@ dependencies = [ [[package]] name = "windmill-parser-yaml" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "serde_json", @@ -10994,7 +10994,7 @@ dependencies = [ [[package]] name = "windmill-queue" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "async-recursion", @@ -11027,7 +11027,7 @@ dependencies = [ [[package]] name = "windmill-sql-datatype-parser-wasm" -version = "1.418.0" +version = "1.419.0" dependencies = [ "wasm-bindgen", "wasm-bindgen-test", @@ -11037,7 +11037,7 @@ dependencies = [ [[package]] name = "windmill-worker" -version = "1.418.0" +version = "1.419.0" dependencies = [ "anyhow", "async-recursion", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index b0d6e47120..c444778502 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "windmill" -version = "1.418.0" +version = "1.419.0" authors.workspace = true edition.workspace = true @@ -29,7 +29,7 @@ members = [ ] [workspace.package] -version = "1.418.0" +version = "1.419.0" authors = ["Ruben Fiszel "] edition = "2021" diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 3b0d784bd7..67e52eb9fa 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: - version: 1.418.0 + version: 1.419.0 title: Windmill API contact: diff --git a/backend/windmill-worker/src/common.rs b/backend/windmill-worker/src/common.rs index e22f9be54c..80269f7777 100644 --- a/backend/windmill-worker/src/common.rs +++ b/backend/windmill-worker/src/common.rs @@ -562,7 +562,7 @@ pub async fn resolve_job_timeout( _w_id: &str, _job_id: Uuid, custom_timeout_secs: Option, -) -> (Duration, Option) { +) -> (Duration, Option, bool) { let mut warn_msg: Option = None; #[cfg(feature = "cloud")] let cloud_premium_workspace = *CLOUD_HOSTED @@ -587,12 +587,12 @@ pub async fn resolve_job_timeout( Some(timeout_secs) if Duration::from_secs(timeout_secs as u64) < global_max_timeout_duration => { - (Duration::from_secs(timeout_secs as u64), warn_msg) + (Duration::from_secs(timeout_secs as u64), warn_msg, true) } Some(timeout_secs) => { warn_msg = Some(format!("WARNING: Custom job timeout of {timeout_secs} seconds was greater than the maximum timeout. It will be ignored and the max timeout will be used instead")); tracing::warn!(warn_msg); - (global_max_timeout_duration, warn_msg) + (global_max_timeout_duration, warn_msg, false) } None => { // fallback to default timeout or max if not set @@ -610,7 +610,7 @@ pub async fn resolve_job_timeout( global_max_timeout_duration } }; - (default_timeout, warn_msg) + (default_timeout, warn_msg, false) } } } diff --git a/backend/windmill-worker/src/handle_child.rs b/backend/windmill-worker/src/handle_child.rs index 6e7520daf8..6846e9dfee 100644 --- a/backend/windmill-worker/src/handle_child.rs +++ b/backend/windmill-worker/src/handle_child.rs @@ -143,15 +143,40 @@ pub async fn handle_child( occupancy_metrics, ); - #[derive(PartialEq, Debug)] enum KillReason { TooManyLogs, - Timeout, - Cancelled, + Timeout { is_job_specific: bool }, + Cancelled(Option), AlreadyCompleted, } - let (timeout_duration, timeout_warn_msg) = + impl std::fmt::Debug for KillReason { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + KillReason::TooManyLogs => f.write_str("too many logs (max size: 2MB)"), + KillReason::Timeout { is_job_specific } => f.write_str(if *is_job_specific { + "timeout after exceeding job-specific duration limit" + } else { + "timeout after exceeding instance-wide job duration limit" + }), + KillReason::Cancelled(canceled_by) => { + let mut reason = "cancelled".to_string(); + if let Some(canceled_by) = canceled_by { + if let Some(by) = canceled_by.username.as_ref() { + reason.push_str(&format!(" by {}", by)); + } + if let Some(rsn) = canceled_by.reason.as_ref() { + reason.push_str(&format!(" (reason: {})", rsn)); + } + } + f.write_str(&reason) + } + KillReason::AlreadyCompleted => f.write_str("already completed"), + } + } + } + + let (timeout_duration, timeout_warn_msg, is_job_specific) = resolve_job_timeout(&db, w_id, job_id, custom_timeout).await; if let Some(msg) = timeout_warn_msg { append_logs(&job_id, w_id, msg.as_str(), db).await; @@ -165,9 +190,9 @@ pub async fn handle_child( biased; result = child.wait() => return result.map(Ok), Ok(()) = too_many_logs.changed() => KillReason::TooManyLogs, - _ = sleep(timeout_duration) => KillReason::Timeout, + _ = sleep(timeout_duration) => KillReason::Timeout { is_job_specific }, ex = update_job, if job_id != Uuid::nil() => match ex { - UpdateJobPollingExit::Done => KillReason::Cancelled, + UpdateJobPollingExit::Done(canceled_by) => KillReason::Cancelled(canceled_by), UpdateJobPollingExit::AlreadyCompleted => KillReason::AlreadyCompleted, }, }; @@ -175,7 +200,7 @@ pub async fn handle_child( drop(tx); let set_reason = async { - if kill_reason == KillReason::Timeout { + if matches!(kill_reason, KillReason::Timeout { .. }) { if let Err(err) = sqlx::query( r#" UPDATE queue @@ -402,7 +427,7 @@ pub async fn handle_child( Err(Error::AlreadyCompleted("Job already completed".to_string())) } _ => Err(Error::ExecutionErr(format!( - "job process killed because {kill_reason:#?}" + "job process terminated due to {kill_reason:#?}" ))), }, Err(err) => Err(Error::ExecutionErr(format!("job process io error: {err}"))), @@ -505,7 +530,10 @@ where })?, ex = update_job, if job_id != Uuid::nil() => { match ex { - UpdateJobPollingExit::Done => Err(Error::ExecutionErr("Job cancelled".to_string())).map_err(to_anyhow)?, + UpdateJobPollingExit::Done(canceled_by) => { + let (by, reason) = canceled_by.as_ref().map_or(("unknown".to_string(), "unknown".to_string()), |x| (x.username.clone().unwrap_or("".to_string()), x.reason.clone().unwrap_or("".to_string()))); + Err(Error::ExecutionErr(format!("Job cancelled by {by} (reason: {reason})",))).map_err(to_anyhow)? + }, UpdateJobPollingExit::AlreadyCompleted => Err(Error::AlreadyCompleted("Job already completed".to_string())).map_err(to_anyhow)?, } } @@ -515,7 +543,7 @@ where } pub enum UpdateJobPollingExit { - Done, + Done(Option), AlreadyCompleted, } @@ -640,7 +668,7 @@ where } tracing::info!("job {job_id} finished"); - UpdateJobPollingExit::Done + UpdateJobPollingExit::Done(canceled_by_ref.clone()) } /// takes stdout and stderr from Child, panics if either are not present diff --git a/benchmarks/lib.ts b/benchmarks/lib.ts index 961d105aa1..85484f8915 100644 --- a/benchmarks/lib.ts +++ b/benchmarks/lib.ts @@ -2,7 +2,7 @@ import { sleep } from "https://deno.land/x/sleep@v1.2.1/mod.ts"; import * as windmill from "https://deno.land/x/windmill@v1.174.0/mod.ts"; import * as api from "https://deno.land/x/windmill@v1.174.0/windmill-api/index.ts"; -export const VERSION = "v1.418.0"; +export const VERSION = "v1.419.0"; export async function login(email: string, password: string): Promise { return await windmill.UserService.login({ diff --git a/cli/main.ts b/cli/main.ts index 92039f51f8..87dba5b461 100644 --- a/cli/main.ts +++ b/cli/main.ts @@ -60,7 +60,7 @@ export { // } // }); -export const VERSION = "1.418.0"; +export const VERSION = "1.419.0"; const command = new Command() .name("wmill") diff --git a/cli/sync.ts b/cli/sync.ts index 342dda3162..f0ec3dce2c 100644 --- a/cli/sync.ts +++ b/cli/sync.ts @@ -1398,11 +1398,12 @@ export async function push(opts: GlobalOptions & SyncOptions) { log.info(`Deleting ${typ} ${change.path}`); } const workspaceId = workspace.workspaceId; + const target = change.path.replaceAll(SEP, "/"); switch (typ) { case "script": { const script = await wmill.getScriptByPath({ workspace: workspaceId, - path: removeExtensionToPath(change.path), + path: removeExtensionToPath(target), }); await wmill.archiveScriptByHash({ workspace: workspaceId, @@ -1419,37 +1420,37 @@ export async function push(opts: GlobalOptions & SyncOptions) { case "resource": await wmill.deleteResource({ workspace: workspaceId, - path: removeSuffix(change.path, ".resource.json"), + path: removeSuffix(target, ".resource.json"), }); break; case "resource-type": await wmill.deleteResourceType({ workspace: workspaceId, - path: removeSuffix(change.path, ".resource-type.json"), + path: removeSuffix(target, ".resource-type.json"), }); break; case "flow": await wmill.deleteFlowByPath({ workspace: workspaceId, - path: removeSuffix(change.path, ".flow/flow.json"), + path: removeSuffix(target, ".flow/flow.json"), }); break; case "app": await wmill.deleteApp({ workspace: workspaceId, - path: removeSuffix(change.path, ".app/app.json"), + path: removeSuffix(target, ".app/app.json"), }); break; case "schedule": await wmill.deleteSchedule({ workspace: workspaceId, - path: removeSuffix(change.path, ".schedule.json"), + path: removeSuffix(target, ".schedule.json"), }); break; case "variable": await wmill.deleteVariable({ workspace: workspaceId, - path: removeSuffix(change.path, ".variable.json"), + path: removeSuffix(target, ".variable.json"), }); break; case "user": { diff --git a/frontend/package-lock.json b/frontend/package-lock.json index a5c5e883d1..49ea5ca116 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "windmill-components", - "version": "1.418.0", + "version": "1.419.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "windmill-components", - "version": "1.418.0", + "version": "1.419.0", "license": "AGPL-3.0", "dependencies": { "@aws-crypto/sha256-js": "^4.0.0", diff --git a/frontend/package.json b/frontend/package.json index 1716d5546a..48dca74fed 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "windmill-components", - "version": "1.418.0", + "version": "1.419.0", "scripts": { "dev": "vite dev", "build": "vite build", diff --git a/frontend/src/lib/components/InputTransformForm.svelte b/frontend/src/lib/components/InputTransformForm.svelte index 706d00b7ae..7dc11e9229 100644 --- a/frontend/src/lib/components/InputTransformForm.svelte +++ b/frontend/src/lib/components/InputTransformForm.svelte @@ -1,3 +1,12 @@ + + diff --git a/frontend/src/lib/components/flows/content/FlowConstants.svelte b/frontend/src/lib/components/flows/content/FlowConstants.svelte index df0688f177..76859bbcff 100644 --- a/frontend/src/lib/components/flows/content/FlowConstants.svelte +++ b/frontend/src/lib/components/flows/content/FlowConstants.svelte @@ -77,6 +77,8 @@ .filter(([i, f, m]) => f.length > 0) setContext('PropPickerWrapper', { + inputMatches: writable(undefined), + filteredPickableProperties: writable(undefined), focusProp: () => {}, propPickerConfig: writable(undefined), clearFocus: () => {} diff --git a/frontend/src/lib/components/flows/previousResults.ts b/frontend/src/lib/components/flows/previousResults.ts index 94c028af23..e922c55978 100644 --- a/frontend/src/lib/components/flows/previousResults.ts +++ b/frontend/src/lib/components/flows/previousResults.ts @@ -260,3 +260,40 @@ declare const approvers: string } ` } + +export function buildPrefixRegex(words: string[]): Array<{ regex: RegExp; word: string }> { + return words.map((word) => { + const prefixes: string[] = [] + for (let i = 1; i <= word.length; i++) { + prefixes.push(word.slice(0, i) + '$') + } + prefixes.push(word + '\\.') + prefixes.push(word + '\\[') + + return { + regex: new RegExp(`^(${prefixes.join('|')}).*`), + word + } + }) +} + +export function filterNestedObject(obj: any, nestedKeys: string[]) { + if (nestedKeys.length === 0) return {} + if (nestedKeys.length === 1) { + if (nestedKeys[0] === '') { + return obj + } + const regexes = buildPrefixRegex(Object.keys(obj)) + const matches = regexes.filter(({ regex }) => regex.test(nestedKeys[0])) + return Object.fromEntries( + Object.entries(obj).filter(([key]) => matches.some(({ word }) => word === key)) + ) + } + const [key, ...rest] = nestedKeys + if (obj && typeof obj === 'object' && key in obj) { + const result = {} + result[key] = filterNestedObject(obj[key], rest) + return result + } + return {} +} diff --git a/frontend/src/lib/components/flows/propPicker/PropPickerWrapper.svelte b/frontend/src/lib/components/flows/propPicker/PropPickerWrapper.svelte index c180463f36..7ff05d9b4f 100644 --- a/frontend/src/lib/components/flows/propPicker/PropPickerWrapper.svelte +++ b/frontend/src/lib/components/flows/propPicker/PropPickerWrapper.svelte @@ -11,6 +11,8 @@ export type PropPickerWrapperContext = { propPickerConfig: Writable + inputMatches: Writable<{ word: string; value: string }[] | undefined> + filteredPickableProperties: Writable focusProp: (propName: string, insertionMode: InsertionMode, onSelect: SelectCallback) => void clearFocus: () => void } @@ -37,10 +39,14 @@ export let noPadding: boolean = false const propPickerConfig = writable(undefined) + const filteredPickableProperties = writable(undefined) + const inputMatches = writable<{ word: string; value: string }[] | undefined>(undefined) const dispatch = createEventDispatcher() setContext('PropPickerWrapper', { propPickerConfig, + inputMatches, + filteredPickableProperties, focusProp: (propName, insertionMode, onSelect) => { propPickerConfig.set({ propName, diff --git a/frontend/src/lib/components/instanceSettings.ts b/frontend/src/lib/components/instanceSettings.ts index 8e38dc3816..016b5eef78 100644 --- a/frontend/src/lib/components/instanceSettings.ts +++ b/frontend/src/lib/components/instanceSettings.ts @@ -274,7 +274,7 @@ export const settings: Record = { label: 'Keep job directories', key: 'keep_job_dir', fieldType: 'boolean', - description: 'Keep Job directories after execution at /tmp/windmill//', + description: 'Keep Job directories after execution at /tmp/windmill/WORKER/JOB_ID', storage: 'setting' }, { diff --git a/frontend/src/lib/components/propertyPicker/PropPicker.svelte b/frontend/src/lib/components/propertyPicker/PropPicker.svelte index 0e27cab996..e4d598d793 100644 --- a/frontend/src/lib/components/propertyPicker/PropPicker.svelte +++ b/frontend/src/lib/components/propertyPicker/PropPicker.svelte @@ -9,6 +9,7 @@ import { keepByKey } from './utils' import type { PickableProperties } from '../flows/previousResults' import ClearableInput from '../common/clearableInput/ClearableInput.svelte' + import { filterNestedObject } from '../flows/previousResults' export let pickableProperties: PickableProperties export let displayContext = true @@ -20,18 +21,31 @@ let resources: Record = {} let displayVariable = false let displayResources = false + let allResultsCollapsed = true + let collapsableInitialState: + | { + allResultsCollapsed: boolean + displayVariable: boolean + displayResources: boolean + } + | undefined + + let filterActive = false const EMPTY_STRING = '' let search = '' - const { propPickerConfig } = getContext('PropPickerWrapper') + const { propPickerConfig, filteredPickableProperties, inputMatches } = + getContext('PropPickerWrapper') + $filteredPickableProperties = { ...pickableProperties } let flowInputsFiltered = pickableProperties.flow_input let resultByIdFiltered = pickableProperties.priorIds let timeout: NodeJS.Timeout function onSearch(search: string) { + filterActive = false clearTimeout(timeout) setTimeout(() => { flowInputsFiltered = @@ -72,29 +86,124 @@ ).map((resource) => [resource.path, resource.description ?? '']) ) } + + async function filterPickableProperties() { + if (!filterActive) { + return + } + + if (!$inputMatches?.some((match) => match.word === 'flow_input')) { + flowInputsFiltered = [] + } + if (!$inputMatches?.some((match) => match.word === 'results')) { + resultByIdFiltered = [] + } + if ($inputMatches?.length == 1) { + if ($inputMatches[0].word === 'flow_input') { + flowInputsFiltered = pickableProperties.flow_input + let [, ...nestedKeys] = $inputMatches[0].value.split('.') + let filtered = filterNestedObject(flowInputsFiltered, nestedKeys) + if (Object.keys(filtered).length > 0) { + flowInputsFiltered = filtered + } + } else if ($inputMatches[0].word === 'results') { + resultByIdFiltered = pickableProperties.priorIds + let [, ...nestedKeys] = $inputMatches[0].value.split('.') + let filtered = filterNestedObject(resultByIdFiltered, nestedKeys) + if (Object.keys(filtered).length > 0) { + resultByIdFiltered = filtered + } + } + } + + if ($filteredPickableProperties) { + resultByIdFiltered && ($filteredPickableProperties.priorIds = resultByIdFiltered) + flowInputsFiltered && ($filteredPickableProperties.flow_input = flowInputsFiltered) + } + } + + async function updateCollapsable() { + if (!$inputMatches || $inputMatches.length !== 1) { + resetCollapsable() + return + } + + if (!collapsableInitialState) { + collapsableInitialState = { allResultsCollapsed, displayVariable, displayResources } + } + + if ($inputMatches[0].word === 'variable') { + await loadVariables() + displayVariable = true + return + } + if ($inputMatches[0].word === 'resource') { + await loadResources() + displayResources = true + return + } + if ($inputMatches[0].word === 'results') { + allResultsCollapsed = false + return + } + } + + function resetCollapsable() { + if (!collapsableInitialState) { + return + } + ;({ allResultsCollapsed, displayVariable, displayResources } = collapsableInitialState) + collapsableInitialState = undefined + } + + async function updateFilterActive() { + const prev = filterActive + + filterActive = Boolean( + $inputMatches && + $inputMatches?.length > 0 && + $propPickerConfig?.insertionMode === 'insert' && + search === EMPTY_STRING + ) + + if (prev && !filterActive) { + flowInputsFiltered = pickableProperties.flow_input + resultByIdFiltered = pickableProperties.priorIds + } + } + + async function updateState() { + await updateFilterActive() + await filterPickableProperties() + await updateCollapsable() + } + + $: search, $inputMatches, $propPickerConfig, updateState()
-
-
- Flow Input -
-
-
- -
+
+ {#if flowInputsFiltered && (Object.keys(flowInputsFiltered).length > 0 || !filterActive)} +
+ Flow Input +
+
+
+ +
+ {/if} {#if error} Error -
+
0} {#if suggestedPropsFiltered && Object.keys(suggestedPropsFiltered).length > 0} Suggested Results -
+
{/if} All Results -
+
{/if} {:else} - {#if previousId} + {@const json = Object.fromEntries( + Object.entries(resultByIdFiltered).filter(([k, v]) => k == previousId) + )} + {#if previousId && Object.keys(json).length > 0} Previous Result -
+
Resume payloads -
+
{/if} {#if Object.keys(pickableProperties.priorIds).length > 0} - {#if suggestedPropsFiltered && Object.keys(suggestedPropsFiltered).length > 0} + {#if !filterActive && suggestedPropsFiltered && Object.keys(suggestedPropsFiltered).length > 0} Suggested Results -
+
{/if} -
- All Results - {#if !allResultsCollapsed} + {#if Object.keys(resultByIdFiltered).length > 0} +
+ All Results + + +
+ {/if} + {/if} + {/if} + + {#if displayContext} + {#if !filterActive || $inputMatches?.some((match) => match.word === 'variable')} +
+ Variables: + + {#if displayVariable} - {/if} - + + {:else} + + {/if} +
+ {/if} + {#if !filterActive || $inputMatches?.some((match) => match.word === 'resource')} +
+ Resources: + + {#if displayResources} + + + {:else} + + {/if}
{/if} {/if} - - {#if displayContext} -
- Variables: - - {#if displayVariable} - - - - {:else} - - {/if} -
- -
- Resources: - - {#if displayResources} - - - {:else} - - {/if} -
- {/if}
diff --git a/frontend/src/lib/components/triggers/TriggersEditor.svelte b/frontend/src/lib/components/triggers/TriggersEditor.svelte index 0c6b2ebe78..5e0cebef7a 100644 --- a/frontend/src/lib/components/triggers/TriggersEditor.svelte +++ b/frontend/src/lib/components/triggers/TriggersEditor.svelte @@ -32,9 +32,11 @@ Routes Websockets Email - Scheduled Poll + {#if isFlow} + Scheduled Poll + {/if} {#if $selectedTrigger === 'webhooks'} diff --git a/lsp/Pipfile b/lsp/Pipfile index 8e529f4349..49652909b5 100644 --- a/lsp/Pipfile +++ b/lsp/Pipfile @@ -4,8 +4,8 @@ verify_ssl = true name = "pypi" [packages] -wmill = ">=1.418.0" -wmill_pg = ">=1.418.0" +wmill = ">=1.419.0" +wmill_pg = ">=1.419.0" sendgrid = "*" mysql-connector-python = "*" pymongo = "*" diff --git a/openflow.openapi.yaml b/openflow.openapi.yaml index a96d3ac217..57864131bf 100644 --- a/openflow.openapi.yaml +++ b/openflow.openapi.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: - version: 1.418.0 + version: 1.419.0 title: OpenFlow Spec contact: name: Ruben Fiszel diff --git a/powershell-client/WindmillClient/WindmillClient.psd1 b/powershell-client/WindmillClient/WindmillClient.psd1 index f530a19563..e73338005f 100644 --- a/powershell-client/WindmillClient/WindmillClient.psd1 +++ b/powershell-client/WindmillClient/WindmillClient.psd1 @@ -12,7 +12,7 @@ RootModule = 'WindmillClient.psm1' # Version number of this module. -ModuleVersion = '1.418.0' +ModuleVersion = '1.419.0' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/python-client/wmill/pyproject.toml b/python-client/wmill/pyproject.toml index 651786ca82..e07c0b6b25 100644 --- a/python-client/wmill/pyproject.toml +++ b/python-client/wmill/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "wmill" -version = "1.418.0" +version = "1.419.0" description = "A client library for accessing Windmill server wrapping the Windmill client API" license = "Apache-2.0" homepage = "https://windmill.dev" diff --git a/python-client/wmill_pg/pyproject.toml b/python-client/wmill_pg/pyproject.toml index 85e436d451..72688f686a 100644 --- a/python-client/wmill_pg/pyproject.toml +++ b/python-client/wmill_pg/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "wmill-pg" -version = "1.418.0" +version = "1.419.0" description = "An extension client for the wmill client library focused on pg" license = "Apache-2.0" homepage = "https://windmill.dev" diff --git a/typescript-client/jsr.json b/typescript-client/jsr.json index 58d900b091..396c44c06b 100644 --- a/typescript-client/jsr.json +++ b/typescript-client/jsr.json @@ -1,6 +1,6 @@ { "name": "@windmill/windmill", - "version": "1.418.0", + "version": "1.419.0", "exports": "./src/index.ts", "publish": { "exclude": ["!src", "./s3Types.ts", "./client.ts"] diff --git a/typescript-client/package.json b/typescript-client/package.json index 5767d560c9..8e0b78b11d 100644 --- a/typescript-client/package.json +++ b/typescript-client/package.json @@ -1,7 +1,7 @@ { "name": "windmill-client", "description": "Windmill SDK client for browsers and Node.js", - "version": "1.418.0", + "version": "1.419.0", "author": "Ruben Fiszel", "license": "Apache 2.0", "devDependencies": { diff --git a/version.txt b/version.txt index 0a0c0912c6..c3911f1102 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.418.0 +1.419.0