mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-18 16:02:10 +00:00
feat: Workspace error handler now supports args and Slack for EE (#2447)
* feat: Workspace error handler now supports args and Slack * Cleanup unused value * run sqlx prepare * Fix script path loading
This commit is contained in:
committed by
GitHub
parent
221965546d
commit
a55cb50b5d
-1
@@ -37,7 +37,6 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
+7
-1
@@ -72,6 +72,11 @@
|
||||
"ordinal": 13,
|
||||
"name": "code_completion_enabled",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 14,
|
||||
"name": "error_handler_extra_args",
|
||||
"type_info": "Json"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
@@ -93,7 +98,8 @@
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "1730f39fd1793d45fbb41b21389c61296a3ff7489ae12f52a19f9543173ac597"
|
||||
|
||||
-1
@@ -67,7 +67,6 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
-1
@@ -28,7 +28,6 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
+7
-1
@@ -72,6 +72,11 @@
|
||||
"ordinal": 13,
|
||||
"name": "code_completion_enabled",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 14,
|
||||
"name": "error_handler_extra_args",
|
||||
"type_info": "Json"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
@@ -93,7 +98,8 @@
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "5445083864b2b092b012e894bff7630a1d7b9deb8d33e9f909061f351f96844e"
|
||||
|
||||
-1
@@ -42,7 +42,6 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
-1
@@ -42,7 +42,6 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
-1
@@ -46,7 +46,6 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
-1
@@ -40,7 +40,6 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
-1
@@ -60,7 +60,6 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
-1
@@ -42,7 +42,6 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE workspace_settings SET error_handler = NULL WHERE workspace_id = $1",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "c0635f65d561c1a6b183b8fea45320482375d0bb5e617a9dd236a631a7b9ff05"
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE workspace_settings SET error_handler = NULL, error_handler_extra_args = NULL WHERE workspace_id = $1",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "d9308c0154e029f7568b1d021368ca07f4867d192aa58b3888ae532d1c040828"
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE workspace_settings SET error_handler = $1 WHERE workspace_id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Varchar",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "e844b9ee75a1b5438ffe743185fc78f649db89c78b2b8cd7e778bf18a6b41e67"
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE workspace_settings SET error_handler = $1, error_handler_extra_args = $2 WHERE workspace_id = $3",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Varchar",
|
||||
"Json",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "ea2ad5213bb6de8eab502fbb76149fa7964cd11e74e5ed1a30e857aad8ea5595"
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
-- Add down migration script here
|
||||
ALTER TABLE workspace_settings DROP COLUMN error_handler_extra_args;
|
||||
@@ -0,0 +1,2 @@
|
||||
-- Add up migration script here
|
||||
ALTER TABLE workspace_settings ADD COLUMN error_handler_extra_args JSON;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1158,6 +1158,8 @@ paths:
|
||||
type: boolean
|
||||
error_handler:
|
||||
type: string
|
||||
error_handler_extra_args:
|
||||
$ref: "#/components/schemas/ScriptArgs"
|
||||
required:
|
||||
- code_completion_enabled
|
||||
|
||||
@@ -1419,6 +1421,8 @@ paths:
|
||||
properties:
|
||||
error_handler:
|
||||
type: string
|
||||
error_handler_extra_args:
|
||||
$ref: "#/components/schemas/ScriptArgs"
|
||||
|
||||
responses:
|
||||
"200":
|
||||
|
||||
@@ -95,7 +95,6 @@ async fn create_schedule(
|
||||
Json(ns): Json<NewSchedule>,
|
||||
) -> Result<String> {
|
||||
let authed = maybe_refresh_folders(&ns.path, &w_id, authed, &db).await;
|
||||
let mut tx: QueueTransaction<'_, _> = (rsmq, user_db.begin(&authed).await?).into();
|
||||
|
||||
#[cfg(not(feature = "enterprise"))]
|
||||
if ns.on_recovery.is_some() {
|
||||
@@ -121,6 +120,8 @@ async fn create_schedule(
|
||||
));
|
||||
}
|
||||
|
||||
let mut tx: QueueTransaction<'_, _> = (rsmq, user_db.begin(&authed).await?).into();
|
||||
|
||||
cron::Schedule::from_str(&ns.schedule).map_err(|e| Error::BadRequest(e.to_string()))?;
|
||||
check_path_conflict(tx.transaction_mut(), &w_id, &ns.path).await?;
|
||||
check_flow_conflict(
|
||||
|
||||
@@ -132,6 +132,7 @@ pub struct WorkspaceSettings {
|
||||
pub openai_resource_path: Option<String>,
|
||||
pub code_completion_enabled: bool,
|
||||
pub error_handler: Option<String>,
|
||||
pub error_handler_extra_args: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
#[derive(FromRow, Serialize, Debug)]
|
||||
@@ -243,6 +244,7 @@ pub struct NewWorkspaceUser {
|
||||
#[derive(Deserialize)]
|
||||
pub struct EditErrorHandler {
|
||||
pub error_handler: Option<String>,
|
||||
pub error_handler_extra_args: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
async fn list_pending_invites(
|
||||
@@ -807,6 +809,15 @@ async fn edit_error_handler(
|
||||
) -> Result<String> {
|
||||
require_admin(is_admin, &username)?;
|
||||
|
||||
#[cfg(not(feature = "enterprise"))]
|
||||
if ee.error_handler.is_some()
|
||||
&& ee.error_handler.as_ref().unwrap() == "script/hub/2431/slack/schedule-error-handler-slack"
|
||||
{
|
||||
return Err(Error::BadRequest(
|
||||
"Slack error handler is only available in enterprise version".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let mut tx = db.begin().await?;
|
||||
|
||||
sqlx::query_as!(
|
||||
@@ -821,17 +832,17 @@ async fn edit_error_handler(
|
||||
.await?;
|
||||
|
||||
if let Some(error_handler) = &ee.error_handler {
|
||||
|
||||
sqlx::query!(
|
||||
"UPDATE workspace_settings SET error_handler = $1 WHERE workspace_id = $2",
|
||||
"UPDATE workspace_settings SET error_handler = $1, error_handler_extra_args = $2 WHERE workspace_id = $3",
|
||||
error_handler,
|
||||
ee.error_handler_extra_args,
|
||||
&w_id
|
||||
)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
} else {
|
||||
sqlx::query!(
|
||||
"UPDATE workspace_settings SET error_handler = NULL WHERE workspace_id = $1",
|
||||
"UPDATE workspace_settings SET error_handler = NULL, error_handler_extra_args = NULL WHERE workspace_id = $1",
|
||||
&w_id,
|
||||
)
|
||||
.execute(&mut *tx)
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
export let showScriptHelpText: boolean = false
|
||||
export let handlerSelected: 'custom' | 'slack'
|
||||
export let handlersOnlyForEe: string[]
|
||||
export let customScriptTooltip: string | undefined = undefined
|
||||
|
||||
export let handlerPath: string | undefined
|
||||
export let handlerExtraArgs: Record<string, any>
|
||||
|
||||
export let customInitialScriptPath: string | undefined
|
||||
export let customScriptTemplate: string
|
||||
export let customHandlerKind: 'flow' | 'script' = 'script'
|
||||
let customHandlerSchema: Schema | undefined
|
||||
@@ -168,7 +168,7 @@
|
||||
<div class="flex flex-row mb-2">
|
||||
<ScriptPicker
|
||||
disabled={!isEditable}
|
||||
initialPath={handlerPath}
|
||||
initialPath={customInitialScriptPath}
|
||||
kind={Script.kind.SCRIPT}
|
||||
allowFlow={true}
|
||||
bind:scriptPath={handlerPath}
|
||||
|
||||
@@ -28,9 +28,11 @@
|
||||
let itemKind: 'flow' | 'script' = 'script'
|
||||
let errorHandleritemKind: 'flow' | 'script' = 'script'
|
||||
let errorHandlerPath: string | undefined = undefined
|
||||
let errorHandlerCustomInitialPath: string | undefined = undefined
|
||||
let errorHandlerSelected: 'custom' | 'slack' = 'slack'
|
||||
let errorHandlerExtraArgs: Record<string, any> = {}
|
||||
let recoveryHandlerPath: string | undefined = undefined
|
||||
let recoveryHandlerCustomInitialPath: string | undefined = undefined
|
||||
let recoveryHandlerSelected: 'custom' | 'slack' = 'slack'
|
||||
let recoveryHandlerItemKind: 'flow' | 'script' = 'script'
|
||||
let recoveryHandlerExtraArgs: Record<string, any> = {}
|
||||
@@ -64,9 +66,11 @@
|
||||
errorHandlerSelected = $enterpriseLicense ? 'slack' : 'custom'
|
||||
errorHandleritemKind = 'script'
|
||||
errorHandlerPath = undefined
|
||||
errorHandlerCustomInitialPath = undefined
|
||||
errorHandlerExtraArgs = {}
|
||||
recoveryHandlerSelected = $enterpriseLicense ? 'slack' : 'custom'
|
||||
recoveryHandlerPath = undefined
|
||||
recoveryHandlerCustomInitialPath = undefined
|
||||
recoveryHandlerItemKind = 'script'
|
||||
recoveryHandlerExtraArgs = {}
|
||||
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
@@ -125,6 +129,7 @@
|
||||
let splitted = s.on_failure.split('/')
|
||||
errorHandleritemKind = splitted[0] as 'flow' | 'script'
|
||||
errorHandlerPath = splitted.slice(1)?.join('/')
|
||||
errorHandlerCustomInitialPath = errorHandlerPath
|
||||
failedTimes = s.on_failure_times ?? 1
|
||||
failedExact = s.on_failure_exact ?? false
|
||||
errorHandlerExtraArgs = s.on_failure_extra_args ?? {}
|
||||
@@ -139,6 +144,7 @@
|
||||
let splitted = s.on_recovery.split('/')
|
||||
recoveryHandlerItemKind = splitted[0] as 'flow' | 'script'
|
||||
recoveryHandlerPath = splitted.slice(1)?.join('/')
|
||||
recoveryHandlerCustomInitialPath = recoveryHandlerPath
|
||||
recoveredTimes = s.on_recovery_times ?? 1
|
||||
recoveryHandlerExtraArgs = s.on_recovery_extra_args ?? {}
|
||||
if (recoveryHandlerPath !== slackRecoveryHandler) {
|
||||
@@ -173,7 +179,7 @@
|
||||
on_failure: errorHandlerPath ? `${errorHandleritemKind}/${errorHandlerPath}` : undefined,
|
||||
on_failure_times: failedTimes,
|
||||
on_failure_exact: failedExact,
|
||||
on_failure_extra_args: errorHandlerPath ? errorHandlerExtraArgs : {},
|
||||
on_failure_extra_args: errorHandlerPath ? errorHandlerExtraArgs : undefined,
|
||||
on_recovery: recoveryHandlerPath
|
||||
? `${recoveryHandlerItemKind}/${recoveryHandlerPath}`
|
||||
: undefined,
|
||||
@@ -196,7 +202,7 @@
|
||||
on_failure: errorHandlerPath ? `${errorHandleritemKind}/${errorHandlerPath}` : undefined,
|
||||
on_failure_times: failedTimes,
|
||||
on_failure_exact: failedExact,
|
||||
on_failure_extra_args: errorHandlerPath ? errorHandlerExtraArgs : {},
|
||||
on_failure_extra_args: errorHandlerPath ? errorHandlerExtraArgs : undefined,
|
||||
on_recovery: recoveryHandlerPath
|
||||
? `${recoveryHandlerItemKind}/${recoveryHandlerPath}`
|
||||
: undefined,
|
||||
@@ -331,9 +337,9 @@
|
||||
isEditable={can_write}
|
||||
handlersOnlyForEe={['slack']}
|
||||
showScriptHelpText={true}
|
||||
customScriptTooltip="Hello"
|
||||
bind:handlerSelected={errorHandlerSelected}
|
||||
bind:handlerPath={errorHandlerPath}
|
||||
customInitialScriptPath={errorHandlerCustomInitialPath}
|
||||
slackHandlerScriptPath={slackErrorHandler}
|
||||
slackToggleText="Alert channel on error"
|
||||
customScriptTemplate="/scripts/add?hub=hub%2F2420%2Fwindmill%2Fschedule_error_handler_template"
|
||||
@@ -395,6 +401,7 @@
|
||||
handlersOnlyForEe={[]}
|
||||
bind:handlerSelected={recoveryHandlerSelected}
|
||||
bind:handlerPath={recoveryHandlerPath}
|
||||
customInitialScriptPath={recoveryHandlerCustomInitialPath}
|
||||
slackHandlerScriptPath={slackRecoveryHandler}
|
||||
slackToggleText="Alert channel when error recovered"
|
||||
customScriptTemplate="/scripts/add?hub=hub%2F2421%2Fwindmill%2Fschedule_recovery_handler_template"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { Alert, Badge, Button, Tab, Tabs } from '$lib/components/common'
|
||||
|
||||
import DeployToSetting from '$lib/components/DeployToSetting.svelte'
|
||||
import ErrorOrRecoveryHandler from '$lib/components/ErrorOrRecoveryHandler.svelte'
|
||||
import PageHeader from '$lib/components/PageHeader.svelte'
|
||||
import ResourcePicker from '$lib/components/ResourcePicker.svelte'
|
||||
import ScriptPicker from '$lib/components/ScriptPicker.svelte'
|
||||
@@ -23,7 +24,7 @@
|
||||
workspaceStore
|
||||
} from '$lib/stores'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { setQueryWithoutLoad } from '$lib/utils'
|
||||
import { setQueryWithoutLoad, emptyString } from '$lib/utils'
|
||||
import { faSlack } from '@fortawesome/free-brands-svg-icons'
|
||||
import { faBarsStaggered, faScroll } from '@fortawesome/free-solid-svg-icons'
|
||||
import { Slack } from 'lucide-svelte'
|
||||
@@ -31,6 +32,8 @@
|
||||
import PremiumInfo from '$lib/components/settings/PremiumInfo.svelte'
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
|
||||
const slackErrorHandler = 'hub/2431/slack/schedule-error-handler-slack'
|
||||
|
||||
let initialPath: string
|
||||
let scriptPath: string
|
||||
let team_name: string | undefined
|
||||
@@ -39,9 +42,11 @@
|
||||
let customer_id: string | undefined = undefined
|
||||
let webhook: string | undefined = undefined
|
||||
let workspaceToDeployTo: string | undefined = undefined
|
||||
let errorHandlerInitialPath: string
|
||||
let errorHandlerSelected: 'custom' | 'slack' = 'slack'
|
||||
let errorHandlerInitialScriptPath: string
|
||||
let errorHandlerScriptPath: string
|
||||
let errorHandlerItemKind: 'script' = 'script'
|
||||
let errorHandlerItemKind: 'flow' | 'script' = 'script'
|
||||
let errorHandlerExtraArgs: Record<string, any> = {}
|
||||
let openaiResourceInitialPath: string | undefined = undefined
|
||||
let codeCompletionEnabled: boolean = false
|
||||
let tab =
|
||||
@@ -159,7 +164,13 @@
|
||||
webhook = settings.webhook
|
||||
openaiResourceInitialPath = settings.openai_resource_path
|
||||
errorHandlerScriptPath = (settings.error_handler ?? '').split('/').slice(1).join('/')
|
||||
errorHandlerInitialPath = errorHandlerScriptPath
|
||||
errorHandlerInitialScriptPath = errorHandlerScriptPath
|
||||
if (emptyString($enterpriseLicense)) {
|
||||
errorHandlerSelected = 'custom'
|
||||
} else {
|
||||
errorHandlerSelected = emptyString(errorHandlerScriptPath) || errorHandlerScriptPath === slackErrorHandler ? 'slack' : 'custom'
|
||||
}
|
||||
errorHandlerExtraArgs = settings.error_handler_extra_args ?? {}
|
||||
codeCompletionEnabled = settings.code_completion_enabled
|
||||
}
|
||||
|
||||
@@ -170,17 +181,22 @@
|
||||
}
|
||||
|
||||
async function editErrorHandler() {
|
||||
errorHandlerInitialPath = errorHandlerScriptPath
|
||||
if (errorHandlerScriptPath) {
|
||||
await WorkspaceService.editErrorHandler({
|
||||
workspace: $workspaceStore!,
|
||||
requestBody: { error_handler: `${errorHandlerItemKind}/${errorHandlerScriptPath}` }
|
||||
requestBody: {
|
||||
error_handler: `${errorHandlerItemKind}/${errorHandlerScriptPath}`,
|
||||
error_handler_extra_args: errorHandlerExtraArgs,
|
||||
}
|
||||
})
|
||||
sendUserToast(`workspace error handler set to ${errorHandlerScriptPath}`)
|
||||
} else {
|
||||
await WorkspaceService.editErrorHandler({
|
||||
workspace: $workspaceStore!,
|
||||
requestBody: { error_handler: undefined }
|
||||
requestBody: {
|
||||
error_handler: undefined,
|
||||
error_handler_extra_args: undefined,
|
||||
}
|
||||
})
|
||||
sendUserToast(`workspace error handler removed`)
|
||||
}
|
||||
@@ -422,41 +438,51 @@
|
||||
</div>
|
||||
{:else if tab == 'error_handler'}
|
||||
<PageHeader title="Script to run as error handler" primary={false} />
|
||||
<ScriptPicker
|
||||
kind={undefined}
|
||||
bind:itemKind={errorHandlerItemKind}
|
||||
bind:scriptPath={errorHandlerScriptPath}
|
||||
initialPath={errorHandlerInitialPath}
|
||||
on:select={editErrorHandler}
|
||||
allowRefresh
|
||||
/>
|
||||
<div class="flex flex-col gap-20 items-start mt-3">
|
||||
<div class="w-2/3">
|
||||
<div class="text-tertiary text-xs">
|
||||
The following args will be passed to the error handler:
|
||||
<ul class="mt-1 ml-2">
|
||||
<li><b>path</b>: The path of the script or flow that errored.</li>
|
||||
<li><b>email</b>: The email of the user who ran the script or flow that errored.</li>
|
||||
<li><b>error</b>: The error details.</li>
|
||||
<li><b>job_id</b>: The job id.</li>
|
||||
<li><b>is_flow</b>: Whether the error comes from a flow.</li>
|
||||
<li><b>workspace_id</b>: The workspace id of the failed script or flow.</li>
|
||||
</ul>
|
||||
<br />
|
||||
The error handler will be executed by the automatically created group g/error_handler. If
|
||||
your error handler requires variables or resources, you need to add them to the group.
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-1/3 flex items-start">
|
||||
<div class="mt-2">
|
||||
<!-- Adjusted margin class -->
|
||||
<Button
|
||||
href="/scripts/add?hub=hub%2F1088%2Fwindmill%2FGlobal_%2F_workspace_error_handler_template"
|
||||
target="_blank">Use template</Button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ErrorOrRecoveryHandler
|
||||
isEditable={true}
|
||||
handlersOnlyForEe={['slack']}
|
||||
showScriptHelpText={true}
|
||||
customInitialScriptPath={errorHandlerInitialScriptPath}
|
||||
bind:handlerSelected={errorHandlerSelected}
|
||||
bind:handlerPath={errorHandlerScriptPath}
|
||||
slackHandlerScriptPath={slackErrorHandler}
|
||||
customScriptTemplate="/scripts/add?hub=hub%2F2420%2Fwindmill%2Fworkspace_error_handler_template"
|
||||
bind:customHandlerKind={errorHandlerItemKind}
|
||||
bind:handlerExtraArgs={errorHandlerExtraArgs}
|
||||
>
|
||||
<svelte:fragment slot="custom-tab-tooltip">
|
||||
<Tooltip>
|
||||
<div class="flex gap-20 items-start mt-3">
|
||||
<div class="text-sm">
|
||||
The following args will be passed to the error handler:
|
||||
<ul class="mt-1 ml-2">
|
||||
<li><b>path</b>: The path of the script or flow that errored.</li>
|
||||
<li><b>email</b>: The email of the user who ran the script or flow that errored.</li>
|
||||
<li><b>error</b>: The error details.</li>
|
||||
<li><b>job_id</b>: The job id.</li>
|
||||
<li><b>is_flow</b>: Whether the error comes from a flow.</li>
|
||||
<li><b>workspace_id</b>: The workspace id of the failed script or flow.</li>
|
||||
</ul>
|
||||
<br />
|
||||
The error handler will be executed by the automatically created group g/error_handler. If
|
||||
your error handler requires variables or resources, you need to add them to the group.
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</svelte:fragment>
|
||||
</ErrorOrRecoveryHandler>
|
||||
|
||||
<div class="flex mt-5 justify-start">
|
||||
<Button
|
||||
disabled={(errorHandlerSelected === 'slack' && !emptyString(errorHandlerScriptPath) && emptyString(errorHandlerExtraArgs['channel']))}
|
||||
size="sm"
|
||||
on:click={editErrorHandler}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{:else if tab == 'openai'}
|
||||
<PageHeader title="Windmill AI" primary={false} />
|
||||
<div class="mt-2">
|
||||
|
||||
Reference in New Issue
Block a user