From 4de344d4eeb2d0b1b3bee8b35f3d8f23a090fb40 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Mon, 31 Aug 2026 04:50:52 -0700 Subject: [PATCH] fix(automations): preserve destination form save semantics (cherry picked from commit a793b07c12b1a57be9763d0558e7785c3a2047a3) --- .../automation-orca-save-operations.ts | 28 +++++++++---------- .../automations/automation-orca-save.ts | 1 + .../use-automations-page-destination-form.ts | 22 +++++++++++++-- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/renderer/src/components/automations/automation-orca-save-operations.ts b/src/renderer/src/components/automations/automation-orca-save-operations.ts index c8623d4af61..b12874d0036 100644 --- a/src/renderer/src/components/automations/automation-orca-save-operations.ts +++ b/src/renderer/src/components/automations/automation-orca-save-operations.ts @@ -236,30 +236,28 @@ export async function createAutomationOnDestination( export async function saveExistingAutomation( context: AutomationSaveContext, + automationId: string, currentAutomation: Automation | null, updates: AutomationUpdateInput, destination: AutomationDestination | undefined, fallbackTarget: AutomationHostTarget | null, rowKey: string | null ): Promise> { - if (!currentAutomation) { - return { - ok: false, - notice: { - message: translate( - 'auto.components.automations.AutomationsPage.ownerChanged', - 'This automation changed hosts. Refresh and try again.' - ), - recovery: 'retry', - severity: 'owner' - } - } - } return await dispatchAutomationUpdate( context.destination.automationDispatchContext, - { rowKey: rowKey ?? '', automationId: currentAutomation.id }, + { rowKey: rowKey ?? '', automationId }, updates, - () => updateAutomationForTarget(currentAutomation, updates, fallbackTarget), + () => { + if (!currentAutomation) { + throw new Error( + translate( + 'auto.components.automations.AutomationsPage.ownerChanged', + 'This automation changed hosts. Refresh and try again.' + ) + ) + } + return updateAutomationForTarget(currentAutomation, updates, fallbackTarget) + }, 'save', destination ) diff --git a/src/renderer/src/components/automations/automation-orca-save.ts b/src/renderer/src/components/automations/automation-orca-save.ts index f556412b27c..8459aaf0659 100644 --- a/src/renderer/src/components/automations/automation-orca-save.ts +++ b/src/renderer/src/components/automations/automation-orca-save.ts @@ -232,6 +232,7 @@ export async function saveOrcaAutomation( } else if (editingAutomationId !== null) { saved = await saveExistingAutomation( context, + editingAutomationId, currentAutomation, updates, editDestination, diff --git a/src/renderer/src/components/automations/use-automations-page-destination-form.ts b/src/renderer/src/components/automations/use-automations-page-destination-form.ts index a7b7072f5a0..c9f91cb2f37 100644 --- a/src/renderer/src/components/automations/use-automations-page-destination-form.ts +++ b/src/renderer/src/components/automations/use-automations-page-destination-form.ts @@ -51,6 +51,7 @@ export function useAutomationsPageDestinationForm({ settings } = store const { + createOpen, createTarget, editingAutomationId, editingRowKey, @@ -58,6 +59,7 @@ export function useAutomationsPageDestinationForm({ setEditingHostStableKey, setEditingDestination, setDraft, + draft, draftRef } = local const { visibleRows, hostCatalog, capturedAutomationOwners } = list @@ -162,9 +164,23 @@ export function useAutomationsPageDestinationForm({ ? editHostProjects : editorProjects : getAutomationCreateRepos(repos, { kind: 'local' }) + + // A destination change can strand the chosen project on another host; clear + // it so the draft/default-target effect can select a project the host owns. + useEffect(() => { + if (!createOpen || editingAutomationId !== null || createTarget !== 'orca') { + return + } + setDraft((current) => + !current.projectId || editorProjects.some((project) => project.id === current.projectId) + ? current + : { ...current, projectId: '', workspaceId: '', baseBranch: '' } + ) + }, [createOpen, createTarget, editingAutomationId, editorProjects, setDraft]) + const dialogWorktrees = useMemo(() => { - const candidates = worktreesByRepo[draftRef.current.projectId] ?? [] - const project = dialogRepos.find((repo) => repo.id === draftRef.current.projectId) + const candidates = worktreesByRepo[draft.projectId] ?? [] + const project = dialogRepos.find((repo) => repo.id === draft.projectId) if (!project) { return candidates } @@ -179,7 +195,7 @@ export function useAutomationsPageDestinationForm({ worktree.runtimeOwnerEnvironmentId === parsedHost.environmentId ) }) - }, [dialogRepos, draftRef, worktreesByRepo]) + }, [dialogRepos, draft.projectId, worktreesByRepo]) const destinationForProject = useCallback( (projectId: string, hostStableKey?: string | null): AutomationCreateDestination | null => { const selectedEntry = hostStableKey