feat(workflows): wire Cancel button into workflow-editor test runs (TKAI-173) - #99
feat(workflows): wire Cancel button into workflow-editor test runs (TKAI-173)#99yourbuddyconner wants to merge 1 commit into
Conversation
…KAI-173) Add a Cancel button to the workflow-editor test-run surface so users can bail out of an in-flight run without refreshing the page. The backend cancellation path was already implemented (POST /executions/:id/cancel, runCancellationCleanup for approvals + spawned sessions + in-flight tool calls); this is client wiring only. - Cancel button in the ExecutionSummaryPane on the Executions tab of the workflow editor, gated on the execution being non-terminal. - Cancel button in the editor header next to Test, visible while the test-run mutation is pending or the selected execution is still active. Lets users bail during the brief window between clicking Test and the execution row appearing. - Both use the two-phase armed-double-click pattern already established on the execution detail page (first click arms, second confirms, auto-disarms after 4s). - Two new pure model helpers (getCancelButtonState, shouldShowExecutionCancel) drive both sites and are unit-tested.
|
Preview deployment: https://pr-99.dev-valet-turnkey-client.pages.dev |
68e9b2e to
0cfed1c
Compare
xBalbinus
left a comment
There was a problem hiding this comment.
Extracting getCancelButtonState / shouldShowExecutionCancel as tested pure functions is exactly the right shape. Two real bugs in the toolbar path and one state gap, then cleanup.
-
Wrong-execution cancel ($workflowId.tsx:303): during the
testRun.isPendingwindow,handleCancelTestRuntargetsselectedExecutionId— which still holds the previously auto-selected execution (set on mount at :137) untilonSuccessreassigns it (:277). A confirm-click in that window cancels the prior run (or errors against a terminal one) while toasting "Test run cancelled". The execution detail page is immune because its target is the immutable route param; this one isn't. -
That same
isPendingvisibility branch appears unreachable (:423): test runs start only from the manual-run dialog, whose modal overlay covers the toolbar untilonSuccesscloses it — so the "bail during startup" window the comment describes can't actually be clicked. Given 1 + 2, the simplest fix is to drop theisPendingbranch and show the toolbar Cancel only once the new execution is selected. -
A stuck
cancellingexecution presents a live Cancel: button state derives only from client-sidearmed/isPending(workflow-execution-viewer.tsx:376), so once the mutation resolves, an execution the server holds incancelling(local dev produces this routinely —instance.terminate()is unimplemented there) reverts to a re-clickable "Cancel" that will keep failing.getCancelButtonStatealready has the right shape to take the server status as an input and render a terminal "Cancelling…".
Cleanup, non-blocking: the toolbar and summary pane can render two independent Cancel buttons for the same execution with separate armed state (:600); the arm/4s-disarm machine is duplicated in both, and the toolbar copy misses the disarm-on-not-cancelable effect the pane has (:151) — a small useCancelArm hook would fix the drift and the stale-arm carryover; TERMINAL_EXECUTION_STATUSES is hand-copied from api/executions with only a keep-in-sync comment (workflow-execution-viewer-model.ts:9); and the persisted cancel reason hardcodes "test run" even when cancelling a non-test execution from the editor page (:313).
xBalbinus
left a comment
There was a problem hiding this comment.
The Test-row Cancel button copies the two-phase armed-confirm pattern but omits the reset that its sibling ExecutionSummaryPane has ($workflowId.tsx:104 and :151). testCancelArmed is never cleared when the button hides or the run goes terminal, so the armed state carries from a finished run into a new one and a single click cancels the fresh run, defeating the confirm step. Mirror the sibling with useEffect(() => { if (!showTestCancel) setTestCancelArmed(false) }, [showTestCancel]).
shouldShowExecutionCancel and its private TERMINAL_EXECUTION_STATUSES copy (workflow-execution-viewer-model.ts:58) duplicate the exported isActiveExecutionStatus and TERMINAL_EXECUTION_STATUSES from @/api/executions.ts and will drift out of sync. Call the shared helper instead.
Summary
Adds a Cancel button to the workflow-editor test-run UI so users can bail on a running test without refreshing the page. Wires client UI onto the existing backend cancellation path — no backend changes.
Two entry points:
WorkflowExecutionViewer): Cancel button appears in the execution summary pane next to Retry, whenever the selected execution's status is active perisActiveExecutionStatus.Cancel testbutton appears whiletestRun.isPendingOR the current execution is active, so users can bail before an execution row exists.Both buttons use the armed-double-click pattern verbatim from
packages/client/src/routes/automation/executions/$executionId.tsx:66-82— first click arms, second confirms, 4s auto-disarm. State transitions and render gates are extracted as pure helpers inworkflow-execution-viewer-model.tsso both call sites share the same model.Backend is already implemented and unchanged:
POST /executions/:id/cancelinpackages/worker/src/routes/executions.ts(andPOST /:id/executions/:executionId/cancelinpackages/worker/src/routes/workflows.ts)runCancellationCleanupinpackages/worker/src/workflows/cancel-cleanup.tshandles approvals, spawned sessions, in-flight tool calls, and CAS on the execution row.Before: user had to refresh the page to know a stuck test run had drained; no way to actively stop it. After: Cancel button surfaces in the editor and in the execution viewer while the run is active; clicking twice sends the cancel request and the server-side cleanup pipeline drains the run.
Linear: https://linear.app/turnkey/issue/TKAI-173/
Test plan
pnpm -F @valet/client test— 281/281 pass (13 new tests covering the state machine + render gates)pnpm -F @valet/client typecheck— cleanpnpm -F @valet/client build— clean (Vite build succeeded)