From 71fc31c4718a98211e0ce1dd4f18e8bc4cb6c2b7 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Tue, 3 Dec 2024 23:10:21 +0100 Subject: [PATCH 01/34] improve draft only delete security --- ...43061932dc5b4b17cf13d5cf8d833aedbe6d5.json | 2 +- ...5753b86a4ad239708851c998ff5620ebca5b8.json | 14 --------- ...06aaa6d6a8940017a1172403ca9851d0f13a7.json | 22 -------------- ...b32cbde4240e143df1c980843dcdfeef3499e.json | 28 ------------------ ...0560bacd55c6ae9fafcbb0239163a3d7f3c0c.json | 22 -------------- ...2b5f818a4274ba223f905e68280b86b24fa25.json | 27 ----------------- ...7f5033b9c9afc344d9c3e385ba20a3ad2197a.json | 2 +- ...11480ff040bb987a48b6f66522bc9b7e2c1d8.json | 28 ------------------ ...120444af65b1dc43a234821cde5bf6bf8b74f.json | 27 ----------------- ...160ad1962668fc3305d8e80ae91ef73614a80.json | 2 +- backend/windmill-api/src/scripts.rs | 29 ++++++++++++++----- backend/windmill-worker/src/job_logger_ee.rs | 17 ++++++++--- 12 files changed, 37 insertions(+), 183 deletions(-) delete mode 100644 backend/.sqlx/query-062859f1d0e5cfba3115f4241115753b86a4ad239708851c998ff5620ebca5b8.json delete mode 100644 backend/.sqlx/query-113b120ae10ea4469ec3575dc3506aaa6d6a8940017a1172403ca9851d0f13a7.json delete mode 100644 backend/.sqlx/query-15a5db0202c61ed187d9594311cb32cbde4240e143df1c980843dcdfeef3499e.json delete mode 100644 backend/.sqlx/query-3d77e5b691dab38b3e39477ed980560bacd55c6ae9fafcbb0239163a3d7f3c0c.json delete mode 100644 backend/.sqlx/query-5ac7c9eb3ce21e46f90e23435562b5f818a4274ba223f905e68280b86b24fa25.json delete mode 100644 backend/.sqlx/query-8653373c2c8301c902e21e8bf5a11480ff040bb987a48b6f66522bc9b7e2c1d8.json delete mode 100644 backend/.sqlx/query-aa98ab0e4b9a0eb41a804ab047a120444af65b1dc43a234821cde5bf6bf8b74f.json diff --git a/backend/.sqlx/query-02424907504848e983bfa89eec343061932dc5b4b17cf13d5cf8d833aedbe6d5.json b/backend/.sqlx/query-02424907504848e983bfa89eec343061932dc5b4b17cf13d5cf8d833aedbe6d5.json index 043d236a6b..c8b5e3086f 100644 --- a/backend/.sqlx/query-02424907504848e983bfa89eec343061932dc5b4b17cf13d5cf8d833aedbe6d5.json +++ b/backend/.sqlx/query-02424907504848e983bfa89eec343061932dc5b4b17cf13d5cf8d833aedbe6d5.json @@ -5,7 +5,7 @@ "columns": [ { "ordinal": 0, - "name": "bool", + "name": "?column?", "type_info": "Bool" } ], diff --git a/backend/.sqlx/query-062859f1d0e5cfba3115f4241115753b86a4ad239708851c998ff5620ebca5b8.json b/backend/.sqlx/query-062859f1d0e5cfba3115f4241115753b86a4ad239708851c998ff5620ebca5b8.json deleted file mode 100644 index 9803b76cea..0000000000 --- a/backend/.sqlx/query-062859f1d0e5cfba3115f4241115753b86a4ad239708851c998ff5620ebca5b8.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "UPDATE queue SET last_ping = now() WHERE id = $1", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Uuid" - ] - }, - "nullable": [] - }, - "hash": "062859f1d0e5cfba3115f4241115753b86a4ad239708851c998ff5620ebca5b8" -} diff --git a/backend/.sqlx/query-113b120ae10ea4469ec3575dc3506aaa6d6a8940017a1172403ca9851d0f13a7.json b/backend/.sqlx/query-113b120ae10ea4469ec3575dc3506aaa6d6a8940017a1172403ca9851d0f13a7.json deleted file mode 100644 index 64ec588ffa..0000000000 --- a/backend/.sqlx/query-113b120ae10ea4469ec3575dc3506aaa6d6a8940017a1172403ca9851d0f13a7.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT flow as \"flow!: sqlx::types::Json>\" FROM flow_node WHERE id = $1 LIMIT 1", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "flow!: sqlx::types::Json>", - "type_info": "Jsonb" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - true - ] - }, - "hash": "113b120ae10ea4469ec3575dc3506aaa6d6a8940017a1172403ca9851d0f13a7" -} diff --git a/backend/.sqlx/query-15a5db0202c61ed187d9594311cb32cbde4240e143df1c980843dcdfeef3499e.json b/backend/.sqlx/query-15a5db0202c61ed187d9594311cb32cbde4240e143df1c980843dcdfeef3499e.json deleted file mode 100644 index d06eadbccf..0000000000 --- a/backend/.sqlx/query-15a5db0202c61ed187d9594311cb32cbde4240e143df1c980843dcdfeef3499e.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT lock, code AS \"code!: String\" FROM flow_node WHERE id = $1", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "lock", - "type_info": "Text" - }, - { - "ordinal": 1, - "name": "code!: String", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - true, - true - ] - }, - "hash": "15a5db0202c61ed187d9594311cb32cbde4240e143df1c980843dcdfeef3499e" -} diff --git a/backend/.sqlx/query-3d77e5b691dab38b3e39477ed980560bacd55c6ae9fafcbb0239163a3d7f3c0c.json b/backend/.sqlx/query-3d77e5b691dab38b3e39477ed980560bacd55c6ae9fafcbb0239163a3d7f3c0c.json deleted file mode 100644 index edaec50386..0000000000 --- a/backend/.sqlx/query-3d77e5b691dab38b3e39477ed980560bacd55c6ae9fafcbb0239163a3d7f3c0c.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT flow AS \"flow!: Json>\" FROM flow_node WHERE id = $1 LIMIT 1", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "flow!: Json>", - "type_info": "Jsonb" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - true - ] - }, - "hash": "3d77e5b691dab38b3e39477ed980560bacd55c6ae9fafcbb0239163a3d7f3c0c" -} diff --git a/backend/.sqlx/query-5ac7c9eb3ce21e46f90e23435562b5f818a4274ba223f905e68280b86b24fa25.json b/backend/.sqlx/query-5ac7c9eb3ce21e46f90e23435562b5f818a4274ba223f905e68280b86b24fa25.json deleted file mode 100644 index 11c522e70d..0000000000 --- a/backend/.sqlx/query-5ac7c9eb3ce21e46f90e23435562b5f818a4274ba223f905e68280b86b24fa25.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n WITH existing AS (\n SELECT id FROM flow_node\n WHERE hash = $1 AND path = $2 AND workspace_id = $3 AND code = $4 AND lock = $5 AND (flow IS NOT DISTINCT FROM $6)\n LIMIT 1\n ),\n inserted AS (\n INSERT INTO flow_node (hash, path, workspace_id, code, lock, flow)\n VALUES ($1, $2, $3, $4, $5, $6)\n ON CONFLICT DO NOTHING\n RETURNING id\n )\n SELECT id FROM existing\n UNION ALL\n SELECT id FROM inserted\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Int8", - "Text", - "Text", - "Text", - "Text", - "Jsonb" - ] - }, - "nullable": [ - null - ] - }, - "hash": "5ac7c9eb3ce21e46f90e23435562b5f818a4274ba223f905e68280b86b24fa25" -} diff --git a/backend/.sqlx/query-661f472ff3860983322162420457f5033b9c9afc344d9c3e385ba20a3ad2197a.json b/backend/.sqlx/query-661f472ff3860983322162420457f5033b9c9afc344d9c3e385ba20a3ad2197a.json index 1fa370e682..75b8108281 100644 --- a/backend/.sqlx/query-661f472ff3860983322162420457f5033b9c9afc344d9c3e385ba20a3ad2197a.json +++ b/backend/.sqlx/query-661f472ff3860983322162420457f5033b9c9afc344d9c3e385ba20a3ad2197a.json @@ -5,7 +5,7 @@ "columns": [ { "ordinal": 0, - "name": "bool", + "name": "?column?", "type_info": "Bool" } ], diff --git a/backend/.sqlx/query-8653373c2c8301c902e21e8bf5a11480ff040bb987a48b6f66522bc9b7e2c1d8.json b/backend/.sqlx/query-8653373c2c8301c902e21e8bf5a11480ff040bb987a48b6f66522bc9b7e2c1d8.json deleted file mode 100644 index f57226bfa9..0000000000 --- a/backend/.sqlx/query-8653373c2c8301c902e21e8bf5a11480ff040bb987a48b6f66522bc9b7e2c1d8.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT lock, code AS \"code!: String\" FROM flow_node WHERE id = $1 LIMIT 1", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "lock", - "type_info": "Text" - }, - { - "ordinal": 1, - "name": "code!: String", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - true, - true - ] - }, - "hash": "8653373c2c8301c902e21e8bf5a11480ff040bb987a48b6f66522bc9b7e2c1d8" -} diff --git a/backend/.sqlx/query-aa98ab0e4b9a0eb41a804ab047a120444af65b1dc43a234821cde5bf6bf8b74f.json b/backend/.sqlx/query-aa98ab0e4b9a0eb41a804ab047a120444af65b1dc43a234821cde5bf6bf8b74f.json deleted file mode 100644 index d70e81e786..0000000000 --- a/backend/.sqlx/query-aa98ab0e4b9a0eb41a804ab047a120444af65b1dc43a234821cde5bf6bf8b74f.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n WITH existing AS (\n SELECT id FROM flow_node\n WHERE hash = $1 AND path = $2 AND workspace_id = $3 AND code = $4 AND lock = $5 AND flow = $6\n LIMIT 1\n ),\n inserted AS (\n INSERT INTO flow_node (hash, path, workspace_id, code, lock, flow)\n VALUES ($1, $2, $3, $4, $5, $6)\n ON CONFLICT DO NOTHING\n RETURNING id\n )\n SELECT id FROM existing\n UNION ALL\n SELECT id FROM inserted\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Int8", - "Text", - "Text", - "Text", - "Text", - "Jsonb" - ] - }, - "nullable": [ - null - ] - }, - "hash": "aa98ab0e4b9a0eb41a804ab047a120444af65b1dc43a234821cde5bf6bf8b74f" -} diff --git a/backend/.sqlx/query-d6615719bf8db4b333ed55c9a3c160ad1962668fc3305d8e80ae91ef73614a80.json b/backend/.sqlx/query-d6615719bf8db4b333ed55c9a3c160ad1962668fc3305d8e80ae91ef73614a80.json index 103219fe05..271c395f9a 100644 --- a/backend/.sqlx/query-d6615719bf8db4b333ed55c9a3c160ad1962668fc3305d8e80ae91ef73614a80.json +++ b/backend/.sqlx/query-d6615719bf8db4b333ed55c9a3c160ad1962668fc3305d8e80ae91ef73614a80.json @@ -5,7 +5,7 @@ "columns": [ { "ordinal": 0, - "name": "bool", + "name": "?column?", "type_info": "Bool" } ], diff --git a/backend/windmill-api/src/scripts.rs b/backend/windmill-api/src/scripts.rs index 2f8c54232b..ba21c688e4 100644 --- a/backend/windmill-api/src/scripts.rs +++ b/backend/windmill-api/src/scripts.rs @@ -1439,14 +1439,27 @@ async fn delete_script_by_path( require_admin(authed.is_admin, &authed.username)?; } - let script = sqlx::query_scalar!( - "DELETE FROM script WHERE path = $1 AND workspace_id = $2 RETURNING path", - path, - w_id - ) - .fetch_one(&db) - .await - .map_err(|e| Error::InternalErr(format!("deleting script by path {w_id}: {e:#}")))?; + let script = if !draft_only { + require_admin(authed.is_admin, &authed.username)?; + sqlx::query_scalar!( + "DELETE FROM script WHERE path = $1 AND workspace_id = $2 RETURNING path", + path, + w_id + ) + .fetch_one(&db) + .await + .map_err(|e| Error::InternalErr(format!("deleting script by path {w_id}: {e:#}")))? + } else { + // If the script is draft only, we can delete it without admin permissions but we still need write permissions + sqlx::query_scalar!( + "DELETE FROM script WHERE path = $1 AND workspace_id = $2 RETURNING path", + path, + w_id + ) + .fetch_one(&mut *tx) + .await + .map_err(|e| Error::InternalErr(format!("deleting script by path {w_id}: {e:#}")))? + }; sqlx::query!( "DELETE FROM draft WHERE path = $1 AND workspace_id = $2 AND typ = 'script'", diff --git a/backend/windmill-worker/src/job_logger_ee.rs b/backend/windmill-worker/src/job_logger_ee.rs index e0758b31f3..5414ccd496 100644 --- a/backend/windmill-worker/src/job_logger_ee.rs +++ b/backend/windmill-worker/src/job_logger_ee.rs @@ -8,7 +8,14 @@ use windmill_common::DB; use crate::job_logger::CompactLogs; #[cfg(all(feature = "enterprise", feature = "parquet"))] -pub(crate) async fn s3_storage(_job_id: Uuid, _w_id: &String, _db: &sqlx::Pool, _logs: &String, _total_size: &Arc, _worker_name: &String) { +pub(crate) async fn s3_storage( + _job_id: Uuid, + _w_id: &String, + _db: &sqlx::Pool, + _logs: &String, + _total_size: &Arc, + _worker_name: &String, +) { tracing::info!("Logs length of {job_id} has exceeded a threshold. Implementation to store excess on s3 in not OSS"); } @@ -24,7 +31,9 @@ pub(crate) async fn default_disk_log_storage( tracing::info!("Logs length of {job_id} has exceeded a threshold. Implementation to store excess on disk in not OSS"); } - -pub(crate) fn process_streaming_log_lines(r: Result, io::Error>, _stderr: bool) -> Option> { +pub(crate) fn process_streaming_log_lines( + r: Result, io::Error>, + _stderr: bool, +) -> Option> { r.transpose() -} \ No newline at end of file +} From 7642b1121e0a5711840abf73580bc8a784e947d6 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Wed, 4 Dec 2024 07:11:31 +0100 Subject: [PATCH 02/34] nit editors --- frontend/src/lib/components/Editor.svelte | 2 ++ frontend/src/lib/components/ScriptEditor.svelte | 3 ++- frontend/src/lib/components/SimpleEditor.svelte | 2 ++ frontend/src/lib/components/TemplateEditor.svelte | 7 ++++--- .../settingsPanel/inputEditor/EvalV2InputEditor.svelte | 5 +++-- .../components/flows/content/FlowModuleComponent.svelte | 1 + frontend/src/lib/editorUtils.ts | 7 ++++--- 7 files changed, 18 insertions(+), 9 deletions(-) diff --git a/frontend/src/lib/components/Editor.svelte b/frontend/src/lib/components/Editor.svelte index 68a58a989b..ba23b76fdc 100644 --- a/frontend/src/lib/components/Editor.svelte +++ b/frontend/src/lib/components/Editor.svelte @@ -214,6 +214,7 @@ export let small = false export let scriptLang: Preview['language'] | 'bunnative' export let disabled: boolean = false + export let lineNumbersMinChars = 3 const rHash = randomHash() $: filePath = computePath(path) @@ -1131,6 +1132,7 @@ ...editorConfig(code, lang, automaticLayout, fixedOverflowWidgets), model, fontSize: !small ? 14 : 12, + lineNumbersMinChars, // overflowWidgetsDomNode: widgets, tabSize: lang == 'python' ? 4 : 2, folding diff --git a/frontend/src/lib/components/ScriptEditor.svelte b/frontend/src/lib/components/ScriptEditor.svelte index 3e1009d0d9..8adff7f21e 100644 --- a/frontend/src/lib/components/ScriptEditor.svelte +++ b/frontend/src/lib/components/ScriptEditor.svelte @@ -317,9 +317,10 @@ -
+
{#key lang} { diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/EvalV2InputEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/EvalV2InputEditor.svelte index 5296fbc21c..6072e2569b 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/EvalV2InputEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/EvalV2InputEditor.svelte @@ -133,8 +133,9 @@
{/if} (fullscreen = true)}> {#if focus}
diff --git a/frontend/src/lib/components/flows/content/FlowModuleComponent.svelte b/frontend/src/lib/components/flows/content/FlowModuleComponent.svelte index 97801d24ab..e5992f4ab5 100644 --- a/frontend/src/lib/components/flows/content/FlowModuleComponent.svelte +++ b/frontend/src/lib/components/flows/content/FlowModuleComponent.svelte @@ -303,6 +303,7 @@ {#if !noEditor} {#key flowModule.id} Date: Wed, 4 Dec 2024 14:07:29 +0100 Subject: [PATCH 03/34] Trigger panels texts + doclinks (#4796) * Trigger panels texts + doclinks * create description component * Description module workspace settings * Delete package-lock.json --------- Co-authored-by: Guilhem --- .../src/lib/components/Description.svelte | 10 ++ .../lib/components/RunPageSchedules.svelte | 21 ++- .../details/EmailTriggerPanel.svelte | 6 + .../triggers/KafkaTriggersPanel.svelte | 117 +++++++------- .../components/triggers/RoutesPanel.svelte | 7 +- .../triggers/ScheduledPollPanel.svelte | 12 +- .../components/triggers/WebhooksPanel.svelte | 27 ++-- .../triggers/WebsocketTriggersPanel.svelte | 107 +++++++------ .../(logged)/workspace_settings/+page.svelte | 149 ++++++------------ 9 files changed, 219 insertions(+), 237 deletions(-) create mode 100644 frontend/src/lib/components/Description.svelte diff --git a/frontend/src/lib/components/Description.svelte b/frontend/src/lib/components/Description.svelte new file mode 100644 index 0000000000..59e233aaa8 --- /dev/null +++ b/frontend/src/lib/components/Description.svelte @@ -0,0 +1,10 @@ + + +
+ + {#if link} + Learn more + {/if} +
diff --git a/frontend/src/lib/components/RunPageSchedules.svelte b/frontend/src/lib/components/RunPageSchedules.svelte index e7d5e68f79..f953d160a5 100644 --- a/frontend/src/lib/components/RunPageSchedules.svelte +++ b/frontend/src/lib/components/RunPageSchedules.svelte @@ -14,6 +14,7 @@ import Toggle from './Toggle.svelte' import { loadSchedules, saveSchedule } from './flows/scheduleUtils' import { type Writable, writable } from 'svelte/store' + import Description from '$lib/components/Description.svelte' export let schema: any export let isFlow: boolean @@ -48,14 +49,18 @@ } - { - updateSchedules(true) - }} - bind:this={scheduleEditor} -/> -
+ + Run scripts and flows automatically on a recurring basis using cron expressions. Each script or + flow can have multiple schedules, with one designated as primary. + + { + updateSchedules(true) + }} + bind:this={scheduleEditor} + /> + {#if $primarySchedule == undefined} {:else if $primarySchedule} @@ -163,7 +168,7 @@ }} variant="contained" color="dark" - size="md" + size="sm" startIcon={{ icon: Calendar }} > Set Primary Schedule diff --git a/frontend/src/lib/components/details/EmailTriggerPanel.svelte b/frontend/src/lib/components/details/EmailTriggerPanel.svelte index fca824946f..0eb69d12bb 100644 --- a/frontend/src/lib/components/details/EmailTriggerPanel.svelte +++ b/frontend/src/lib/components/details/EmailTriggerPanel.svelte @@ -17,6 +17,7 @@ import Label from '$lib/components/Label.svelte' import TriggerTokens from '../triggers/TriggerTokens.svelte' let userSettings: UserSettings + import Description from '$lib/components/Description.svelte' export let token: string export let scopes: string[] = [] @@ -79,6 +80,11 @@ />
+ + Email triggers execute scripts and flows when emails are sent to specific addresses. Each + trigger has its own unique email address that can be used to invoke the script or flow. + + {#if loading} {:else} diff --git a/frontend/src/lib/components/triggers/KafkaTriggersPanel.svelte b/frontend/src/lib/components/triggers/KafkaTriggersPanel.svelte index fa52e2b72e..e4d247d084 100644 --- a/frontend/src/lib/components/triggers/KafkaTriggersPanel.svelte +++ b/frontend/src/lib/components/triggers/KafkaTriggersPanel.svelte @@ -10,6 +10,7 @@ import KafkaTriggerEditor from './KafkaTriggerEditor.svelte' import { isCloudHosted } from '$lib/cloud' import KafkaIcon from '../icons/KafkaIcon.svelte' + import Description from '$lib/components/Description.svelte' export let isFlow: boolean export let path: string @@ -47,60 +48,66 @@ bind:this={kafkaTriggerEditor} /> -{#if !$enterpriseLicense} - - Kafka triggers are an enterprise only feature. - -{:else if isCloudHosted()} - - Kafka triggers are disabled in the multi-tenant cloud. - -{:else} -
- {#if newItem} - - Deploy the {isFlow ? 'flow' : 'script'} to add kafka triggers. - - {:else} - - {#if kafkaTriggers} - {#if kafkaTriggers.length == 0} -
No kafka triggers
- {:else} -
- {#each kafkaTriggers as kafkaTrigger (kafkaTrigger.path)} -
-
{kafkaTrigger.path}
-
- {kafkaTrigger.kafka_resource_path} -
-
- -
-
- {/each} -
- {/if} +
+ + Kafka triggers execute scripts and flows in response to messages published to Kafka topics. + + + {#if !$enterpriseLicense} + + Kafka triggers are an enterprise only feature. + + {:else if isCloudHosted()} + + Kafka triggers are disabled in the multi-tenant cloud. + + {:else} +
+ {#if newItem} + + Deploy the {isFlow ? 'flow' : 'script'} to add kafka triggers. + {:else} - + + {#if kafkaTriggers} + {#if kafkaTriggers.length == 0} +
No kafka triggers
+ {:else} +
+ {#each kafkaTriggers as kafkaTrigger (kafkaTrigger.path)} +
+
{kafkaTrigger.path}
+
+ {kafkaTrigger.kafka_resource_path} +
+
+ +
+
+ {/each} +
+ {/if} + {:else} + + {/if} {/if} - {/if} -
-{/if} +
+ {/if} +
diff --git a/frontend/src/lib/components/triggers/RoutesPanel.svelte b/frontend/src/lib/components/triggers/RoutesPanel.svelte index 12feac5bd8..425b9dd9c7 100644 --- a/frontend/src/lib/components/triggers/RoutesPanel.svelte +++ b/frontend/src/lib/components/triggers/RoutesPanel.svelte @@ -10,7 +10,7 @@ import Alert from '../common/alert/Alert.svelte' import type { TriggerContext } from '../triggers' import { getContext } from 'svelte' - + import Description from '$lib/components/Description.svelte' export let isFlow: boolean export let path: string export let newItem: boolean = false @@ -48,6 +48,11 @@ />
+ + Routes expose your scripts and flows as HTTP endpoints. Each route can be configured with a + specific HTTP method and path. + + {#if !newItem} {#if $userStore?.is_admin || $userStore?.is_super_admin} - {#if wsTriggers.length == 0} -
No WS triggers
+
+ + Websocket triggers allow real-time bidirectional communication between your scripts/flows and + external systems. Each trigger creates a unique websocket endpoint. + + + {#if isCloudHosted()} + + Websocket triggers are disabled in the multi-tenant cloud. + + {:else} +
+ {#if newItem} + + Deploy the {isFlow ? 'flow' : 'script'} to add WS triggers. + + {:else if wsTriggers} + + {#if wsTriggers.length == 0} +
No WS triggers
+ {:else} +
+ {#each wsTriggers as wsTriggers (wsTriggers.path)} +
+
{wsTriggers.path}
+
+ {wsTriggers.url} +
+
+ +
+
+ {/each} +
+ {/if} {:else} -
- {#each wsTriggers as wsTriggers (wsTriggers.path)} -
-
{wsTriggers.path}
-
- {wsTriggers.url} -
-
- -
-
- {/each} -
+ {/if} - {:else} - - {/if} -
-{/if} +
+ {/if} +
diff --git a/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte b/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte index 6e9ba1d116..36bfda9a2d 100644 --- a/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte @@ -66,6 +66,7 @@ import ToggleButtonGroup from '$lib/components/common/toggleButton-v2/ToggleButtonGroup.svelte' import ToggleButton from '$lib/components/common/toggleButton-v2/ToggleButton.svelte' import type { AiProviderTypes } from '$lib/components/copilot/lib' + import Description from '$lib/components/Description.svelte' type GitSyncTypeMap = { scripts: boolean @@ -693,18 +694,12 @@ {:else if tab == 'deploy_to'}
-
+
Link this workspace to another Staging / Prod workspace
-
- Connecting this workspace with another staging/production workspace enables web-based - deployment to that workspace. - Learn more. -
+ + Connecting this workspace with another staging/production workspace enables web-based deployment to that workspace. +
{#if $enterpriseLicense} @@ -722,15 +717,10 @@
Connect workspace to Slack
-
+ Connect your Windmill workspace to your Slack workspace to trigger a script or a flow with a '/windmill' command or to configure Slack error handlers. - Learn more. -
+
{#if team_name} @@ -891,15 +881,10 @@
Workspace Webhook
-
+ Connect your Windmill workspace to an external service to sync or get notified about any change. - Learn more. -
+
@@ -926,20 +911,15 @@ {/if}
-
Workspace Error Handler
-
+
Workspace Error Handler
+ Define a script or flow to be executed automatically in case of error in the workspace. - Learn more. -
+
-
+
Script or flow to run as error handler
@@ -1001,16 +981,10 @@
-
Workspace Critical Alerts
-
- Critical alerts within the scope of a workspace are sent to the workspace admins through - a UI notification. - Learn more. -
+
Workspace Critical Alerts
+ + Critical alerts within the scope of a workspace are sent to the workspace admins through a UI notification. +
{ aiResourceInitialPath = '' + aiResourceInitialProvider = '' }} > @@ -1091,18 +1061,10 @@ {:else if tab == 'windmill_lfs'}
-
Workspace object storage (S3/Azure Blob)
-
- Connect your Windmill workspace to your S3 bucket or your Azure Blob storage to enable - users to read and write from S3 without having to have access to the credentials. - Learn more. -
+
Workspace object storage (S3/Azure Blob)
+ + Connect your Windmill workspace to your S3 bucket or your Azure Blob storage to enable users to read and write from S3 without having to have access to the credentials. +
{#if !$enterpriseLicense} @@ -1278,16 +1240,10 @@ {:else if tab == 'git_sync'}
-
Git Sync
-
- Connect the Windmill workspace to a Git repository to automatically commit and push - scripts, flows, and apps to the repository on each deploy. - Learn more. -
+
Git Sync
+ + Connect the Windmill workspace to a Git repository to automatically commit and push scripts, flows, and apps to the repository on each deploy. +
{#if !$enterpriseLicense} @@ -1732,20 +1688,13 @@ git push
-
Workspace default app
-
- If configured, users who are operators in this workspace will be redirected to this app - automatically when logging into this workspace. -
-
- Make sure the default app is shared with all the operators of this workspace before - turning this feature on. - Learn more. -
+
Workspace default app
+ + If configured, users who are operators in this workspace will be redirected to this app automatically when logging into this workspace. + + + Make sure the default app is shared with all the operators of this workspace before turning this feature on. +
{#if !$enterpriseLicense} @@ -1771,21 +1720,13 @@ git push
-
Workspace secret encryption
-
- When updating the encryption key of a workspace, all secrets will be re-encrypted with - the new key and the previous key will be replaced by the new one. -
-
- If you're manually updating the key to match another workspace key from another Windmill - instance, make sure not to use the 'SECRET_SALT' environment variable or, if you're - using it, make sure it the salt matches across both instances. - Learn more. -
+
Workspace secret encryption
+ + When updating the encryption key of a workspace, all secrets will be re-encrypted with the new key and the previous key will be replaced by the new one. + + + If you're manually updating the key to match another workspace key from another Windmill instance, make sure not to use the 'SECRET_SALT' environment variable or, if you're using it, make sure it the salt matches across both instances. +
From 4efa9c2b0a03a559a583e581135397d84724aad8 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Wed, 4 Dec 2024 14:11:44 +0100 Subject: [PATCH 04/34] chore(main): release 1.434.2 (#4836) * chore(main): release 1.434.2 * Apply automatic changes --------- Co-authored-by: rubenfiszel --- CHANGELOG.md | 7 + backend/Cargo.lock | 386 +++++++++--------- backend/Cargo.toml | 4 +- backend/windmill-api/openapi.yaml | 2 +- benchmarks/lib.ts | 2 +- cli/main.ts | 2 +- frontend/package-lock.json | 4 +- frontend/package.json | 2 +- lsp/Pipfile | 4 +- openflow.openapi.yaml | 2 +- .../WindmillClient/WindmillClient.psd1 | 2 +- python-client/wmill/pyproject.toml | 2 +- python-client/wmill_pg/pyproject.toml | 2 +- typescript-client/jsr.json | 2 +- typescript-client/package.json | 2 +- version.txt | 2 +- 16 files changed, 222 insertions(+), 205 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 656fb77d8a..29628db02c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [1.434.2](https://github.com/windmill-labs/windmill/compare/v1.434.1...v1.434.2) (2024-12-04) + + +### Bug Fixes + +* custom http routes auth ([#4835](https://github.com/windmill-labs/windmill/issues/4835)) ([02611e4](https://github.com/windmill-labs/windmill/commit/02611e42e1b5c81d9bc57e3b46795e4c8cad67f7)) + ## [1.434.1](https://github.com/windmill-labs/windmill/compare/v1.434.0...v1.434.1) (2024-11-29) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 2e176de462..54facad0c1 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android-tzdata" @@ -166,9 +166,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "arc-swap" @@ -359,7 +359,7 @@ dependencies = [ "arrow-schema", "chrono", "half", - "indexmap 2.6.0", + "indexmap 2.7.0", "lexical-core", "num", "serde", @@ -441,7 +441,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -499,7 +499,7 @@ checksum = "021cf450e9574793e45e1044a5d3d94bba7dbaa0802e6122e9c10eb8c4dd12dc" dependencies = [ "base64 0.22.1", "bytes", - "http 1.1.0", + "http 1.2.0", "rand 0.8.5", "reqwest 0.12.9", "serde", @@ -518,7 +518,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -540,7 +540,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -576,7 +576,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -641,7 +641,7 @@ dependencies = [ "aws-sdk-sts", "aws-smithy-async", "aws-smithy-http", - "aws-smithy-json", + "aws-smithy-json 0.60.7", "aws-smithy-runtime", "aws-smithy-runtime-api", "aws-smithy-types", @@ -672,9 +672,9 @@ dependencies = [ [[package]] name = "aws-runtime" -version = "1.4.3" +version = "1.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a10d5c055aa540164d9561a0e2e74ad30f0dcf7393c3a92f6733ddf9c5762468" +checksum = "b5ac934720fbb46206292d2c75b57e67acfc56fe7dfd34fb9a02334af08409ea" dependencies = [ "aws-credential-types", "aws-sigv4", @@ -697,15 +697,15 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.49.0" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09677244a9da92172c8dc60109b4a9658597d4d298b188dd0018b6a66b410ca4" +checksum = "05ca43a4ef210894f93096039ef1d6fa4ad3edfabb3be92b80908b9f2e4b4eab" dependencies = [ "aws-credential-types", "aws-runtime", "aws-smithy-async", "aws-smithy-http", - "aws-smithy-json", + "aws-smithy-json 0.61.1", "aws-smithy-runtime", "aws-smithy-runtime-api", "aws-smithy-types", @@ -719,15 +719,15 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.50.0" +version = "1.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fea2f3a8bb3bd10932ae7ad59cc59f65f270fc9183a7e91f501dc5efbef7ee" +checksum = "abaf490c2e48eed0bb8e2da2fb08405647bd7f253996e0f93b981958ea0f73b0" dependencies = [ "aws-credential-types", "aws-runtime", "aws-smithy-async", "aws-smithy-http", - "aws-smithy-json", + "aws-smithy-json 0.61.1", "aws-smithy-runtime", "aws-smithy-runtime-api", "aws-smithy-types", @@ -741,15 +741,15 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.50.0" +version = "1.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ada54e5f26ac246dc79727def52f7f8ed38915cb47781e2a72213957dc3a7d5" +checksum = "b68fde0d69c8bfdc1060ea7da21df3e39f6014da316783336deff0a9ec28f4bf" dependencies = [ "aws-credential-types", "aws-runtime", "aws-smithy-async", "aws-smithy-http", - "aws-smithy-json", + "aws-smithy-json 0.61.1", "aws-smithy-query", "aws-smithy-runtime", "aws-smithy-runtime-api", @@ -764,9 +764,9 @@ dependencies = [ [[package]] name = "aws-sigv4" -version = "1.2.5" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5619742a0d8f253be760bfbb8e8e8368c69e3587e4637af5754e488a611499b1" +checksum = "7d3820e0c08d0737872ff3c7c1f21ebbb6693d832312d6152bf18ef50a5471c2" dependencies = [ "aws-credential-types", "aws-smithy-http", @@ -777,7 +777,7 @@ dependencies = [ "hex", "hmac", "http 0.2.12", - "http 1.1.0", + "http 1.2.0", "once_cell", "percent-encoding", "sha2 0.10.8", @@ -825,6 +825,15 @@ dependencies = [ "aws-smithy-types", ] +[[package]] +name = "aws-smithy-json" +version = "0.61.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4e69cc50921eb913c6b662f8d909131bb3e6ad6cb6090d3a39b66fc5c52095" +dependencies = [ + "aws-smithy-types", +] + [[package]] name = "aws-smithy-query" version = "0.60.7" @@ -837,9 +846,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.7.3" +version = "1.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be28bd063fa91fd871d131fc8b68d7cd4c5fa0869bea68daca50dcb1cbd76be2" +checksum = "9f20685047ca9d6f17b994a07f629c813f08b5bce65523e47124879e60103d45" dependencies = [ "aws-smithy-async", "aws-smithy-http", @@ -872,7 +881,7 @@ dependencies = [ "aws-smithy-types", "bytes", "http 0.2.12", - "http 1.1.0", + "http 1.2.0", "pin-project-lite", "tokio", "tracing", @@ -890,7 +899,7 @@ dependencies = [ "bytes-utils", "futures-core", "http 0.2.12", - "http 1.1.0", + "http 1.2.0", "http-body 0.4.6", "http-body 1.0.1", "http-body-util", @@ -938,7 +947,7 @@ dependencies = [ "axum-core", "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", "hyper 1.5.1", @@ -972,7 +981,7 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", "mime", @@ -1115,7 +1124,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.89", + "syn 2.0.90", "which 4.4.2", ] @@ -1134,7 +1143,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1265,7 +1274,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1367,7 +1376,7 @@ checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1598,9 +1607,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.21" +version = "4.5.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "69371e34337c4c984bbe322360c2547210bf632eb2814bbe78a6e87a2935bd2b" dependencies = [ "clap_builder", "clap_derive", @@ -1608,9 +1617,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "6e24c1b4099818523236a8ca881d2b45db98dadfb4625cf6608c12069fcbbde1" dependencies = [ "anstream", "anstyle", @@ -1627,7 +1636,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2012,7 +2021,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2060,7 +2069,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2082,7 +2091,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core 0.20.10", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2144,7 +2153,7 @@ dependencies = [ "glob", "half", "hashbrown 0.14.5", - "indexmap 2.6.0", + "indexmap 2.7.0", "itertools 0.12.1", "log", "num_cpus", @@ -2313,7 +2322,7 @@ dependencies = [ "datafusion-expr", "datafusion-physical-expr", "hashbrown 0.14.5", - "indexmap 2.6.0", + "indexmap 2.7.0", "itertools 0.12.1", "log", "regex-syntax 0.8.5", @@ -2342,7 +2351,7 @@ dependencies = [ "half", "hashbrown 0.14.5", "hex", - "indexmap 2.6.0", + "indexmap 2.7.0", "itertools 0.12.1", "log", "paste", @@ -2386,7 +2395,7 @@ dependencies = [ "futures", "half", "hashbrown 0.14.5", - "indexmap 2.6.0", + "indexmap 2.7.0", "itertools 0.12.1", "log", "once_cell", @@ -2531,7 +2540,7 @@ dependencies = [ "deno_tls", "dyn-clone", "error_reporter", - "http 1.1.0", + "http 1.2.0", "http-body-util", "hyper 1.5.1", "hyper-rustls 0.27.3", @@ -2603,7 +2612,7 @@ dependencies = [ "quote", "strum 0.25.0", "strum_macros 0.25.3", - "syn 2.0.89", + "syn 2.0.90", "thiserror 1.0.69", ] @@ -2676,10 +2685,11 @@ dependencies = [ [[package]] name = "deno_unsync" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f36b4ef61a04ce201b925a5dffa90f88437d37fee4836c758470dd15ba7f05e" +checksum = "d774fd83f26b24f0805a6ab8b26834a0d06ceac0db517b769b1e4633c96a2057" dependencies = [ + "futures", "parking_lot", "tokio", ] @@ -2795,7 +2805,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2900,7 +2910,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2923,7 +2933,7 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3079,7 +3089,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3099,7 +3109,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3304,7 +3314,7 @@ checksum = "32016f1242eb82af5474752d00fd8ebcd9004bd69b462b1c91de833972d08ed4" dependencies = [ "proc-macro2", "swc_macros_common", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3336,7 +3346,7 @@ checksum = "e99b8b3c28ae0e84b604c75f721c21dc77afb3706076af5e8216d15fd1deaae3" dependencies = [ "frunk_proc_macro_helpers", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3348,7 +3358,7 @@ dependencies = [ "frunk_core", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3360,7 +3370,7 @@ dependencies = [ "frunk_core", "frunk_proc_macro_helpers", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3471,7 +3481,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3724,7 +3734,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3802,7 +3812,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.6.0", + "indexmap 2.7.0", "slab", "tokio", "tokio-util", @@ -3820,8 +3830,8 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http 1.1.0", - "indexmap 2.6.0", + "http 1.2.0", + "indexmap 2.7.0", "slab", "tokio", "tokio-util", @@ -4002,9 +4012,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -4029,7 +4039,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http 1.2.0", ] [[package]] @@ -4040,7 +4050,7 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "pin-project-lite", ] @@ -4118,7 +4128,7 @@ dependencies = [ "futures-channel", "futures-util", "h2 0.4.7", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "httparse", "httpdate", @@ -4152,7 +4162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", - "http 1.1.0", + "http 1.2.0", "hyper 1.5.1", "hyper-util", "rustls 0.23.19", @@ -4201,7 +4211,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "hyper 1.5.1", "pin-project-lite", @@ -4350,7 +4360,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -4409,9 +4419,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -4482,7 +4492,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -4571,7 +4581,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee7893dab2e44ae5f9d0173f26ff4aa327c10b01b06a72b52dd9405b628640d" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", ] [[package]] @@ -5126,7 +5136,7 @@ checksum = "a7ce64b975ed4f123575d11afd9491f2e37bbd5813fbfbc0f09ae1fbddea74e0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -5138,7 +5148,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 1.1.0", + "http 1.2.0", "httparse", "memchr", "mime", @@ -5165,7 +5175,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", "termcolor", "thiserror 1.0.69", ] @@ -5422,7 +5432,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -5596,7 +5606,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -5840,7 +5850,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.6.0", + "indexmap 2.7.0", ] [[package]] @@ -5883,7 +5893,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -5924,7 +5934,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -6080,7 +6090,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -6120,7 +6130,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -6131,7 +6141,7 @@ checksum = "07c277e4e643ef00c1233393c673f655e3672cf7eb3ba08a00bdd0ea59139b5f" dependencies = [ "proc-macro-rules-macros", "proc-macro2", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -6143,7 +6153,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -6204,7 +6214,7 @@ dependencies = [ "schemars", "serde", "serde_json", - "syn 2.0.89", + "syn 2.0.90", "thiserror 1.0.69", "typify", "unicode-ident", @@ -6224,7 +6234,7 @@ dependencies = [ "serde_json", "serde_tokenstream", "serde_yaml", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -6267,7 +6277,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -6380,10 +6390,10 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.0.0", + "rustc-hash 2.1.0", "rustls 0.23.19", "socket2", - "thiserror 2.0.3", + "thiserror 2.0.4", "tokio", "tracing", ] @@ -6398,11 +6408,11 @@ dependencies = [ "getrandom 0.2.15", "rand 0.8.5", "ring 0.17.8", - "rustc-hash 2.0.0", + "rustc-hash 2.1.0", "rustls 0.23.19", "rustls-pki-types", "slab", - "thiserror 2.0.3", + "thiserror 2.0.4", "tinyvec", "tracing", "web-time", @@ -6759,7 +6769,7 @@ dependencies = [ "futures-core", "futures-util", "h2 0.4.7", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", "hyper 1.5.1", @@ -6944,7 +6954,7 @@ dependencies = [ "quote", "rust-embed-utils", "shellexpand", - "syn 2.0.89", + "syn 2.0.90", "walkdir", ] @@ -6999,9 +7009,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] name = "rustc_version" @@ -7326,7 +7336,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -7486,7 +7496,7 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -7497,7 +7507,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -7506,7 +7516,7 @@ version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "itoa", "memchr", "ryu", @@ -7572,7 +7582,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -7610,7 +7620,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_derive", "serde_json", @@ -7627,7 +7637,7 @@ dependencies = [ "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -7636,7 +7646,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "itoa", "ryu", "serde", @@ -7989,7 +7999,7 @@ checksum = "01b2e185515564f15375f593fb966b5718bc624ba77fe49fa4616ad619690554" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -8028,7 +8038,7 @@ dependencies = [ "hashbrown 0.14.5", "hashlink", "hex", - "indexmap 2.6.0", + "indexmap 2.7.0", "log", "memchr", "once_cell", @@ -8060,7 +8070,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -8083,7 +8093,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.89", + "syn 2.0.90", "tempfile", "tokio", "url", @@ -8235,7 +8245,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -8289,7 +8299,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -8302,7 +8312,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -8394,7 +8404,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4740e53eaf68b101203c1df0937d5161a29f3c13bceed0836ddfe245b72dd000" dependencies = [ "anyhow", - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_json", "swc_cached", @@ -8410,7 +8420,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -8459,7 +8469,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -8506,7 +8516,7 @@ checksum = "65f21494e75d0bd8ef42010b47cabab9caaed8f2207570e809f6f4eb51a710d1" dependencies = [ "better_scoped_tls", "bitflags 2.6.0", - "indexmap 2.6.0", + "indexmap 2.7.0", "once_cell", "phf", "rustc-hash 1.1.0", @@ -8544,7 +8554,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -8575,7 +8585,7 @@ checksum = "76c76d8b9792ce51401d38da0fa62158d61f6d80d16d68fe5b03ce4bf5fba383" dependencies = [ "base64 0.21.7", "dashmap", - "indexmap 2.6.0", + "indexmap 2.7.0", "once_cell", "serde", "sha1", @@ -8615,7 +8625,7 @@ version = "0.134.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "029eec7dd485923a75b5a45befd04510288870250270292fc2c1b3a9e7547408" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "num_cpus", "once_cell", "rustc-hash 1.1.0", @@ -8651,7 +8661,7 @@ checksum = "63db0adcff29d220c3d151c5b25c0eabe7e32dd936212b84cdaa1392e3130497" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -8662,7 +8672,7 @@ checksum = "f486687bfb7b5c560868f69ed2d458b880cebc9babebcb67e49f31b55c5bf847" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -8685,7 +8695,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -8701,9 +8711,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.89" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -8733,7 +8743,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -8992,11 +9002,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "2f49a1853cf82743e3b7950f77e0f4d622ca36cf4317cba00c767838bac8d490" dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl 2.0.4", ] [[package]] @@ -9007,18 +9017,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "8381894bb3efe0c4acac3ded651301ceee58a15d47c2e34885ed1908ad667061" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -9114,9 +9124,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -9135,9 +9145,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -9253,7 +9263,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -9367,9 +9377,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -9418,7 +9428,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", @@ -9431,7 +9441,7 @@ version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", @@ -9492,7 +9502,7 @@ dependencies = [ "axum-core", "cookie 0.18.1", "futures-util", - "http 1.1.0", + "http 1.2.0", "parking_lot", "pin-project-lite", "tower-layer", @@ -9509,7 +9519,7 @@ dependencies = [ "bitflags 2.6.0", "bytes", "futures-core", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", "pin-project-lite", @@ -9564,7 +9574,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -9755,7 +9765,7 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http 1.1.0", + "http 1.2.0", "httparse", "log", "native-tls", @@ -9811,7 +9821,7 @@ dependencies = [ "regress", "schemars", "serde_json", - "syn 2.0.89", + "syn 2.0.90", "thiserror 1.0.69", "unicode-ident", ] @@ -9828,7 +9838,7 @@ dependencies = [ "serde", "serde_json", "serde_tokenstream", - "syn 2.0.89", + "syn 2.0.90", "typify-impl", ] @@ -10034,9 +10044,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.10.1" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" dependencies = [ "base64 0.22.1", "flate2", @@ -10235,7 +10245,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", "wasm-bindgen-shared", ] @@ -10269,7 +10279,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -10302,7 +10312,7 @@ checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -10436,7 +10446,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windmill" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "axum", @@ -10477,7 +10487,7 @@ dependencies = [ [[package]] name = "windmill-api" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "argon2", @@ -10504,7 +10514,7 @@ dependencies = [ "hex", "hf-hub", "hmac", - "http 1.1.0", + "http 1.2.0", "hyper 1.5.1", "itertools 0.13.0", "jsonwebtoken", @@ -10563,7 +10573,7 @@ dependencies = [ [[package]] name = "windmill-api-client" -version = "1.434.1" +version = "1.434.2" dependencies = [ "base64 0.22.1", "chrono", @@ -10581,7 +10591,7 @@ dependencies = [ [[package]] name = "windmill-audit" -version = "1.434.1" +version = "1.434.2" dependencies = [ "chrono", "serde", @@ -10594,7 +10604,7 @@ dependencies = [ [[package]] name = "windmill-autoscaling" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "serde", @@ -10608,7 +10618,7 @@ dependencies = [ [[package]] name = "windmill-common" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "async-stream", @@ -10628,7 +10638,7 @@ dependencies = [ "hex", "hmac", "hyper 1.5.1", - "indexmap 2.6.0", + "indexmap 2.7.0", "itertools 0.13.0", "lazy_static", "magic-crypt", @@ -10644,7 +10654,7 @@ dependencies = [ "serde_json", "sha2 0.10.8", "sqlx", - "thiserror 2.0.3", + "thiserror 2.0.4", "tikv-jemalloc-ctl", "tokio", "tracing", @@ -10658,7 +10668,7 @@ dependencies = [ [[package]] name = "windmill-git-sync" -version = "1.434.1" +version = "1.434.2" dependencies = [ "regex", "serde", @@ -10672,7 +10682,7 @@ dependencies = [ [[package]] name = "windmill-indexer" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "bytes", @@ -10695,19 +10705,19 @@ dependencies = [ [[package]] name = "windmill-macros" -version = "1.434.1" +version = "1.434.2" dependencies = [ "itertools 0.13.0", "lazy_static", "proc-macro2", "quote", "regex", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] name = "windmill-parser" -version = "1.434.1" +version = "1.434.2" dependencies = [ "convert_case 0.6.0", "serde", @@ -10716,7 +10726,7 @@ dependencies = [ [[package]] name = "windmill-parser-bash" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "lazy_static", @@ -10728,7 +10738,7 @@ dependencies = [ [[package]] name = "windmill-parser-go" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "gosyn", @@ -10740,7 +10750,7 @@ dependencies = [ [[package]] name = "windmill-parser-graphql" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "lazy_static", @@ -10752,7 +10762,7 @@ dependencies = [ [[package]] name = "windmill-parser-php" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "itertools 0.13.0", @@ -10763,7 +10773,7 @@ dependencies = [ [[package]] name = "windmill-parser-py" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "itertools 0.13.0", @@ -10774,7 +10784,7 @@ dependencies = [ [[package]] name = "windmill-parser-py-imports" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "async-recursion", @@ -10792,7 +10802,7 @@ dependencies = [ [[package]] name = "windmill-parser-rust" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "convert_case 0.6.0", @@ -10802,14 +10812,14 @@ dependencies = [ "quote", "regex", "serde_json", - "syn 2.0.89", + "syn 2.0.90", "toml 0.7.8", "windmill-parser", ] [[package]] name = "windmill-parser-sql" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "lazy_static", @@ -10821,7 +10831,7 @@ dependencies = [ [[package]] name = "windmill-parser-ts" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "lazy_static", @@ -10839,7 +10849,7 @@ dependencies = [ [[package]] name = "windmill-parser-wasm" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "getrandom 0.2.15", @@ -10860,7 +10870,7 @@ dependencies = [ [[package]] name = "windmill-parser-yaml" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "serde_json", @@ -10870,7 +10880,7 @@ dependencies = [ [[package]] name = "windmill-queue" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "async-recursion", @@ -10904,7 +10914,7 @@ dependencies = [ [[package]] name = "windmill-sql-datatype-parser-wasm" -version = "1.434.1" +version = "1.434.2" dependencies = [ "wasm-bindgen", "wasm-bindgen-test", @@ -10914,7 +10924,7 @@ dependencies = [ [[package]] name = "windmill-worker" -version = "1.434.1" +version = "1.434.2" dependencies = [ "anyhow", "async-recursion", @@ -11292,7 +11302,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", "synstructure", ] @@ -11314,7 +11324,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -11334,7 +11344,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", "synstructure", ] @@ -11363,7 +11373,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 8802e10403..be954faac2 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "windmill" -version = "1.434.1" +version = "1.434.2" authors.workspace = true edition.workspace = true @@ -29,7 +29,7 @@ members = [ ] [workspace.package] -version = "1.434.1" +version = "1.434.2" authors = ["Ruben Fiszel "] edition = "2021" diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 7a7525bf04..4a9492418b 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: - version: 1.434.1 + version: 1.434.2 title: Windmill API contact: diff --git a/benchmarks/lib.ts b/benchmarks/lib.ts index aed23d3ca0..da88c5d0aa 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.434.1"; +export const VERSION = "v1.434.2"; 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 3b1027fd14..bf465fc315 100644 --- a/cli/main.ts +++ b/cli/main.ts @@ -60,7 +60,7 @@ export { // } // }); -export const VERSION = "1.434.1"; +export const VERSION = "1.434.2"; const command = new Command() .name("wmill") diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 9bd2c2ee7d..237bcb81bd 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "windmill-components", - "version": "1.434.1", + "version": "1.434.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "windmill-components", - "version": "1.434.1", + "version": "1.434.2", "license": "AGPL-3.0", "dependencies": { "@anthropic-ai/sdk": "^0.32.1", diff --git a/frontend/package.json b/frontend/package.json index 5b358f953e..24cf283420 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "windmill-components", - "version": "1.434.1", + "version": "1.434.2", "scripts": { "dev": "vite dev", "build": "vite build", diff --git a/lsp/Pipfile b/lsp/Pipfile index cc4fe8a35e..b65209dcd2 100644 --- a/lsp/Pipfile +++ b/lsp/Pipfile @@ -4,8 +4,8 @@ verify_ssl = true name = "pypi" [packages] -wmill = ">=1.434.1" -wmill_pg = ">=1.434.1" +wmill = ">=1.434.2" +wmill_pg = ">=1.434.2" sendgrid = "*" mysql-connector-python = "*" pymongo = "*" diff --git a/openflow.openapi.yaml b/openflow.openapi.yaml index d578644ec0..9ed0fede12 100644 --- a/openflow.openapi.yaml +++ b/openflow.openapi.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: - version: 1.434.1 + version: 1.434.2 title: OpenFlow Spec contact: name: Ruben Fiszel diff --git a/powershell-client/WindmillClient/WindmillClient.psd1 b/powershell-client/WindmillClient/WindmillClient.psd1 index 2b35f5df52..9dc95dee21 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.434.1' +ModuleVersion = '1.434.2' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/python-client/wmill/pyproject.toml b/python-client/wmill/pyproject.toml index 99906b4dec..1ee961678d 100644 --- a/python-client/wmill/pyproject.toml +++ b/python-client/wmill/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "wmill" -version = "1.434.1" +version = "1.434.2" 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 a0f543d788..4e41543428 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.434.1" +version = "1.434.2" 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 43d0625bf3..e113d36b82 100644 --- a/typescript-client/jsr.json +++ b/typescript-client/jsr.json @@ -1,6 +1,6 @@ { "name": "@windmill/windmill", - "version": "1.434.1", + "version": "1.434.2", "exports": "./src/index.ts", "publish": { "exclude": ["!src", "./s3Types.ts", "./client.ts"] diff --git a/typescript-client/package.json b/typescript-client/package.json index 1ba5e77965..ac77f8302b 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.434.1", + "version": "1.434.2", "author": "Ruben Fiszel", "license": "Apache 2.0", "devDependencies": { diff --git a/version.txt b/version.txt index 890aba3f45..417684d0b6 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.434.1 +1.434.2 From 1ec6c6f765904361e641d89495890bc87e8544aa Mon Sep 17 00:00:00 2001 From: HugoCasa Date: Wed, 4 Dec 2024 16:50:17 +0100 Subject: [PATCH 05/34] feat: app custom paths (#4828) * feat: app custom paths * nit * make ee only + fix sqlx * fix: custom http routes auth * nits * fix auth + nits * apps_ee * move custom path to ee * fix app jwt * update ee ref --- ...71ca897dcfa9e82618ce8f11afb08a39e3b20.json | 23 +++ ...979f51b53dcd4d8ec50d312c9e7fe31ad5f5.json} | 7 +- ...a1d606d9725e20e9c2d76a0887fadfd87f8df.json | 25 +++ backend/ee-repo-ref.txt | 2 +- .../20241202134622_app_custom_path.down.sql | 2 + .../20241202134622_app_custom_path.up.sql | 2 + backend/windmill-api/openapi.yaml | 50 +++++ backend/windmill-api/src/apps.rs | 109 +++++++++-- backend/windmill-api/src/apps_ee.rs | 5 + backend/windmill-api/src/lib.rs | 13 ++ .../components/apps/editor/AppEditor.svelte | 1 + .../apps/editor/AppEditorHeader.svelte | 126 +++++++++--- .../components/details/ClipboardPanel.svelte | 6 +- .../(logged)/apps/edit/[...path]/+page.svelte | 4 +- frontend/src/routes/a/[...path]/+page.js | 5 + frontend/src/routes/a/[...path]/+page.svelte | 182 ++++++++++++++++++ 16 files changed, 514 insertions(+), 48 deletions(-) create mode 100644 backend/.sqlx/query-1ec97e1bf7c6edfa82b7e64585171ca897dcfa9e82618ce8f11afb08a39e3b20.json rename backend/.sqlx/{query-75e880f9d9fbda36c2314706923cef36e4667d930fb8ee1876dd9ce1c92396b2.json => query-6b53f7c4bb73177316d6134698f3979f51b53dcd4d8ec50d312c9e7fe31ad5f5.json} (63%) create mode 100644 backend/.sqlx/query-fb1399c1dc171ec6bb24fee3477a1d606d9725e20e9c2d76a0887fadfd87f8df.json create mode 100644 backend/migrations/20241202134622_app_custom_path.down.sql create mode 100644 backend/migrations/20241202134622_app_custom_path.up.sql create mode 100644 backend/windmill-api/src/apps_ee.rs create mode 100644 frontend/src/routes/a/[...path]/+page.js create mode 100644 frontend/src/routes/a/[...path]/+page.svelte diff --git a/backend/.sqlx/query-1ec97e1bf7c6edfa82b7e64585171ca897dcfa9e82618ce8f11afb08a39e3b20.json b/backend/.sqlx/query-1ec97e1bf7c6edfa82b7e64585171ca897dcfa9e82618ce8f11afb08a39e3b20.json new file mode 100644 index 0000000000..51343088a6 --- /dev/null +++ b/backend/.sqlx/query-1ec97e1bf7c6edfa82b7e64585171ca897dcfa9e82618ce8f11afb08a39e3b20.json @@ -0,0 +1,23 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT EXISTS(SELECT 1 FROM app WHERE custom_path = $1 AND ($2::TEXT IS NULL OR workspace_id = $2))", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "exists", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [ + null + ] + }, + "hash": "1ec97e1bf7c6edfa82b7e64585171ca897dcfa9e82618ce8f11afb08a39e3b20" +} diff --git a/backend/.sqlx/query-75e880f9d9fbda36c2314706923cef36e4667d930fb8ee1876dd9ce1c92396b2.json b/backend/.sqlx/query-6b53f7c4bb73177316d6134698f3979f51b53dcd4d8ec50d312c9e7fe31ad5f5.json similarity index 63% rename from backend/.sqlx/query-75e880f9d9fbda36c2314706923cef36e4667d930fb8ee1876dd9ce1c92396b2.json rename to backend/.sqlx/query-6b53f7c4bb73177316d6134698f3979f51b53dcd4d8ec50d312c9e7fe31ad5f5.json index efaac63d39..0c82c9dd74 100644 --- a/backend/.sqlx/query-75e880f9d9fbda36c2314706923cef36e4667d930fb8ee1876dd9ce1c92396b2.json +++ b/backend/.sqlx/query-6b53f7c4bb73177316d6134698f3979f51b53dcd4d8ec50d312c9e7fe31ad5f5.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "INSERT INTO app\n (workspace_id, path, summary, policy, versions, draft_only)\n VALUES ($1, $2, $3, $4, '{}', $5) RETURNING id", + "query": "INSERT INTO app\n (workspace_id, path, summary, policy, versions, draft_only, custom_path)\n VALUES ($1, $2, $3, $4, '{}', $5, $6) RETURNING id", "describe": { "columns": [ { @@ -15,12 +15,13 @@ "Varchar", "Varchar", "Jsonb", - "Bool" + "Bool", + "Text" ] }, "nullable": [ false ] }, - "hash": "75e880f9d9fbda36c2314706923cef36e4667d930fb8ee1876dd9ce1c92396b2" + "hash": "6b53f7c4bb73177316d6134698f3979f51b53dcd4d8ec50d312c9e7fe31ad5f5" } diff --git a/backend/.sqlx/query-fb1399c1dc171ec6bb24fee3477a1d606d9725e20e9c2d76a0887fadfd87f8df.json b/backend/.sqlx/query-fb1399c1dc171ec6bb24fee3477a1d606d9725e20e9c2d76a0887fadfd87f8df.json new file mode 100644 index 0000000000..a2362be620 --- /dev/null +++ b/backend/.sqlx/query-fb1399c1dc171ec6bb24fee3477a1d606d9725e20e9c2d76a0887fadfd87f8df.json @@ -0,0 +1,25 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT EXISTS(SELECT 1 FROM app WHERE custom_path = $1 AND ($2::TEXT IS NULL OR workspace_id = $2) AND NOT (path = $3 AND workspace_id = $4))", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "exists", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Text", + "Text", + "Text", + "Text" + ] + }, + "nullable": [ + null + ] + }, + "hash": "fb1399c1dc171ec6bb24fee3477a1d606d9725e20e9c2d76a0887fadfd87f8df" +} diff --git a/backend/ee-repo-ref.txt b/backend/ee-repo-ref.txt index 496432b7e0..c7e750d0f4 100644 --- a/backend/ee-repo-ref.txt +++ b/backend/ee-repo-ref.txt @@ -1 +1 @@ -aefbc1e2188fea312996fcfc30a29d8fb5315316 \ No newline at end of file +8606d98a692d11b09a387c5efbd6b4335c533fd3 \ No newline at end of file diff --git a/backend/migrations/20241202134622_app_custom_path.down.sql b/backend/migrations/20241202134622_app_custom_path.down.sql new file mode 100644 index 0000000000..1dadbefff1 --- /dev/null +++ b/backend/migrations/20241202134622_app_custom_path.down.sql @@ -0,0 +1,2 @@ +-- Add down migration script here +ALTER TABLE app DROP COLUMN custom_path; diff --git a/backend/migrations/20241202134622_app_custom_path.up.sql b/backend/migrations/20241202134622_app_custom_path.up.sql new file mode 100644 index 0000000000..832efd0cb2 --- /dev/null +++ b/backend/migrations/20241202134622_app_custom_path.up.sql @@ -0,0 +1,2 @@ +-- Add up migration script here +ALTER TABLE app ADD COLUMN custom_path TEXT CHECK (custom_path ~ '^[\w-]+(\/[\w-]+)*$'); diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 4a9492418b..f0bd8856d5 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -3733,6 +3733,27 @@ paths: required: - app + /apps_u/public_app_by_custom_path/{custom_path}: + get: + summary: get public app by custom path + operationId: getPublicAppByCustomPath + tags: + - app + parameters: + - $ref: "#/components/parameters/CustomPath" + responses: + "200": + description: app details + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/AppWithLastVersion" + - type: object + properties: + workspace_id: + type: string + /scripts/hub/get/{path}: get: summary: get hub script content by path @@ -5371,6 +5392,8 @@ paths: type: boolean deployment_message: type: string + custom_path: + type: string required: - path - value @@ -5696,6 +5719,8 @@ paths: $ref: "#/components/schemas/Policy" deployment_message: type: string + custom_path: + type: string responses: "200": description: app updated @@ -5704,6 +5729,23 @@ paths: schema: type: string + /w/{workspace}/apps/custom_path_exists/{custom_path}: + get: + summary: check if custom path exists + operationId: customPathExists + tags: + - app + parameters: + - $ref: "#/components/parameters/WorkspaceId" + - $ref: "#/components/parameters/CustomPath" + responses: + "200": + description: custom path exists + content: + application/json: + schema: + type: boolean + /w/{workspace}/apps_u/execute_component/{path}: post: summary: executeComponent @@ -10222,6 +10264,12 @@ components: required: true schema: type: string + CustomPath: + name: custom_path + in: path + required: true + schema: + type: string PathId: name: id in: path @@ -12860,6 +12908,8 @@ components: draft_only: type: boolean draft: {} + custom_path: + type: string AppHistory: type: object diff --git a/backend/windmill-api/src/apps.rs b/backend/windmill-api/src/apps.rs index 5e236baeb6..e1a9421252 100644 --- a/backend/windmill-api/src/apps.rs +++ b/backend/windmill-api/src/apps.rs @@ -56,10 +56,10 @@ use windmill_common::{ jobs::{get_payload_tag_from_prefixed_path, JobPayload, RawCode}, users::username_to_permissioned_as, utils::{ - http_get_from_hub, not_found_if_none, paginate, query_elems_from_hub, Pagination, StripPath, + http_get_from_hub, not_found_if_none, paginate, query_elems_from_hub, require_admin, Pagination, StripPath }, variables::{build_crypt, build_crypt_with_key_suffix}, - worker::to_raw_value, + worker::{to_raw_value, CLOUD_HOSTED}, HUB_BASE_URL, }; @@ -81,6 +81,7 @@ pub fn workspaced_service() -> Router { .route("/history/p/*path", get(get_app_history)) .route("/get_latest_version/*path", get(get_latest_version)) .route("/history_update/a/:id/v/:version", post(update_app_history)) + .route("/custom_path_exists/*custom_path", get(custom_path_exists)) } pub fn unauthed_service() -> Router { @@ -90,13 +91,17 @@ pub fn unauthed_service() -> Router { .route("/public_app/:secret", get(get_public_app_by_secret)) .route("/public_resource/*path", get(get_public_resource)) } - pub fn global_service() -> Router { Router::new() .route("/hub/list", get(list_hub_apps)) .route("/hub/get/:id", get(get_hub_app_by_id)) } +#[cfg(not(feature = "enterprise"))] +pub fn global_unauthed_service() -> Router { + Router::new() +} + #[derive(FromRow, Deserialize, Serialize)] pub struct ListableApp { pub id: i64, @@ -147,21 +152,26 @@ pub struct AppWithLastVersionAndStarred { pub starred: Option, } +#[cfg(feature = "enterprise")] +#[derive(Serialize, FromRow)] +pub struct AppWithLastVersionAndWorkspace { + #[sqlx(flatten)] + #[serde(flatten)] + pub app: AppWithLastVersion, + pub workspace_id: String, +} + #[derive(Serialize, Deserialize, FromRow)] pub struct AppWithLastVersionAndDraft { - pub id: i64, - pub path: String, - pub summary: String, - pub policy: sqlx::types::Json>, - pub versions: Vec, - pub value: sqlx::types::Json>, - pub created_by: String, - pub created_at: chrono::DateTime, - pub extra_perms: serde_json::Value, + #[sqlx(flatten)] + #[serde(flatten)] + pub app: AppWithLastVersion, #[serde(skip_serializing_if = "Option::is_none")] pub draft: Option>>, #[serde(skip_serializing_if = "Option::is_none")] pub draft_only: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub custom_path: Option, } #[derive(Serialize)] @@ -229,6 +239,7 @@ pub struct CreateApp { pub policy: Policy, pub draft_only: Option, pub deployment_message: Option, + pub custom_path: Option, } #[derive(Deserialize)] @@ -238,6 +249,7 @@ pub struct EditApp { pub value: Option>>, pub policy: Option, pub deployment_message: Option, + pub custom_path: Option, } #[derive(Serialize, FromRow)] @@ -408,7 +420,7 @@ async fn get_app_w_draft( let app_o = sqlx::query_as::<_, AppWithLastVersionAndDraft>( r#"SELECT app.id, app.path, app.summary, app.versions, app.policy, - app.extra_perms, app_version.value, + app.extra_perms, app_version.value, app.custom_path, app_version.created_at, app_version.created_by, app.draft_only, draft.value as "draft" from app @@ -515,6 +527,22 @@ async fn update_app_history( return Ok(()); } + +async fn custom_path_exists( + Extension(db): Extension, + Path((w_id, custom_path)): Path<(String, String)>, +) -> JsonResult { + let exists = + sqlx::query_scalar!( + "SELECT EXISTS(SELECT 1 FROM app WHERE custom_path = $1 AND ($2::TEXT IS NULL OR workspace_id = $2))", + custom_path, + if *CLOUD_HOSTED { Some(&w_id) } else { None } + ) + .fetch_one(&db) + .await?.unwrap_or(false); + Ok(Json(exists)) +} + async fn get_app_by_id( authed: ApiAuthed, Extension(user_db): Extension, @@ -598,6 +626,7 @@ async fn get_public_app_by_secret( Ok(Json(app)) } + async fn get_public_resource( Extension(db): Extension, Path((w_id, path)): Path<(String, StripPath)>, @@ -680,6 +709,26 @@ async fn create_app( ))); } + if let Some(custom_path) = &app.custom_path { + + require_admin(authed.is_admin, &authed.username)?; + + let exists = sqlx::query_scalar!( + "SELECT EXISTS(SELECT 1 FROM app WHERE custom_path = $1 AND ($2::TEXT IS NULL OR workspace_id = $2))", + custom_path, + if *CLOUD_HOSTED { Some(&w_id) } else { None } + ) + .fetch_one(&mut *tx) + .await?.unwrap_or(false); + + if exists { + return Err(Error::BadRequest(format!( + "App with custom path {} already exists", + custom_path + ))); + } + } + sqlx::query!( "DELETE FROM draft WHERE path = $1 AND workspace_id = $2 AND typ = 'app'", &app.path, @@ -690,13 +739,14 @@ async fn create_app( let id = sqlx::query_scalar!( "INSERT INTO app - (workspace_id, path, summary, policy, versions, draft_only) - VALUES ($1, $2, $3, $4, '{}', $5) RETURNING id", + (workspace_id, path, summary, policy, versions, draft_only, custom_path) + VALUES ($1, $2, $3, $4, '{}', $5, $6) RETURNING id", w_id, app.path, app.summary, json!(app.policy), app.draft_only, + app.custom_path, ) .fetch_one(&mut *tx) .await?; @@ -899,7 +949,11 @@ async fn update_app( let mut tx = user_db.clone().begin(&authed).await?; - let npath = if ns.policy.is_some() || ns.path.is_some() || ns.summary.is_some() { + let npath = if ns.policy.is_some() + || ns.path.is_some() + || ns.summary.is_some() + || ns.custom_path.is_some() + { let mut sqlb = SqlBuilder::update_table("app"); sqlb.and_where_eq("path", "?".bind(&path)); sqlb.and_where_eq("workspace_id", "?".bind(&w_id)); @@ -932,6 +986,29 @@ async fn update_app( sqlb.set_str("summary", nsummary); } + if let Some(ncustom_path) = &ns.custom_path { + + require_admin(authed.is_admin, &authed.username)?; + + let exists = sqlx::query_scalar!( + "SELECT EXISTS(SELECT 1 FROM app WHERE custom_path = $1 AND ($2::TEXT IS NULL OR workspace_id = $2) AND NOT (path = $3 AND workspace_id = $4))", + ncustom_path, + if *CLOUD_HOSTED { Some(&w_id) } else { None }, + path, + w_id + ) + .fetch_one(&mut *tx) + .await?.unwrap_or(false); + + if exists { + return Err(Error::BadRequest(format!( + "App with custom path {} already exists", + ncustom_path + ))); + } + sqlb.set_str("custom_path", ncustom_path); + } + if let Some(mut npolicy) = ns.policy { npolicy.on_behalf_of = Some(username_to_permissioned_as(&authed.username)); npolicy.on_behalf_of_email = Some(authed.email.clone()); diff --git a/backend/windmill-api/src/apps_ee.rs b/backend/windmill-api/src/apps_ee.rs new file mode 100644 index 0000000000..a7737664b9 --- /dev/null +++ b/backend/windmill-api/src/apps_ee.rs @@ -0,0 +1,5 @@ +use axum::Router; + +pub fn global_unauthed_service() -> Router { + Router::new() +} diff --git a/backend/windmill-api/src/lib.rs b/backend/windmill-api/src/lib.rs index 28f2523ad5..88243789b4 100644 --- a/backend/windmill-api/src/lib.rs +++ b/backend/windmill-api/src/lib.rs @@ -64,6 +64,8 @@ mod indexer_ee; mod inputs; mod integration; +#[cfg(feature = "enterprise")] +mod apps_ee; #[cfg(feature = "parquet")] mod job_helpers_ee; pub mod job_metrics; @@ -343,6 +345,17 @@ pub async fn run_server( ) .nest("/concurrency_groups", concurrency_groups::global_service()) .nest("/scripts_u", scripts::global_unauthed_service()) + .nest("/apps_u", { + #[cfg(feature = "enterprise")] + { + apps_ee::global_unauthed_service() + } + + #[cfg(not(feature = "enterprise"))] + { + Router::new() + } + }) .nest( "/w/:workspace_id/apps_u", apps::unauthed_service() diff --git a/frontend/src/lib/components/apps/editor/AppEditor.svelte b/frontend/src/lib/components/apps/editor/AppEditor.svelte index 66b2d3e009..f0380f09e2 100644 --- a/frontend/src/lib/components/apps/editor/AppEditor.svelte +++ b/frontend/src/lib/components/apps/editor/AppEditor.svelte @@ -68,6 +68,7 @@ summary: string policy: any draft_only?: boolean + custom_path?: string } | undefined = undefined export let version: number | undefined = undefined diff --git a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte index 82e47a0473..3c7783e3f4 100644 --- a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte +++ b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte @@ -11,12 +11,11 @@ import Toggle from '$lib/components/Toggle.svelte' import { AppService, DraftService, type Job, type Policy } from '$lib/gen' import { redo, undo } from '$lib/history' - import { enterpriseLicense, workspaceStore } from '$lib/stores' + import { enterpriseLicense, userStore, workspaceStore } from '$lib/stores' import { AlignHorizontalSpaceAround, BellOff, Bug, - Clipboard, DiffIcon, Expand, FileJson, @@ -39,7 +38,6 @@ import { classNames, cleanValueProperties, - copyToClipboard, truncateRev, orderedJsonStringify, type Value, @@ -90,6 +88,9 @@ import HideButton from './settingsPanel/HideButton.svelte' import DeployOverrideConfirmationModal from '$lib/components/common/confirmationModal/DeployOverrideConfirmationModal.svelte' import { computeS3FileInputPolicy, computeWorkspaceS3FileInputPolicy } from './appUtilsS3' + import { isCloudHosted } from '$lib/cloud' + import { base } from '$lib/base' + import ClipboardPanel from '$lib/components/details/ClipboardPanel.svelte' async function hash(message) { try { @@ -119,6 +120,7 @@ summary: string policy: any draft_only?: boolean + custom_path?: string } | undefined = undefined export let version: number | undefined = undefined @@ -479,14 +481,16 @@ summary: $summary, policy, path: npath, - deployment_message: deploymentMsg + deployment_message: deploymentMsg, + custom_path: $userStore?.is_admin || $userStore?.is_super_admin ? customPath : undefined } }) savedApp = { summary: $summary, value: structuredClone($app), path: npath, - policy + policy, + custom_path: customPath } const appHistory = await AppService.getAppHistoryByPath({ workspace: $workspaceStore!, @@ -885,6 +889,37 @@ let priorDarkMode = document.documentElement.classList.contains('dark') setTheme($app?.darkMode) + + let customPath = savedApp?.custom_path + let dirtyCustomPath = false + let customPathError = '' + $: fullCustomUrl = `${window.location.origin}${base}/a/${ + isCloudHosted() ? $workspaceStore + '/' : '' + }${customPath}` + async function appExists(customPath: string) { + return await AppService.customPathExists({ + workspace: $workspaceStore!, + customPath + }) + } + let validateTimeout: NodeJS.Timeout | undefined = undefined + async function validateCustomPath(customPath: string): Promise { + customPathError = '' + if (validateTimeout) { + clearTimeout(validateTimeout) + } + validateTimeout = setTimeout(async () => { + if (!/^[\w-]+(\/[\w-]+)*$/.test(customPath)) { + customPathError = 'Invalid path' + } else if (customPath !== savedApp?.custom_path && (await appExists(customPath))) { + customPathError = 'Path already taken' + } else { + customPathError = '' + } + validateTimeout = undefined + }, 500) + } + $: customPath !== undefined && validateCustomPath(customPath) @@ -1071,7 +1106,7 @@
- Public url: +
+
Public URL
+
{#if secretUrl} - {@const url = `${window.location.hostname}/public/${$workspaceStore}/${secretUrl}`} - {@const href = window.location.protocol + '//' + url} - { - e.preventDefault() - copyToClipboard(href) - }} - {href} - class="whitespace-nowrap text-ellipsis overflow-hidden mr-1 inline-flex gap-2" - > - {url} - - - - + {@const href = `${window.location.origin}${base}/public/${$workspaceStore}/${secretUrl}`} + {:else} {/if} -
Share this url directly or embed it using an iframe (if requiring login, top-level domain - of embedding app must be the same as the one of Windmill)
+
+ Share this url directly or embed it using an iframe (if requiring login, top-level domain + of embedding app must be the same as the one of Windmill) +
+ +
+ {#if !$enterpriseLicense} + + Custom path is an enterprise only feature. + +
+ {:else if !($userStore?.is_admin || $userStore?.is_super_admin)} + + Custom path can only be set by workspace admins + +
+ {/if} + { + customPath = detail ? '' : undefined + }} + checked={customPath !== undefined} + options={{ + right: 'Use a custom URL' + }} + disabled={!$enterpriseLicense || !($userStore?.is_admin || $userStore?.is_super_admin)} + /> + + {#if customPath !== undefined} +
+
Custom path
+
+ { + dirtyCustomPath = true + }} + /> +
+
Custom public URL
+
+ + +
{dirtyCustomPath ? customPathError : ''} +
+ {/if} +
You will still need to deploy the app to make visible the latest changes diff --git a/frontend/src/lib/components/details/ClipboardPanel.svelte b/frontend/src/lib/components/details/ClipboardPanel.svelte index 3107834df3..53d442fbb6 100644 --- a/frontend/src/lib/components/details/ClipboardPanel.svelte +++ b/frontend/src/lib/components/details/ClipboardPanel.svelte @@ -1,9 +1,11 @@ {#if title !== undefined} @@ -19,6 +21,8 @@ copyToClipboard(content) }} > -
{content}
+
{content}
diff --git a/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte b/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte index a0913dd1c8..083fd107d3 100644 --- a/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte @@ -19,6 +19,7 @@ summary: string policy: any draft_only?: boolean + custom_path?: string } | undefined = undefined let redraw = 0 @@ -58,7 +59,8 @@ path: app_w_draft_.path, policy: app_w_draft_.policy } - : undefined + : undefined, + custom_path: app_w_draft_.custom_path } if (stateLoadedFromUrl) { diff --git a/frontend/src/routes/a/[...path]/+page.js b/frontend/src/routes/a/[...path]/+page.js new file mode 100644 index 0000000000..42a8b51427 --- /dev/null +++ b/frontend/src/routes/a/[...path]/+page.js @@ -0,0 +1,5 @@ +export function load({ params }) { + return { + stuff: { title: `Public App` } + } +} diff --git a/frontend/src/routes/a/[...path]/+page.svelte b/frontend/src/routes/a/[...path]/+page.svelte new file mode 100644 index 0000000000..ba5135bfd8 --- /dev/null +++ b/frontend/src/routes/a/[...path]/+page.svelte @@ -0,0 +1,182 @@ + + + + +
{#if $userStore} +
{$userStore.username}
+ {:else}{/if} +
+ +{#if notExists} +
There was an error loading the app, is the url correct? Go to Windmill +
+{:else if noPermission} +
{#if $userStore}You are logged in but have no read access to this app{:else}You must be logged + in and have read access to this app{/if}
+
+ {#if !jwtError} + { + // window.location.reload() + loadApp() + app = app + }} + popup + rd={$page.url.toString()} + /> + {/if} +
+{:else if app} + {#key app} +
+ goto(path)} + gotoFn={(path, opt) => goto(path, opt)} + /> +
+ {/key} +{:else} + +{/if} From b534ef6074aba995eccc5010a3f739e500accc0e Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Wed, 4 Dec 2024 17:30:52 +0100 Subject: [PATCH 06/34] improve transparency for slow queries --- backend/Cargo.lock | 1 + backend/Cargo.toml | 1 + ...4154025_grant_all_concurrency_key.down.sql | 1 + ...204154025_grant_all_concurrency_key.up.sql | 3 + backend/src/monitor.rs | 4 +- backend/windmill-common/Cargo.toml | 1 + backend/windmill-common/src/utils.rs | 98 +++++++++++++++++-- .../windmill-worker/src/result_processor.rs | 3 + backend/windmill-worker/src/worker.rs | 22 ++++- backend/windmill-worker/src/worker_flow.rs | 6 +- 10 files changed, 124 insertions(+), 16 deletions(-) create mode 100644 backend/migrations/20241204154025_grant_all_concurrency_key.down.sql create mode 100644 backend/migrations/20241204154025_grant_all_concurrency_key.up.sql diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 54facad0c1..93e027e005 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -10644,6 +10644,7 @@ dependencies = [ "magic-crypt", "mail-send", "object_store", + "pin-project-lite", "prometheus", "quick_cache", "rand 0.8.5", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index be954faac2..6b70463727 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -284,6 +284,7 @@ tikv-jemalloc-sys = { version = "^0.5" } tikv-jemalloc-ctl = { version = "^0.5" } triomphe = "^0" +pin-project-lite = "^0" tantivy = "0.22.0" diff --git a/backend/migrations/20241204154025_grant_all_concurrency_key.down.sql b/backend/migrations/20241204154025_grant_all_concurrency_key.down.sql new file mode 100644 index 0000000000..d2f607c5b8 --- /dev/null +++ b/backend/migrations/20241204154025_grant_all_concurrency_key.down.sql @@ -0,0 +1 @@ +-- Add down migration script here diff --git a/backend/migrations/20241204154025_grant_all_concurrency_key.up.sql b/backend/migrations/20241204154025_grant_all_concurrency_key.up.sql new file mode 100644 index 0000000000..da9b9704d7 --- /dev/null +++ b/backend/migrations/20241204154025_grant_all_concurrency_key.up.sql @@ -0,0 +1,3 @@ +-- Add up migration script here +GRANT ALL ON concurrency_key TO windmill_admin; +GRANT ALL ON concurrency_key TO windmill_user; \ No newline at end of file diff --git a/backend/src/monitor.rs b/backend/src/monitor.rs index 733a841283..df3b695168 100644 --- a/backend/src/monitor.rs +++ b/backend/src/monitor.rs @@ -85,12 +85,12 @@ lazy_static::lazy_static! { static ref ZOMBIE_JOB_TIMEOUT: String = std::env::var("ZOMBIE_JOB_TIMEOUT") .ok() .and_then(|x| x.parse::().ok()) - .unwrap_or_else(|| "30".to_string()); + .unwrap_or_else(|| "60".to_string()); static ref FLOW_ZOMBIE_TRANSITION_TIMEOUT: String = std::env::var("FLOW_ZOMBIE_TRANSITION_TIMEOUT") .ok() .and_then(|x| x.parse::().ok()) - .unwrap_or_else(|| "30".to_string()); + .unwrap_or_else(|| "60".to_string()); pub static ref RESTART_ZOMBIE_JOBS: bool = std::env::var("RESTART_ZOMBIE_JOBS") diff --git a/backend/windmill-common/Cargo.toml b/backend/windmill-common/Cargo.toml index 068668930d..b56b9a39cf 100644 --- a/backend/windmill-common/Cargo.toml +++ b/backend/windmill-common/Cargo.toml @@ -62,6 +62,7 @@ windmill-macros.workspace = true semver.workspace = true croner = "2.0.6" quick_cache.workspace = true +pin-project-lite.workspace = true [target.'cfg(not(target_env = "msvc"))'.dependencies] tikv-jemalloc-ctl = { optional = true, workspace = true } diff --git a/backend/windmill-common/src/utils.rs b/backend/windmill-common/src/utils.rs index 08a0c32e3b..dc76c199e6 100644 --- a/backend/windmill-common/src/utils.rs +++ b/backend/windmill-common/src/utils.rs @@ -34,8 +34,8 @@ pub const GIT_VERSION: &str = git_version!(args = ["--tag", "--always"], fallback = "unknown-version"); use crate::CRITICAL_ALERT_MUTE_UI_ENABLED; -use std::sync::atomic::Ordering; use std::panic::{self, AssertUnwindSafe}; +use std::sync::atomic::Ordering; use crate::worker::CLOUD_HOSTED; @@ -78,14 +78,18 @@ pub fn require_admin(is_admin: bool, username: &str) -> Result<()> { } } -pub async fn require_admin_or_devops(is_admin: bool, username: &str, email: &str, db: &DB) -> Result<()> { +pub async fn require_admin_or_devops( + is_admin: bool, + username: &str, + email: &str, + db: &DB, +) -> Result<()> { if !is_admin { if !is_devops_email(db, email).await? { return Err(Error::RequireAdmin(username.to_string())); } } Ok(()) - } pub fn hostname() -> String { @@ -94,7 +98,7 @@ pub fn hostname() -> String { .to_str() .map(|x| x.to_string()) .unwrap_or_else(|| rd_string(5)) - }) + }) } pub fn paginate(pagination: Pagination) -> (usize, usize) { @@ -440,9 +444,7 @@ impl ScheduleType { Some("v2") | Some(_) => { // Use Croner for v2 let schedule_type_result = panic::catch_unwind(AssertUnwindSafe(|| { - Cron::new(schedule_str) - .with_seconds_optional() - .parse() + Cron::new(schedule_str).with_seconds_optional().parse() })) .map_err(|_| { tracing::error!( @@ -478,8 +480,14 @@ impl ScheduleType { } if let Err(e) = result { - tracing::error!("An error occurred while finding the next occurrence: {:?}", e); - return Err(Error::BadRequest(format!("cron: error during find_next_occurrence: {:?}", e))); + tracing::error!( + "An error occurred while finding the next occurrence: {:?}", + e + ); + return Err(Error::BadRequest(format!( + "cron: error during find_next_occurrence: {:?}", + e + ))); } } @@ -526,3 +534,75 @@ impl ScheduleType { Ok(events) } } + +use std::future::Future; +use std::pin::Pin; +use std::task::{Context as TContext, Poll}; +use tokio::time::{self, Duration, Sleep}; + +use pin_project_lite::pin_project; + +pub trait WarnAfterExt: Future + Sized { + /// Warns if the future takes longer than the specified number of seconds to complete. + fn warn_after_seconds(self, seconds: u8, location: &'static str) -> WarnAfterFuture { + WarnAfterFuture { + future: self, + timeout: time::sleep(Duration::from_secs(seconds as u64)), + warned: false, + start_time: std::time::Instant::now(), + location, + seconds, + } + } +} + +// Blanket implementation for all futures. +impl WarnAfterExt for F {} + +pin_project! { + /// A future that wraps another future and prints a warning if it takes too long. + pub struct WarnAfterFuture { + #[pin] + future: F, + #[pin] + timeout: Sleep, + warned: bool, + location: &'static str, + start_time: std::time::Instant, + seconds: u8, + } +} + +impl Future for WarnAfterFuture { + type Output = F::Output; + + fn poll(self: Pin<&mut Self>, cx: &mut TContext<'_>) -> Poll { + let this = self.project(); + + // Poll the timeout future to check if it has elapsed. + if !*this.warned { + if this.timeout.poll(cx).is_ready() { + tracing::warn!(location = this.location, "SLOW_QUERY: query to db taking longer than expected (> {} seconds). This is a sign the database is under heavy load, query is too heavy or database is undersized", + this.seconds, + ); + *this.warned = true; + } + } + + // Poll the wrapped future. + match this.future.poll(cx) { + Poll::Ready(output) => { + if *this.warned { + let elapsed = this.start_time.elapsed(); + tracing::warn!( + location = this.location, + "SLOW QUERY: completed with total duration: {:.2?}", + elapsed + ); + } + Poll::Ready(output) + } + Poll::Pending => Poll::Pending, + } + } +} diff --git a/backend/windmill-worker/src/result_processor.rs b/backend/windmill-worker/src/result_processor.rs index ea8a883407..6d7d6b1acf 100644 --- a/backend/windmill-worker/src/result_processor.rs +++ b/backend/windmill-worker/src/result_processor.rs @@ -14,6 +14,7 @@ use windmill_common::{ add_time, error::{self, Error}, jobs::{JobKind, QueuedJob}, + utils::WarnAfterExt, worker::{to_raw_value, WORKER_GROUP}, DB, }; @@ -431,6 +432,7 @@ pub async fn process_completed_job( #[cfg(feature = "benchmark")] bench, ) + .warn_after_seconds(10, "update_flow_status_after_job_completion success") .await?; } } @@ -469,6 +471,7 @@ pub async fn process_completed_job( #[cfg(feature = "benchmark")] bench, ) + .warn_after_seconds(10, "update_flow_status_after_job_completion error") .await?; } } diff --git a/backend/windmill-worker/src/worker.rs b/backend/windmill-worker/src/worker.rs index 0d64b30c5a..51c0c64fe1 100644 --- a/backend/windmill-worker/src/worker.rs +++ b/backend/windmill-worker/src/worker.rs @@ -9,6 +9,7 @@ use windmill_common::{ auth::{fetch_authed_from_permissioned_as, JWTAuthClaims, JobPerms, JWT_SECRET}, scripts::PREVIEW_IS_TAR_CODEBASE_HASH, + utils::WarnAfterExt, worker::{ get_memory, get_vcpus, get_windmill_memory_usage, get_worker_memory_usage, write_file, ROOT_CACHE_DIR, TMP_DIR, @@ -159,6 +160,7 @@ pub async fn create_token_for_owner_in_bg( &email, &job_id, ) + .warn_after_seconds(5, "creating token for owner") .await .expect("could not create job token"); *locked = token; @@ -1823,7 +1825,9 @@ async fn handle_queued_job( if job.parent_job.is_none() && job.created_by.starts_with("email-") { let daily_count = sqlx::query!( "SELECT value FROM metrics WHERE id = 'email_trigger_usage' AND created_at > NOW() - INTERVAL '1 day' ORDER BY created_at DESC LIMIT 1" - ).fetch_optional(db).await?.map(|x| serde_json::from_value::(x.value).unwrap_or(1)); + ).fetch_optional(db) + .warn_after_seconds(5, "getting email_trigger_usage") + .await?.map(|x| serde_json::from_value::(x.value).unwrap_or(1)); if let Some(count) = daily_count { if count >= 100 { @@ -1836,6 +1840,7 @@ async fn handle_queued_job( serde_json::json!(count + 1) ) .execute(db) + .warn_after_seconds(5, "updating email_trigger_usage") .await?; } } else { @@ -1843,6 +1848,7 @@ async fn handle_queued_job( "INSERT INTO metrics (id, value) VALUES ('email_trigger_usage', to_jsonb(1))" ) .execute(db) + .warn_after_seconds(5, "inserting email_trigger_usage") .await?; } } @@ -1855,6 +1861,7 @@ async fn handle_queued_job( .ok_or_else(|| Error::InternalErr(format!("expected parent job")))?, job.id, ) + .warn_after_seconds(5, "updating flow status in progress") .await?; Some(r) @@ -1867,6 +1874,7 @@ async fn handle_queued_job( &job.workspace_id ) .execute(db) + .warn_after_seconds(5, "updating parent job started_at flow_status") .await { tracing::error!("Could not update parent job started_at flow_status: {}", e); } @@ -1883,6 +1891,7 @@ async fn handle_queued_job( job.workspace_id ) .fetch_one(db) + .warn_after_seconds(5, "getting job raw values") .await .map(|record| (record.raw_code, record.raw_lock, record.raw_flow)) .unwrap_or_default(), @@ -1923,6 +1932,7 @@ async fn handle_queued_job( &job.parent_job.unwrap() ) .fetch_one(db) + .warn_after_seconds(5, "getting script path from queue for caching purposes") .await .map_err(|e| { Error::InternalErr(format!( @@ -1957,6 +1967,7 @@ async fn handle_queued_job( &job.workspace_id, &cached_res_path, ) + .warn_after_seconds(5, "getting cached resource value") .await; if let Some(cached_resource_value) = cached_resource_value_maybe { { @@ -1995,6 +2006,7 @@ async fn handle_queued_job( worker_dir, job_completed_tx.0.clone(), ) + .warn_after_seconds(10, "handling flow") .await?; Ok(true) } else { @@ -2285,9 +2297,11 @@ async fn handle_code_execution_job( .await? } JobKind::FlowScript => { - let (lockfile, content) = cache::flow::fetch_script(db, FlowNodeId( - job.script_hash.unwrap_or(ScriptHash(0)).0 - )).await?; + let (lockfile, content) = cache::flow::fetch_script( + db, + FlowNodeId(job.script_hash.unwrap_or(ScriptHash(0)).0), + ) + .await?; ContentReqLangEnvs { content, lockfile, diff --git a/backend/windmill-worker/src/worker_flow.rs b/backend/windmill-worker/src/worker_flow.rs index 33b17db790..a62ee84319 100644 --- a/backend/windmill-worker/src/worker_flow.rs +++ b/backend/windmill-worker/src/worker_flow.rs @@ -41,6 +41,7 @@ use windmill_common::jobs::{ script_hash_to_tag_and_limits, script_path_to_payload, BranchResults, JobPayload, QueuedJob, RawCode, ENTRYPOINT_OVERRIDE, }; +use windmill_common::utils::WarnAfterExt; use windmill_common::worker::to_raw_value; use windmill_common::{ error::{self, to_anyhow, Error}, @@ -1109,6 +1110,7 @@ pub async fn update_flow_status_after_job_completion_internal( worker_dir, job_completed_tx, ) + .warn_after_seconds(10, "handle_flow in update_flow_status") .await { Err(err) => { @@ -1510,7 +1512,7 @@ pub async fn handle_flow( let schedule_path = flow_job.schedule_path.as_ref().unwrap(); let schedule = - get_schedule_opt(&mut tx, &flow_job.workspace_id, schedule_path).await?; + get_schedule_opt(&mut tx, &flow_job.workspace_id, schedule_path).warn_after_seconds(5, "get schedule_opt in handle_flow").await?; tx.commit().await?; @@ -1522,6 +1524,7 @@ pub async fn handle_flow( flow_job.script_path.as_ref().unwrap(), &flow_job.workspace_id, ) + .warn_after_seconds(5, "handle_maybe_scheduled_job in handle_flow") .await { match err { @@ -1549,6 +1552,7 @@ pub async fn handle_flow( worker_dir, job_completed_tx, ) + .warn_after_seconds(10, "push next flow job") .await?; Ok(()) } From bb9dd7d368fa667a0921e48a815b2af434c62861 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Wed, 4 Dec 2024 18:24:31 +0100 Subject: [PATCH 07/34] simplify warn_after_seconds --- backend/windmill-common/src/utils.rs | 11 ++++++---- .../windmill-worker/src/result_processor.rs | 4 ++-- backend/windmill-worker/src/worker.rs | 20 +++++++++---------- backend/windmill-worker/src/worker_flow.rs | 8 ++++---- 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/backend/windmill-common/src/utils.rs b/backend/windmill-common/src/utils.rs index dc76c199e6..5dd89f80e1 100644 --- a/backend/windmill-common/src/utils.rs +++ b/backend/windmill-common/src/utils.rs @@ -34,7 +34,7 @@ pub const GIT_VERSION: &str = git_version!(args = ["--tag", "--always"], fallback = "unknown-version"); use crate::CRITICAL_ALERT_MUTE_UI_ENABLED; -use std::panic::{self, AssertUnwindSafe}; +use std::panic::{self, AssertUnwindSafe, Location}; use std::sync::atomic::Ordering; use crate::worker::CLOUD_HOSTED; @@ -544,13 +544,16 @@ use pin_project_lite::pin_project; pub trait WarnAfterExt: Future + Sized { /// Warns if the future takes longer than the specified number of seconds to complete. - fn warn_after_seconds(self, seconds: u8, location: &'static str) -> WarnAfterFuture { + #[track_caller] + fn warn_after_seconds(self, seconds: u8) -> WarnAfterFuture { + let caller = Location::caller(); + let location = format!("{}:{}", caller.file(), caller.line()); WarnAfterFuture { future: self, timeout: time::sleep(Duration::from_secs(seconds as u64)), warned: false, start_time: std::time::Instant::now(), - location, + location: location, seconds, } } @@ -567,7 +570,7 @@ pin_project! { #[pin] timeout: Sleep, warned: bool, - location: &'static str, + location: String, start_time: std::time::Instant, seconds: u8, } diff --git a/backend/windmill-worker/src/result_processor.rs b/backend/windmill-worker/src/result_processor.rs index 6d7d6b1acf..25bfade2e8 100644 --- a/backend/windmill-worker/src/result_processor.rs +++ b/backend/windmill-worker/src/result_processor.rs @@ -432,7 +432,7 @@ pub async fn process_completed_job( #[cfg(feature = "benchmark")] bench, ) - .warn_after_seconds(10, "update_flow_status_after_job_completion success") + .warn_after_seconds(10) .await?; } } @@ -471,7 +471,7 @@ pub async fn process_completed_job( #[cfg(feature = "benchmark")] bench, ) - .warn_after_seconds(10, "update_flow_status_after_job_completion error") + .warn_after_seconds(10) .await?; } } diff --git a/backend/windmill-worker/src/worker.rs b/backend/windmill-worker/src/worker.rs index 51c0c64fe1..f0fdc93885 100644 --- a/backend/windmill-worker/src/worker.rs +++ b/backend/windmill-worker/src/worker.rs @@ -160,7 +160,7 @@ pub async fn create_token_for_owner_in_bg( &email, &job_id, ) - .warn_after_seconds(5, "creating token for owner") + .warn_after_seconds(5) .await .expect("could not create job token"); *locked = token; @@ -1826,7 +1826,7 @@ async fn handle_queued_job( let daily_count = sqlx::query!( "SELECT value FROM metrics WHERE id = 'email_trigger_usage' AND created_at > NOW() - INTERVAL '1 day' ORDER BY created_at DESC LIMIT 1" ).fetch_optional(db) - .warn_after_seconds(5, "getting email_trigger_usage") + .warn_after_seconds(5) .await?.map(|x| serde_json::from_value::(x.value).unwrap_or(1)); if let Some(count) = daily_count { @@ -1840,7 +1840,7 @@ async fn handle_queued_job( serde_json::json!(count + 1) ) .execute(db) - .warn_after_seconds(5, "updating email_trigger_usage") + .warn_after_seconds(5) .await?; } } else { @@ -1848,7 +1848,7 @@ async fn handle_queued_job( "INSERT INTO metrics (id, value) VALUES ('email_trigger_usage', to_jsonb(1))" ) .execute(db) - .warn_after_seconds(5, "inserting email_trigger_usage") + .warn_after_seconds(5) .await?; } } @@ -1861,7 +1861,7 @@ async fn handle_queued_job( .ok_or_else(|| Error::InternalErr(format!("expected parent job")))?, job.id, ) - .warn_after_seconds(5, "updating flow status in progress") + .warn_after_seconds(5) .await?; Some(r) @@ -1874,7 +1874,7 @@ async fn handle_queued_job( &job.workspace_id ) .execute(db) - .warn_after_seconds(5, "updating parent job started_at flow_status") + .warn_after_seconds(5) .await { tracing::error!("Could not update parent job started_at flow_status: {}", e); } @@ -1891,7 +1891,7 @@ async fn handle_queued_job( job.workspace_id ) .fetch_one(db) - .warn_after_seconds(5, "getting job raw values") + .warn_after_seconds(5) .await .map(|record| (record.raw_code, record.raw_lock, record.raw_flow)) .unwrap_or_default(), @@ -1932,7 +1932,7 @@ async fn handle_queued_job( &job.parent_job.unwrap() ) .fetch_one(db) - .warn_after_seconds(5, "getting script path from queue for caching purposes") + .warn_after_seconds(5) .await .map_err(|e| { Error::InternalErr(format!( @@ -1967,7 +1967,7 @@ async fn handle_queued_job( &job.workspace_id, &cached_res_path, ) - .warn_after_seconds(5, "getting cached resource value") + .warn_after_seconds(5) .await; if let Some(cached_resource_value) = cached_resource_value_maybe { { @@ -2006,7 +2006,7 @@ async fn handle_queued_job( worker_dir, job_completed_tx.0.clone(), ) - .warn_after_seconds(10, "handling flow") + .warn_after_seconds(10) .await?; Ok(true) } else { diff --git a/backend/windmill-worker/src/worker_flow.rs b/backend/windmill-worker/src/worker_flow.rs index a62ee84319..1e4aefdba0 100644 --- a/backend/windmill-worker/src/worker_flow.rs +++ b/backend/windmill-worker/src/worker_flow.rs @@ -1110,7 +1110,7 @@ pub async fn update_flow_status_after_job_completion_internal( worker_dir, job_completed_tx, ) - .warn_after_seconds(10, "handle_flow in update_flow_status") + .warn_after_seconds(10) .await { Err(err) => { @@ -1512,7 +1512,7 @@ pub async fn handle_flow( let schedule_path = flow_job.schedule_path.as_ref().unwrap(); let schedule = - get_schedule_opt(&mut tx, &flow_job.workspace_id, schedule_path).warn_after_seconds(5, "get schedule_opt in handle_flow").await?; + get_schedule_opt(&mut tx, &flow_job.workspace_id, schedule_path).warn_after_seconds(5).await?; tx.commit().await?; @@ -1524,7 +1524,7 @@ pub async fn handle_flow( flow_job.script_path.as_ref().unwrap(), &flow_job.workspace_id, ) - .warn_after_seconds(5, "handle_maybe_scheduled_job in handle_flow") + .warn_after_seconds(5) .await { match err { @@ -1552,7 +1552,7 @@ pub async fn handle_flow( worker_dir, job_completed_tx, ) - .warn_after_seconds(10, "push next flow job") + .warn_after_seconds(10) .await?; Ok(()) } From db62a2c53cba6457df1bfc020833af715cc5c615 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Wed, 4 Dec 2024 18:28:05 +0100 Subject: [PATCH 08/34] simplify warn_after_seconds --- backend/windmill-common/src/job_metrics.rs | 3 ++- backend/windmill-common/src/utils.rs | 2 +- backend/windmill-queue/src/jobs.rs | 9 ++++++--- backend/windmill-worker/src/worker_flow.rs | 4 +++- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/backend/windmill-common/src/job_metrics.rs b/backend/windmill-common/src/job_metrics.rs index c0c2300fed..6577e34d6e 100644 --- a/backend/windmill-common/src/job_metrics.rs +++ b/backend/windmill-common/src/job_metrics.rs @@ -1,4 +1,4 @@ -use crate::{db::DB, error}; +use crate::{db::DB, error, utils::WarnAfterExt}; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -90,6 +90,7 @@ pub async fn register_metric_for_job( .bind(timeseries_int) .bind(timeseries_float) .execute(db) + .warn_after_seconds(1) .await?; Ok(metric_id) diff --git a/backend/windmill-common/src/utils.rs b/backend/windmill-common/src/utils.rs index 5dd89f80e1..c13f96e2de 100644 --- a/backend/windmill-common/src/utils.rs +++ b/backend/windmill-common/src/utils.rs @@ -599,7 +599,7 @@ impl Future for WarnAfterFuture { let elapsed = this.start_time.elapsed(); tracing::warn!( location = this.location, - "SLOW QUERY: completed with total duration: {:.2?}", + "SLOW_QUERY: completed with total duration: {:.2?}", elapsed ); } diff --git a/backend/windmill-queue/src/jobs.rs b/backend/windmill-queue/src/jobs.rs index 2390ca47bb..1e516f4821 100644 --- a/backend/windmill-queue/src/jobs.rs +++ b/backend/windmill-queue/src/jobs.rs @@ -39,8 +39,8 @@ use windmill_audit::audit_ee::{audit_log, AuditAuthor}; use windmill_audit::ActionKind; use windmill_common::{ - cache, auth::{fetch_authed_from_permissioned_as, permissioned_as_to_username}, + cache, db::{Authed, UserDB}, error::{self, to_anyhow, Error}, flow_status::{ @@ -57,7 +57,7 @@ use windmill_common::{ schedule::Schedule, scripts::{get_full_hub_script_by_path, ScriptHash, ScriptLang}, users::{SUPERADMIN_NOTIFICATION_EMAIL, SUPERADMIN_SECRET_EMAIL}, - utils::{not_found_if_none, report_critical_error, StripPath}, + utils::{not_found_if_none, report_critical_error, StripPath, WarnAfterExt}, worker::{ to_raw_value, CLOUD_HOSTED, DEFAULT_TAGS_PER_WORKSPACE, DEFAULT_TAGS_WORKSPACES, DISABLE_FLOW_SCRIPT, MIN_VERSION_IS_AT_LEAST_1_427, MIN_VERSION_IS_AT_LEAST_1_432, NO_LOGS, @@ -318,6 +318,7 @@ pub async fn append_logs( workspace.as_ref(), ) .execute(db.borrow()) + .warn_after_seconds(1) .await { tracing::error!(%job_id, %err, "error updating logs for large_log job {job_id}: {err}"); @@ -3227,7 +3228,7 @@ pub async fn push<'c, 'd>( None, None, ) - }, + } JobPayload::ScriptHub { path } => { if path == "hub/7771/slack" || path == "hub/7836/slack" { permissioned_as = SUPERADMIN_NOTIFICATION_EMAIL.to_string(); @@ -3851,6 +3852,7 @@ pub async fn push<'c, 'd>( tag, ) .execute(&mut *tx) + .warn_after_seconds(1) .await?; let (raw_code, raw_lock, raw_flow) = if !*MIN_VERSION_IS_AT_LEAST_1_427.read().await { @@ -3901,6 +3903,7 @@ pub async fn push<'c, 'd>( final_priority, ) .fetch_one(&mut *tx) + .warn_after_seconds(1) .await .map_err(|e| Error::InternalErr(format!("Could not insert into queue {job_id} with tag {tag}, schedule_path {schedule_path:?}, script_path: {script_path:?}, email {email}, workspace_id {workspace_id}: {e:#}")))?; diff --git a/backend/windmill-worker/src/worker_flow.rs b/backend/windmill-worker/src/worker_flow.rs index 1e4aefdba0..050f0ebcf4 100644 --- a/backend/windmill-worker/src/worker_flow.rs +++ b/backend/windmill-worker/src/worker_flow.rs @@ -2137,6 +2137,7 @@ async fn push_next_flow_job( .bind(status.step) .bind(json!(status.retry.failed_jobs)) .execute(db) + .warn_after_seconds(2) .await .context("update flow retry")?; @@ -2562,6 +2563,7 @@ async fn push_next_flow_job( new_job_priority_override, job_perms.as_ref(), ) + .warn_after_seconds(2) .await?; tracing::debug!(id = %flow_job.id, root_id = %job_root, "pushed next flow job: {uuid}"); @@ -2774,7 +2776,7 @@ async fn push_next_flow_job( .execute(&mut *tx) .await?; - tx.commit().await?; + tx.commit().warn_after_seconds(3).await?; tracing::info!(id = %flow_job.id, root_id = %job_root, "all next flow jobs pushed: {uuids:?}"); if continue_on_same_worker { From ff8e98feb8b703af597759a2454f272ddd0036c8 Mon Sep 17 00:00:00 2001 From: wendrul <53628737+wendrul@users.noreply.github.com> Date: Wed, 4 Dec 2024 18:33:41 +0100 Subject: [PATCH 09/34] Remove unused env vars from docker compose + css fixes (#4841) --- docker-compose.yml | 6 --- .../search/GlobalSearchModal.svelte | 4 +- .../SplitPanesOrColumnOnMobile.svelte | 44 +++++++++---------- .../(root)/(logged)/service_logs/+page.svelte | 2 +- 4 files changed, 25 insertions(+), 31 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index d45e589808..13d1c3ac98 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -129,12 +129,6 @@ services: - PORT=8001 - DATABASE_URL=${DATABASE_URL} - MODE=indexer - - TANTIVY_MAX_INDEXED_JOB_LOG_SIZE__MB=1 # job logs bigger than this will be truncated before indexing - - TANTIVY_S3_BACKUP_PERIOD__S=3600 # how often to backup the index into object storage - - TANTIVY_INDEX_WRITER_MEMORY_BUDGET__MB=100 # higher budget for higher indexing throughput - - TANTIVY_REFRESH_INDEX_PERIOD__S=300 #how often to start indexing new jobs - - TANTIVY_DOC_COMMIT_MAX_BATCH_SIZE=100000 #how many documents to batch in one commit - - TANTIVY_SHOW_MEMORY_EVERY=10000 #log memory usage and progress every so many documents indexed depends_on: db: condition: service_healthy diff --git a/frontend/src/lib/components/search/GlobalSearchModal.svelte b/frontend/src/lib/components/search/GlobalSearchModal.svelte index 599e8853cb..fc4db3bcf0 100644 --- a/frontend/src/lib/components/search/GlobalSearchModal.svelte +++ b/frontend/src/lib/components/search/GlobalSearchModal.svelte @@ -33,7 +33,7 @@ import ContentSearchInner from '../ContentSearchInner.svelte' import { goto } from '$app/navigation' import QuickMenuItem from '../search/QuickMenuItem.svelte' - import { enterpriseLicense, superadmin, workspaceStore } from '$lib/stores' + import { devopsRole, enterpriseLicense, superadmin, workspaceStore } from '$lib/stores' import uFuzzy from '@leeoniya/ufuzzy' import BarsStaggered from '../icons/BarsStaggered.svelte' import { scroll_into_view_if_needed_polyfill } from '../multiselect/utils' @@ -610,7 +610,7 @@ /> {:else if tab === 'logs'}
- {#if !$superadmin} + {#if !$devopsRole} Service logs are only available to superadmins diff --git a/frontend/src/lib/components/splitPanes/SplitPanesOrColumnOnMobile.svelte b/frontend/src/lib/components/splitPanes/SplitPanesOrColumnOnMobile.svelte index a609b74637..39191e6ade 100644 --- a/frontend/src/lib/components/splitPanes/SplitPanesOrColumnOnMobile.svelte +++ b/frontend/src/lib/components/splitPanes/SplitPanesOrColumnOnMobile.svelte @@ -11,27 +11,27 @@ let clientWidth = window.innerWidth -
- {#if clientWidth >= 768} -