mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-09 16:05:42 +00:00
fix: deploy ai chat drafts with metadata
This commit is contained in:
@@ -794,6 +794,161 @@ describe('global AI tools', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('deploys DB script drafts with draft metadata when no local draft exists', async () => {
|
||||
vi.mocked(ScriptService.existsScriptByPath)
|
||||
.mockResolvedValueOnce(true)
|
||||
.mockResolvedValueOnce(true)
|
||||
vi.mocked(ScriptService.getScriptByPathWithDraft).mockResolvedValueOnce({
|
||||
path: 'f/scripts/existing',
|
||||
hash: 'deployed-hash',
|
||||
summary: 'deployed summary',
|
||||
description: 'deployed description',
|
||||
content: 'deployed content',
|
||||
schema: {},
|
||||
is_template: false,
|
||||
language: 'bun',
|
||||
kind: 'script',
|
||||
tag: 'deployed-tag',
|
||||
envs: ['DEPLOYED_ENV'],
|
||||
timeout: 60,
|
||||
visible_to_runner_only: true,
|
||||
labels: ['deployed'],
|
||||
draft: {
|
||||
path: 'f/scripts/existing',
|
||||
summary: 'db draft summary',
|
||||
description: 'db draft description',
|
||||
content: 'db draft content',
|
||||
language: 'bun',
|
||||
kind: 'script',
|
||||
tag: 'draft-tag',
|
||||
envs: [],
|
||||
timeout: 0,
|
||||
visible_to_runner_only: false,
|
||||
labels: []
|
||||
}
|
||||
} as any)
|
||||
vi.mocked(ScriptService.getScriptByPath).mockResolvedValueOnce({
|
||||
path: 'f/scripts/existing',
|
||||
hash: 'deployed-hash',
|
||||
summary: 'deployed summary',
|
||||
description: 'deployed description',
|
||||
content: 'deployed content',
|
||||
schema: {},
|
||||
is_template: false,
|
||||
language: 'bun',
|
||||
kind: 'script',
|
||||
tag: 'deployed-tag',
|
||||
envs: ['DEPLOYED_ENV'],
|
||||
timeout: 60,
|
||||
visible_to_runner_only: true,
|
||||
labels: ['deployed']
|
||||
} as any)
|
||||
|
||||
await callGlobalTool('deploy_workspace_item', {
|
||||
type: 'script',
|
||||
path: 'f/scripts/existing',
|
||||
deployment_message: 'ship db draft'
|
||||
})
|
||||
|
||||
expect(ScriptService.createScript).toHaveBeenCalledWith({
|
||||
workspace: WORKSPACE,
|
||||
requestBody: expect.objectContaining({
|
||||
path: 'f/scripts/existing',
|
||||
parent_hash: 'deployed-hash',
|
||||
summary: 'db draft summary',
|
||||
description: 'db draft description',
|
||||
content: 'db draft content',
|
||||
language: 'bun',
|
||||
tag: 'draft-tag',
|
||||
envs: [],
|
||||
timeout: 0,
|
||||
visible_to_runner_only: false,
|
||||
labels: [],
|
||||
deployment_message: 'ship db draft'
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('deploys DB flow drafts with draft metadata when no local draft exists', async () => {
|
||||
vi.mocked(FlowService.existsFlowByPath).mockResolvedValueOnce(true).mockResolvedValueOnce(true)
|
||||
vi.mocked(FlowService.getFlowByPathWithDraft).mockResolvedValueOnce({
|
||||
path: 'f/flows/existing',
|
||||
summary: 'deployed summary',
|
||||
description: 'deployed description',
|
||||
value: {
|
||||
modules: [{ id: 'deployed_step', value: { type: 'identity' } }]
|
||||
},
|
||||
schema: { type: 'object', properties: { deployed: { type: 'boolean' } } },
|
||||
edited_by: 'admin',
|
||||
edited_at: '2026-05-22T09:00:00Z',
|
||||
archived: false,
|
||||
extra_perms: {},
|
||||
tag: 'deployed-tag',
|
||||
timeout: 60,
|
||||
visible_to_runner_only: true,
|
||||
labels: ['deployed'],
|
||||
draft: {
|
||||
path: 'f/flows/existing',
|
||||
summary: 'db draft summary',
|
||||
description: 'db draft description',
|
||||
value: {
|
||||
modules: [{ id: 'draft_step', value: { type: 'identity' } }]
|
||||
},
|
||||
schema: { type: 'object', properties: { draft: { type: 'string' } } },
|
||||
edited_by: 'admin',
|
||||
edited_at: '2026-05-22T10:00:00Z',
|
||||
archived: false,
|
||||
extra_perms: {},
|
||||
tag: 'draft-tag',
|
||||
timeout: 0,
|
||||
visible_to_runner_only: false,
|
||||
labels: []
|
||||
}
|
||||
} as any)
|
||||
vi.mocked(FlowService.getFlowByPath).mockResolvedValueOnce({
|
||||
path: 'f/flows/existing',
|
||||
summary: 'deployed summary',
|
||||
description: 'deployed description',
|
||||
value: {
|
||||
modules: [{ id: 'deployed_step', value: { type: 'identity' } }]
|
||||
},
|
||||
schema: { type: 'object', properties: { deployed: { type: 'boolean' } } },
|
||||
edited_by: 'admin',
|
||||
edited_at: '2026-05-22T09:00:00Z',
|
||||
archived: false,
|
||||
extra_perms: {},
|
||||
tag: 'deployed-tag',
|
||||
timeout: 60,
|
||||
visible_to_runner_only: true,
|
||||
labels: ['deployed']
|
||||
} as any)
|
||||
|
||||
await callGlobalTool('deploy_workspace_item', {
|
||||
type: 'flow',
|
||||
path: 'f/flows/existing',
|
||||
deployment_message: 'ship db draft'
|
||||
})
|
||||
|
||||
expect(FlowService.updateFlow).toHaveBeenCalledWith({
|
||||
workspace: WORKSPACE,
|
||||
path: 'f/flows/existing',
|
||||
requestBody: expect.objectContaining({
|
||||
path: 'f/flows/existing',
|
||||
summary: 'db draft summary',
|
||||
description: 'db draft description',
|
||||
schema: { type: 'object', properties: { draft: { type: 'string' } } },
|
||||
tag: 'draft-tag',
|
||||
timeout: 0,
|
||||
visible_to_runner_only: false,
|
||||
labels: [],
|
||||
deployment_message: 'ship db draft'
|
||||
})
|
||||
})
|
||||
expect(vi.mocked(FlowService.updateFlow).mock.calls[0]?.[0].requestBody.value.modules).toEqual([
|
||||
{ id: 'draft_step', value: { type: 'identity' } }
|
||||
])
|
||||
})
|
||||
|
||||
it('applies path_prefix to local drafts before enforcing the result limit', async () => {
|
||||
await callGlobalTool('write_script', {
|
||||
path: 'f/other/outside',
|
||||
|
||||
@@ -95,7 +95,12 @@ import {
|
||||
type WorkspaceItem,
|
||||
type WorkspaceItemType
|
||||
} from './workspaceItems'
|
||||
import { buildFlowDeployRequestBody, buildScriptDeployRequestBody } from './deployRequests'
|
||||
import {
|
||||
buildFlowDeployRequestBody,
|
||||
buildScriptDeployRequestBody,
|
||||
type FlowDeployMetadata,
|
||||
type ScriptDeployMetadata
|
||||
} from './deployRequests'
|
||||
import { userStore } from '$lib/stores'
|
||||
import { get } from 'svelte/store'
|
||||
import { bundleRawAppDraft } from './rawAppBundlerBridge'
|
||||
@@ -2165,6 +2170,11 @@ function buildVariableDeployRequestBody(
|
||||
}
|
||||
|
||||
type DbDraftWorkspaceItemType = Extract<WorkspaceItemType, 'script' | 'flow' | 'app'>
|
||||
type DeployableDraft = {
|
||||
item: WorkspaceItem
|
||||
scriptMetadata?: ScriptDeployMetadata
|
||||
flowMetadata?: FlowDeployMetadata
|
||||
}
|
||||
|
||||
function isDbDraftWorkspaceItemType(type: WorkspaceItemType): type is DbDraftWorkspaceItemType {
|
||||
return type === 'script' || type === 'flow' || type === 'app'
|
||||
@@ -2233,27 +2243,31 @@ async function deleteDbDraftAndDraftOnlyAnchor(
|
||||
}
|
||||
}
|
||||
|
||||
async function loadDbDraftItem(
|
||||
async function loadDbDraftForDeploy(
|
||||
workspace: string,
|
||||
type: DbDraftWorkspaceItemType,
|
||||
path: string
|
||||
): Promise<WorkspaceItem | undefined> {
|
||||
): Promise<DeployableDraft | undefined> {
|
||||
switch (type) {
|
||||
case 'script': {
|
||||
if (!(await ScriptService.existsScriptByPath({ workspace, path }))) return undefined
|
||||
const script = await ScriptService.getScriptByPathWithDraft({ workspace, path })
|
||||
if (!script.draft && !script.draft_only) return undefined
|
||||
return scriptToItem(
|
||||
script.draft ? { ...script, ...script.draft, path: script.path } : script,
|
||||
true,
|
||||
true
|
||||
)
|
||||
const draftScript = script.draft ? { ...script, ...script.draft, path: script.path } : script
|
||||
return {
|
||||
item: scriptToItem(draftScript, true, true),
|
||||
scriptMetadata: draftScript
|
||||
}
|
||||
}
|
||||
case 'flow': {
|
||||
if (!(await FlowService.existsFlowByPath({ workspace, path }))) return undefined
|
||||
const flow = await FlowService.getFlowByPathWithDraft({ workspace, path })
|
||||
if (!flow.draft && !flow.draft_only) return undefined
|
||||
return flowToItem(flow.draft ? { ...flow, ...flow.draft, path: flow.path } : flow, true, true)
|
||||
const draftFlow = flow.draft ? { ...flow, ...flow.draft, path: flow.path } : flow
|
||||
return {
|
||||
item: flowToItem(draftFlow, true, true),
|
||||
flowMetadata: draftFlow
|
||||
}
|
||||
}
|
||||
case 'app': {
|
||||
if (!(await AppService.existsApp({ workspace, path }))) return undefined
|
||||
@@ -2261,16 +2275,26 @@ async function loadDbDraftItem(
|
||||
if (!app.draft && !app.draft_only) return undefined
|
||||
const value = appSourceToDraftValue(app.draft ?? app, app)
|
||||
return {
|
||||
type: 'app',
|
||||
path: app.path,
|
||||
summary: value.summary,
|
||||
value,
|
||||
isDraft: true
|
||||
item: {
|
||||
type: 'app',
|
||||
path: app.path,
|
||||
summary: value.summary,
|
||||
value,
|
||||
isDraft: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function loadDbDraftItem(
|
||||
workspace: string,
|
||||
type: DbDraftWorkspaceItemType,
|
||||
path: string
|
||||
): Promise<WorkspaceItem | undefined> {
|
||||
return (await loadDbDraftForDeploy(workspace, type, path))?.item
|
||||
}
|
||||
|
||||
async function getGlobalOrDbDraft(
|
||||
workspace: string,
|
||||
type: WorkspaceItemType,
|
||||
@@ -2283,6 +2307,34 @@ async function getGlobalOrDbDraft(
|
||||
return loadDbDraftItem(workspace, type, path)
|
||||
}
|
||||
|
||||
async function getGlobalOrDbDraftForDeploy(
|
||||
workspace: string,
|
||||
type: WorkspaceItemType,
|
||||
path: string,
|
||||
triggerKind?: TriggerKind
|
||||
): Promise<DeployableDraft | undefined> {
|
||||
const item = getGlobalDraft(workspace, type, path, triggerKind)
|
||||
if (item) {
|
||||
const storagePath = getGlobalDraftStoragePath(workspace, type, path, triggerKind)
|
||||
switch (type) {
|
||||
case 'script':
|
||||
return {
|
||||
item,
|
||||
scriptMetadata: UserDraft.get<NewScript>('script', storagePath, { workspace })
|
||||
}
|
||||
case 'flow':
|
||||
return {
|
||||
item,
|
||||
flowMetadata: UserDraft.get<Flow>('flow', storagePath, { workspace })
|
||||
}
|
||||
default:
|
||||
return { item }
|
||||
}
|
||||
}
|
||||
if (!isDbDraftWorkspaceItemType(type)) return undefined
|
||||
return loadDbDraftForDeploy(workspace, type, path)
|
||||
}
|
||||
|
||||
function startDraftWrite(ctx: WriteDraftCtx, type: WorkspaceItemType, path: string): void {
|
||||
ctx.toolCallbacks.setToolStatus(ctx.toolId, {
|
||||
content: `Saving ${type} "${path}" as a draft...`
|
||||
@@ -3403,10 +3455,11 @@ async function deployDraft(
|
||||
throw new Error('trigger_kind is required when deploying a trigger.')
|
||||
}
|
||||
|
||||
const draft = await getGlobalOrDbDraft(workspace, type, path, triggerKind)
|
||||
if (!draft) {
|
||||
const deployableDraft = await getGlobalOrDbDraftForDeploy(workspace, type, path, triggerKind)
|
||||
if (!deployableDraft) {
|
||||
throw new Error(`No draft found for ${type} "${path}".`)
|
||||
}
|
||||
const { item: draft } = deployableDraft
|
||||
if (draft.value === undefined) {
|
||||
throw new Error(`Draft ${type} "${path}" has no value to deploy.`)
|
||||
}
|
||||
@@ -3422,7 +3475,13 @@ async function deployDraft(
|
||||
const existing = (await ScriptService.existsScriptByPath({ workspace, path }))
|
||||
? await ScriptService.getScriptByPath({ workspace, path })
|
||||
: undefined
|
||||
const requestBody = buildScriptDeployRequestBody(path, draft, existing, deploymentMessage)
|
||||
const requestBody = buildScriptDeployRequestBody(
|
||||
path,
|
||||
draft,
|
||||
existing,
|
||||
deploymentMessage,
|
||||
deployableDraft.scriptMetadata
|
||||
)
|
||||
// Infer the arg schema from the content so it matches the code, like the editor does.
|
||||
try {
|
||||
const schema = emptySchema()
|
||||
@@ -3444,7 +3503,8 @@ async function deployDraft(
|
||||
draft.summary,
|
||||
flowDraft,
|
||||
existing,
|
||||
deploymentMessage
|
||||
deploymentMessage,
|
||||
deployableDraft.flowMetadata
|
||||
)
|
||||
if (existing) {
|
||||
await FlowService.updateFlow({ workspace, path, requestBody })
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import type { Flow, NewScript, Script } from '$lib/gen/types.gen'
|
||||
import { buildFlowDeployRequestBody, buildScriptDeployRequestBody } from './deployRequests'
|
||||
import {
|
||||
buildFlowDeployRequestBody,
|
||||
buildScriptDeployRequestBody,
|
||||
type FlowDeployMetadata,
|
||||
type ScriptDeployMetadata
|
||||
} from './deployRequests'
|
||||
import type { WorkspaceItem } from './workspaceItems'
|
||||
|
||||
describe('global AI deploy request builders', () => {
|
||||
@@ -93,6 +98,93 @@ describe('global AI deploy request builders', () => {
|
||||
expect(requestBody.lock).toBeUndefined()
|
||||
})
|
||||
|
||||
it('uses script draft metadata over existing deployed metadata', () => {
|
||||
const existing = {
|
||||
hash: 'parent-hash',
|
||||
path: 'f/demo/script',
|
||||
summary: 'existing summary',
|
||||
description: 'existing description',
|
||||
content: 'old content',
|
||||
schema: { properties: { existing: { type: 'string' } } },
|
||||
is_template: true,
|
||||
language: 'bun',
|
||||
kind: 'script',
|
||||
tag: 'old-tag',
|
||||
envs: ['OLD_ENV'],
|
||||
concurrent_limit: 5,
|
||||
cache_ttl: 300,
|
||||
cache_ignore_s3_path: false,
|
||||
dedicated_worker: true,
|
||||
ws_error_handler_muted: true,
|
||||
priority: 10,
|
||||
timeout: 120,
|
||||
visible_to_runner_only: true,
|
||||
on_behalf_of_email: 'existing@example.com',
|
||||
assets: [{ path: 's3://old/key', kind: 's3object' }],
|
||||
modules: { 'old.ts': { content: 'export const old = 1', language: 'bun' } },
|
||||
labels: ['old']
|
||||
} as unknown as Script & Partial<NewScript>
|
||||
const draft: WorkspaceItem = {
|
||||
type: 'script',
|
||||
path: 'f/demo/script',
|
||||
summary: 'draft summary',
|
||||
language: 'bun',
|
||||
value: 'new content',
|
||||
isDraft: true
|
||||
}
|
||||
const draftMetadata: ScriptDeployMetadata = {
|
||||
description: 'draft description',
|
||||
schema: { properties: { draft: { type: 'boolean' } } },
|
||||
tag: 'draft-tag',
|
||||
envs: [],
|
||||
concurrent_limit: 0,
|
||||
cache_ttl: 0,
|
||||
cache_ignore_s3_path: true,
|
||||
dedicated_worker: false,
|
||||
ws_error_handler_muted: false,
|
||||
priority: 0,
|
||||
timeout: 0,
|
||||
visible_to_runner_only: false,
|
||||
on_behalf_of_email: 'draft@example.com',
|
||||
assets: [{ path: 's3://draft/key', kind: 's3object' }],
|
||||
modules: null,
|
||||
labels: []
|
||||
}
|
||||
|
||||
const requestBody = buildScriptDeployRequestBody(
|
||||
'f/demo/script',
|
||||
draft,
|
||||
existing,
|
||||
'ai deploy',
|
||||
draftMetadata
|
||||
)
|
||||
|
||||
expect(requestBody).toMatchObject({
|
||||
path: 'f/demo/script',
|
||||
parent_hash: 'parent-hash',
|
||||
summary: 'draft summary',
|
||||
description: 'draft description',
|
||||
content: 'new content',
|
||||
schema: draftMetadata.schema,
|
||||
tag: 'draft-tag',
|
||||
envs: [],
|
||||
concurrent_limit: 0,
|
||||
cache_ttl: 0,
|
||||
cache_ignore_s3_path: true,
|
||||
dedicated_worker: false,
|
||||
ws_error_handler_muted: false,
|
||||
priority: 0,
|
||||
timeout: 0,
|
||||
visible_to_runner_only: false,
|
||||
on_behalf_of_email: 'draft@example.com',
|
||||
preserve_on_behalf_of: true,
|
||||
assets: draftMetadata.assets,
|
||||
modules: null,
|
||||
labels: [],
|
||||
deployment_message: 'ai deploy'
|
||||
})
|
||||
})
|
||||
|
||||
it('preserves existing flow metadata and uses draft value/schema overrides', () => {
|
||||
const existing = {
|
||||
path: 'f/demo/flow',
|
||||
@@ -143,6 +235,67 @@ describe('global AI deploy request builders', () => {
|
||||
expect(requestBody.value.groups).toEqual(draftValue.groups)
|
||||
})
|
||||
|
||||
it('uses flow draft metadata over existing deployed metadata', () => {
|
||||
const existing = {
|
||||
path: 'f/demo/flow',
|
||||
summary: 'existing summary',
|
||||
description: 'existing description',
|
||||
value: { modules: [] },
|
||||
schema: { required: ['existing'] },
|
||||
tag: 'old-tag',
|
||||
ws_error_handler_muted: true,
|
||||
priority: 7,
|
||||
dedicated_worker: true,
|
||||
timeout: 60,
|
||||
visible_to_runner_only: true,
|
||||
on_behalf_of_email: 'existing@example.com',
|
||||
labels: ['old']
|
||||
} as unknown as Flow
|
||||
const draftValue = {
|
||||
value: { modules: [{ id: 'step', value: { type: 'identity' } }] },
|
||||
schema: { properties: { draft: { type: 'string' } } },
|
||||
groups: null
|
||||
}
|
||||
const draftMetadata: FlowDeployMetadata = {
|
||||
description: 'draft description',
|
||||
tag: 'draft-tag',
|
||||
ws_error_handler_muted: false,
|
||||
priority: 0,
|
||||
dedicated_worker: false,
|
||||
timeout: 0,
|
||||
visible_to_runner_only: false,
|
||||
on_behalf_of_email: undefined,
|
||||
labels: []
|
||||
}
|
||||
|
||||
const requestBody = buildFlowDeployRequestBody(
|
||||
'f/demo/flow',
|
||||
'draft summary',
|
||||
draftValue as any,
|
||||
existing,
|
||||
'ai deploy',
|
||||
draftMetadata
|
||||
)
|
||||
|
||||
expect(requestBody).toMatchObject({
|
||||
path: 'f/demo/flow',
|
||||
summary: 'draft summary',
|
||||
description: 'draft description',
|
||||
schema: draftValue.schema,
|
||||
tag: 'draft-tag',
|
||||
ws_error_handler_muted: false,
|
||||
priority: 0,
|
||||
dedicated_worker: false,
|
||||
timeout: 0,
|
||||
visible_to_runner_only: false,
|
||||
labels: [],
|
||||
deployment_message: 'ai deploy'
|
||||
})
|
||||
expect(requestBody.on_behalf_of_email).toBeUndefined()
|
||||
expect(requestBody.preserve_on_behalf_of).toBeUndefined()
|
||||
expect(requestBody.value.groups).toBeUndefined()
|
||||
})
|
||||
|
||||
it('falls back to existing flow schema when the draft has no schema', () => {
|
||||
const existing = {
|
||||
path: 'f/demo/flow',
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { Flow, NewScript, OpenFlowWPath, Script } from '$lib/gen/types.gen'
|
||||
import type { FlowDraftValue, WorkspaceItem } from './workspaceItems'
|
||||
|
||||
type ScriptWithDeployMetadata = Script & Partial<Pick<NewScript, 'assets' | 'cache_ignore_s3_path'>>
|
||||
export type ScriptDeployMetadata = Partial<Script> & Partial<NewScript>
|
||||
export type FlowDeployMetadata = Partial<Flow>
|
||||
|
||||
export type FlowDeployRequestBody = OpenFlowWPath & {
|
||||
deployment_message?: string
|
||||
@@ -11,56 +12,110 @@ function preserveOnBehalfOf(email: string | undefined): true | undefined {
|
||||
return email ? true : undefined
|
||||
}
|
||||
|
||||
function deployMetadataField<T extends object, K extends keyof T>(
|
||||
draftMetadata: T | undefined,
|
||||
existing: T | undefined,
|
||||
key: K
|
||||
): T[K] | undefined {
|
||||
if (draftMetadata && Object.prototype.hasOwnProperty.call(draftMetadata, key)) {
|
||||
return draftMetadata[key]
|
||||
}
|
||||
return existing?.[key]
|
||||
}
|
||||
|
||||
export function buildScriptDeployRequestBody(
|
||||
path: string,
|
||||
draft: WorkspaceItem,
|
||||
existing: Script | undefined,
|
||||
deploymentMessage: string | undefined
|
||||
deploymentMessage: string | undefined,
|
||||
draftMetadata?: ScriptDeployMetadata
|
||||
): NewScript {
|
||||
if (typeof draft.value !== 'string' || !draft.language) {
|
||||
throw new Error(`Draft script "${path}" is missing content or language.`)
|
||||
}
|
||||
|
||||
const existingWithMetadata = existing as ScriptWithDeployMetadata | undefined
|
||||
const existingWithMetadata = existing as ScriptDeployMetadata | undefined
|
||||
const onBehalfOfEmail = deployMetadataField(
|
||||
draftMetadata,
|
||||
existingWithMetadata,
|
||||
'on_behalf_of_email'
|
||||
)
|
||||
|
||||
return {
|
||||
path,
|
||||
summary: draft.summary ?? existing?.summary ?? '',
|
||||
description: existing?.description ?? '',
|
||||
summary:
|
||||
draft.summary ?? deployMetadataField(draftMetadata, existingWithMetadata, 'summary') ?? '',
|
||||
description: deployMetadataField(draftMetadata, existingWithMetadata, 'description') ?? '',
|
||||
content: draft.value,
|
||||
parent_hash: existing?.hash,
|
||||
schema: existing?.schema,
|
||||
is_template: existing?.is_template,
|
||||
schema: deployMetadataField(draftMetadata, existingWithMetadata, 'schema'),
|
||||
is_template: deployMetadataField(draftMetadata, existingWithMetadata, 'is_template'),
|
||||
language: draft.language,
|
||||
kind: existing?.kind,
|
||||
tag: existing?.tag,
|
||||
envs: existing?.envs,
|
||||
concurrent_limit: existing?.concurrent_limit,
|
||||
concurrency_time_window_s: existing?.concurrency_time_window_s,
|
||||
debounce_key: existing?.debounce_key,
|
||||
debounce_delay_s: existing?.debounce_delay_s,
|
||||
debounce_args_to_accumulate: existing?.debounce_args_to_accumulate,
|
||||
max_total_debouncing_time: existing?.max_total_debouncing_time,
|
||||
max_total_debounces_amount: existing?.max_total_debounces_amount,
|
||||
cache_ttl: existing?.cache_ttl,
|
||||
cache_ignore_s3_path: existingWithMetadata?.cache_ignore_s3_path,
|
||||
dedicated_worker: existing?.dedicated_worker,
|
||||
ws_error_handler_muted: existing?.ws_error_handler_muted,
|
||||
priority: existing?.priority,
|
||||
restart_unless_cancelled: existing?.restart_unless_cancelled,
|
||||
timeout: existing?.timeout,
|
||||
delete_after_secs: existing?.delete_after_secs,
|
||||
kind: deployMetadataField(draftMetadata, existingWithMetadata, 'kind'),
|
||||
tag: deployMetadataField(draftMetadata, existingWithMetadata, 'tag'),
|
||||
envs: deployMetadataField(draftMetadata, existingWithMetadata, 'envs'),
|
||||
concurrent_limit: deployMetadataField(draftMetadata, existingWithMetadata, 'concurrent_limit'),
|
||||
concurrency_time_window_s: deployMetadataField(
|
||||
draftMetadata,
|
||||
existingWithMetadata,
|
||||
'concurrency_time_window_s'
|
||||
),
|
||||
debounce_key: deployMetadataField(draftMetadata, existingWithMetadata, 'debounce_key'),
|
||||
debounce_delay_s: deployMetadataField(draftMetadata, existingWithMetadata, 'debounce_delay_s'),
|
||||
debounce_args_to_accumulate: deployMetadataField(
|
||||
draftMetadata,
|
||||
existingWithMetadata,
|
||||
'debounce_args_to_accumulate'
|
||||
),
|
||||
max_total_debouncing_time: deployMetadataField(
|
||||
draftMetadata,
|
||||
existingWithMetadata,
|
||||
'max_total_debouncing_time'
|
||||
),
|
||||
max_total_debounces_amount: deployMetadataField(
|
||||
draftMetadata,
|
||||
existingWithMetadata,
|
||||
'max_total_debounces_amount'
|
||||
),
|
||||
cache_ttl: deployMetadataField(draftMetadata, existingWithMetadata, 'cache_ttl'),
|
||||
cache_ignore_s3_path: deployMetadataField(
|
||||
draftMetadata,
|
||||
existingWithMetadata,
|
||||
'cache_ignore_s3_path'
|
||||
),
|
||||
dedicated_worker: deployMetadataField(draftMetadata, existingWithMetadata, 'dedicated_worker'),
|
||||
ws_error_handler_muted: deployMetadataField(
|
||||
draftMetadata,
|
||||
existingWithMetadata,
|
||||
'ws_error_handler_muted'
|
||||
),
|
||||
priority: deployMetadataField(draftMetadata, existingWithMetadata, 'priority'),
|
||||
restart_unless_cancelled: deployMetadataField(
|
||||
draftMetadata,
|
||||
existingWithMetadata,
|
||||
'restart_unless_cancelled'
|
||||
),
|
||||
timeout: deployMetadataField(draftMetadata, existingWithMetadata, 'timeout'),
|
||||
delete_after_secs: deployMetadataField(
|
||||
draftMetadata,
|
||||
existingWithMetadata,
|
||||
'delete_after_secs'
|
||||
),
|
||||
deployment_message: deploymentMessage,
|
||||
concurrency_key: existing?.concurrency_key,
|
||||
visible_to_runner_only: existing?.visible_to_runner_only,
|
||||
auto_kind: existing?.auto_kind,
|
||||
codebase: existing?.codebase,
|
||||
has_preprocessor: existing?.has_preprocessor,
|
||||
on_behalf_of_email: existing?.on_behalf_of_email,
|
||||
preserve_on_behalf_of: preserveOnBehalfOf(existing?.on_behalf_of_email),
|
||||
assets: existingWithMetadata?.assets,
|
||||
modules: existing?.modules,
|
||||
labels: existing?.labels
|
||||
concurrency_key: deployMetadataField(draftMetadata, existingWithMetadata, 'concurrency_key'),
|
||||
visible_to_runner_only: deployMetadataField(
|
||||
draftMetadata,
|
||||
existingWithMetadata,
|
||||
'visible_to_runner_only'
|
||||
),
|
||||
auto_kind: deployMetadataField(draftMetadata, existingWithMetadata, 'auto_kind'),
|
||||
codebase: deployMetadataField(draftMetadata, existingWithMetadata, 'codebase'),
|
||||
has_preprocessor: deployMetadataField(draftMetadata, existingWithMetadata, 'has_preprocessor'),
|
||||
on_behalf_of_email: onBehalfOfEmail,
|
||||
preserve_on_behalf_of: preserveOnBehalfOf(onBehalfOfEmail),
|
||||
assets: deployMetadataField(draftMetadata, existingWithMetadata, 'assets'),
|
||||
modules: deployMetadataField(draftMetadata, existingWithMetadata, 'modules'),
|
||||
labels: deployMetadataField(draftMetadata, existingWithMetadata, 'labels')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,23 +134,26 @@ export function buildFlowDeployRequestBody(
|
||||
draftSummary: string | undefined,
|
||||
flowDraft: FlowDraftValue,
|
||||
existing: Flow | undefined,
|
||||
deploymentMessage: string | undefined
|
||||
deploymentMessage: string | undefined,
|
||||
draftMetadata?: FlowDeployMetadata
|
||||
): FlowDeployRequestBody {
|
||||
const onBehalfOfEmail = deployMetadataField(draftMetadata, existing, 'on_behalf_of_email')
|
||||
|
||||
return {
|
||||
path,
|
||||
summary: draftSummary ?? existing?.summary ?? '',
|
||||
description: existing?.description ?? '',
|
||||
summary: draftSummary ?? deployMetadataField(draftMetadata, existing, 'summary') ?? '',
|
||||
description: deployMetadataField(draftMetadata, existing, 'description') ?? '',
|
||||
value: flowValueWithDraftGroups(flowDraft),
|
||||
schema: flowDraft.schema ?? existing?.schema ?? {},
|
||||
tag: existing?.tag,
|
||||
ws_error_handler_muted: existing?.ws_error_handler_muted,
|
||||
priority: existing?.priority,
|
||||
dedicated_worker: existing?.dedicated_worker,
|
||||
timeout: existing?.timeout,
|
||||
visible_to_runner_only: existing?.visible_to_runner_only,
|
||||
on_behalf_of_email: existing?.on_behalf_of_email,
|
||||
preserve_on_behalf_of: preserveOnBehalfOf(existing?.on_behalf_of_email),
|
||||
labels: existing?.labels,
|
||||
schema: flowDraft.schema ?? deployMetadataField(draftMetadata, existing, 'schema') ?? {},
|
||||
tag: deployMetadataField(draftMetadata, existing, 'tag'),
|
||||
ws_error_handler_muted: deployMetadataField(draftMetadata, existing, 'ws_error_handler_muted'),
|
||||
priority: deployMetadataField(draftMetadata, existing, 'priority'),
|
||||
dedicated_worker: deployMetadataField(draftMetadata, existing, 'dedicated_worker'),
|
||||
timeout: deployMetadataField(draftMetadata, existing, 'timeout'),
|
||||
visible_to_runner_only: deployMetadataField(draftMetadata, existing, 'visible_to_runner_only'),
|
||||
on_behalf_of_email: onBehalfOfEmail,
|
||||
preserve_on_behalf_of: preserveOnBehalfOf(onBehalfOfEmail),
|
||||
labels: deployMetadataField(draftMetadata, existing, 'labels'),
|
||||
deployment_message: deploymentMessage
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user