Revert "Remove code generation deletion confirmation prompt" (#4639)
Co-authored-by: Suchintan Singh <suchintan@skyvern.com>
This commit is contained in:
@@ -356,6 +356,8 @@ function Workspace({
|
|||||||
|
|
||||||
await saveWorkflow.mutateAsync();
|
await saveWorkflow.mutateAsync();
|
||||||
|
|
||||||
|
workflowChangesStore.setSaidOkToCodeCacheDeletion(false);
|
||||||
|
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
queryKey: ["cache-key-values", workflowPermanentId, cacheKey],
|
queryKey: ["cache-key-values", workflowPermanentId, cacheKey],
|
||||||
});
|
});
|
||||||
@@ -1111,6 +1113,40 @@ function Workspace({
|
|||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
|
{/* confirm code cache deletion dialog */}
|
||||||
|
<Dialog
|
||||||
|
open={workflowChangesStore.showConfirmCodeCacheDeletion}
|
||||||
|
onOpenChange={(open) => {
|
||||||
|
!open && workflowChangesStore.setShowConfirmCodeCacheDeletion(false);
|
||||||
|
!open && workflowChangesStore.setSaidOkToCodeCacheDeletion(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Are you sure?</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Saving will delete cached code, and Skyvern will re-generate it in
|
||||||
|
the next run. Proceed?
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogFooter>
|
||||||
|
<DialogClose asChild>
|
||||||
|
<Button variant="secondary">Cancel</Button>
|
||||||
|
</DialogClose>
|
||||||
|
<Button
|
||||||
|
variant="default"
|
||||||
|
onClick={async () => {
|
||||||
|
workflowChangesStore.setSaidOkToCodeCacheDeletion(true);
|
||||||
|
await handleOnSave();
|
||||||
|
workflowChangesStore.setShowConfirmCodeCacheDeletion(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
{/* cache key value delete dialog */}
|
{/* cache key value delete dialog */}
|
||||||
<Dialog
|
<Dialog
|
||||||
open={openConfirmCacheKeyValueDeleteDialogue}
|
open={openConfirmCacheKeyValueDeleteDialogue}
|
||||||
|
|||||||
@@ -29,10 +29,14 @@ type WorkflowHasChangesStore = {
|
|||||||
getSaveData: () => SaveData | null;
|
getSaveData: () => SaveData | null;
|
||||||
hasChanges: boolean;
|
hasChanges: boolean;
|
||||||
saveIsPending: boolean;
|
saveIsPending: boolean;
|
||||||
|
saidOkToCodeCacheDeletion: boolean;
|
||||||
|
showConfirmCodeCacheDeletion: boolean;
|
||||||
isInternalUpdate: boolean;
|
isInternalUpdate: boolean;
|
||||||
setGetSaveData: (getSaveData: () => SaveData) => void;
|
setGetSaveData: (getSaveData: () => SaveData) => void;
|
||||||
setHasChanges: (hasChanges: boolean) => void;
|
setHasChanges: (hasChanges: boolean) => void;
|
||||||
setSaveIsPending: (isPending: boolean) => void;
|
setSaveIsPending: (isPending: boolean) => void;
|
||||||
|
setSaidOkToCodeCacheDeletion: (saidOkToCodeCacheDeletion: boolean) => void;
|
||||||
|
setShowConfirmCodeCacheDeletion: (show: boolean) => void;
|
||||||
setIsInternalUpdate: (isInternalUpdate: boolean) => void;
|
setIsInternalUpdate: (isInternalUpdate: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -44,6 +48,8 @@ const useWorkflowHasChangesStore = create<WorkflowHasChangesStore>((set) => {
|
|||||||
return {
|
return {
|
||||||
hasChanges: false,
|
hasChanges: false,
|
||||||
saveIsPending: false,
|
saveIsPending: false,
|
||||||
|
saidOkToCodeCacheDeletion: false,
|
||||||
|
showConfirmCodeCacheDeletion: false,
|
||||||
isInternalUpdate: false,
|
isInternalUpdate: false,
|
||||||
getSaveData: () => null,
|
getSaveData: () => null,
|
||||||
setGetSaveData: (getSaveData: () => SaveData) => {
|
setGetSaveData: (getSaveData: () => SaveData) => {
|
||||||
@@ -55,6 +61,12 @@ const useWorkflowHasChangesStore = create<WorkflowHasChangesStore>((set) => {
|
|||||||
setSaveIsPending: (isPending: boolean) => {
|
setSaveIsPending: (isPending: boolean) => {
|
||||||
set({ saveIsPending: isPending });
|
set({ saveIsPending: isPending });
|
||||||
},
|
},
|
||||||
|
setSaidOkToCodeCacheDeletion: (saidOkToCodeCacheDeletion: boolean) => {
|
||||||
|
set({ saidOkToCodeCacheDeletion });
|
||||||
|
},
|
||||||
|
setShowConfirmCodeCacheDeletion: (show: boolean) => {
|
||||||
|
set({ showConfirmCodeCacheDeletion: show });
|
||||||
|
},
|
||||||
setIsInternalUpdate: (isInternalUpdate: boolean) => {
|
setIsInternalUpdate: (isInternalUpdate: boolean) => {
|
||||||
set({ isInternalUpdate });
|
set({ isInternalUpdate });
|
||||||
},
|
},
|
||||||
@@ -64,8 +76,13 @@ const useWorkflowHasChangesStore = create<WorkflowHasChangesStore>((set) => {
|
|||||||
const useWorkflowSave = (opts?: WorkflowSaveOpts) => {
|
const useWorkflowSave = (opts?: WorkflowSaveOpts) => {
|
||||||
const credentialGetter = useCredentialGetter();
|
const credentialGetter = useCredentialGetter();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const { getSaveData, setHasChanges, setSaveIsPending } =
|
const {
|
||||||
useWorkflowHasChangesStore();
|
getSaveData,
|
||||||
|
saidOkToCodeCacheDeletion,
|
||||||
|
setHasChanges,
|
||||||
|
setSaveIsPending,
|
||||||
|
setShowConfirmCodeCacheDeletion,
|
||||||
|
} = useWorkflowHasChangesStore();
|
||||||
|
|
||||||
const saveWorkflowMutation = useMutation({
|
const saveWorkflowMutation = useMutation({
|
||||||
mutationFn: async () => {
|
mutationFn: async () => {
|
||||||
@@ -149,6 +166,11 @@ const useWorkflowSave = (opts?: WorkflowSaveOpts) => {
|
|||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "text/plain",
|
"Content-Type": "text/plain",
|
||||||
},
|
},
|
||||||
|
params: {
|
||||||
|
delete_code_cache_is_ok: saidOkToCodeCacheDeletion
|
||||||
|
? "true"
|
||||||
|
: "false",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -182,6 +204,14 @@ const useWorkflowSave = (opts?: WorkflowSaveOpts) => {
|
|||||||
onError: (error: AxiosError) => {
|
onError: (error: AxiosError) => {
|
||||||
const detail = (error.response?.data as { detail?: string })?.detail;
|
const detail = (error.response?.data as { detail?: string })?.detail;
|
||||||
|
|
||||||
|
if (
|
||||||
|
detail &&
|
||||||
|
detail.startsWith("No confirmation for code cache deletion")
|
||||||
|
) {
|
||||||
|
setShowConfirmCodeCacheDeletion(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: "Error",
|
title: "Error",
|
||||||
description: detail ? detail : error.message,
|
description: detail ? detail : error.message,
|
||||||
|
|||||||
@@ -837,6 +837,11 @@ class BrowserProfileNotFound(SkyvernHTTPException):
|
|||||||
super().__init__(message, status_code=status.HTTP_404_NOT_FOUND)
|
super().__init__(message, status_code=status.HTTP_404_NOT_FOUND)
|
||||||
|
|
||||||
|
|
||||||
|
class CannotUpdateWorkflowDueToCodeCache(SkyvernException):
|
||||||
|
def __init__(self, workflow_permanent_id: str) -> None:
|
||||||
|
super().__init__(f"No confirmation for code cache deletion on {workflow_permanent_id}.")
|
||||||
|
|
||||||
|
|
||||||
class APIKeyNotFound(SkyvernHTTPException):
|
class APIKeyNotFound(SkyvernHTTPException):
|
||||||
def __init__(self, organization_id: str) -> None:
|
def __init__(self, organization_id: str) -> None:
|
||||||
super().__init__(f"No valid API key token found for organization {organization_id}")
|
super().__init__(f"No valid API key token found for organization {organization_id}")
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ from skyvern import analytics
|
|||||||
from skyvern._version import __version__
|
from skyvern._version import __version__
|
||||||
from skyvern.config import settings
|
from skyvern.config import settings
|
||||||
from skyvern.exceptions import (
|
from skyvern.exceptions import (
|
||||||
|
CannotUpdateWorkflowDueToCodeCache,
|
||||||
MissingBrowserAddressError,
|
MissingBrowserAddressError,
|
||||||
SkyvernHTTPException,
|
SkyvernHTTPException,
|
||||||
)
|
)
|
||||||
@@ -910,6 +911,7 @@ async def update_workflow_legacy(
|
|||||||
..., description="The ID of the workflow to update. Workflow ID starts with `wpid_`.", examples=["wpid_123"]
|
..., description="The ID of the workflow to update. Workflow ID starts with `wpid_`.", examples=["wpid_123"]
|
||||||
),
|
),
|
||||||
current_org: Organization = Depends(org_auth_service.get_current_org),
|
current_org: Organization = Depends(org_auth_service.get_current_org),
|
||||||
|
delete_code_cache_is_ok: bool = Query(False),
|
||||||
) -> Workflow:
|
) -> Workflow:
|
||||||
analytics.capture("skyvern-oss-agent-workflow-update")
|
analytics.capture("skyvern-oss-agent-workflow-update")
|
||||||
# validate the workflow
|
# validate the workflow
|
||||||
@@ -925,7 +927,13 @@ async def update_workflow_legacy(
|
|||||||
organization=current_org,
|
organization=current_org,
|
||||||
request=workflow_create_request,
|
request=workflow_create_request,
|
||||||
workflow_permanent_id=workflow_id,
|
workflow_permanent_id=workflow_id,
|
||||||
|
delete_code_cache_is_ok=delete_code_cache_is_ok,
|
||||||
)
|
)
|
||||||
|
except CannotUpdateWorkflowDueToCodeCache as e:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=422,
|
||||||
|
detail=str(e),
|
||||||
|
) from e
|
||||||
except WorkflowDefinitionValidationException as e:
|
except WorkflowDefinitionValidationException as e:
|
||||||
raise e
|
raise e
|
||||||
except (SkyvernHTTPException, ValidationError) as e:
|
except (SkyvernHTTPException, ValidationError) as e:
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ from skyvern.exceptions import (
|
|||||||
BlockNotFound,
|
BlockNotFound,
|
||||||
BrowserProfileNotFound,
|
BrowserProfileNotFound,
|
||||||
BrowserSessionNotFound,
|
BrowserSessionNotFound,
|
||||||
|
CannotUpdateWorkflowDueToCodeCache,
|
||||||
FailedToSendWebhook,
|
FailedToSendWebhook,
|
||||||
InvalidCredentialId,
|
InvalidCredentialId,
|
||||||
MissingValueForParameter,
|
MissingValueForParameter,
|
||||||
@@ -1957,6 +1958,7 @@ class WorkflowService:
|
|||||||
workflow_definition: WorkflowDefinition,
|
workflow_definition: WorkflowDefinition,
|
||||||
organization_id: str,
|
organization_id: str,
|
||||||
delete_script: bool = True,
|
delete_script: bool = True,
|
||||||
|
delete_code_cache_is_ok: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
if workflow_definition:
|
if workflow_definition:
|
||||||
workflow_definition.validate()
|
workflow_definition.validate()
|
||||||
@@ -2032,6 +2034,27 @@ class WorkflowService:
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if published_groups and not delete_code_cache_is_ok:
|
||||||
|
LOG.info(
|
||||||
|
"Workflow definition changed, asking user if clearing published cached blocks is ok",
|
||||||
|
workflow_id=workflow.workflow_id,
|
||||||
|
workflow_permanent_id=previous_valid_workflow.workflow_permanent_id,
|
||||||
|
organization_id=organization_id,
|
||||||
|
previous_version=previous_valid_workflow.version,
|
||||||
|
new_version=workflow.version,
|
||||||
|
invalidate_reason=plan.reason,
|
||||||
|
invalidate_label=plan.label,
|
||||||
|
invalidate_index_prev=plan.previous_index,
|
||||||
|
invalidate_index_new=plan.new_index,
|
||||||
|
block_labels_to_disable=plan.block_labels_to_disable,
|
||||||
|
to_clear_published_cnt=len(published_groups),
|
||||||
|
to_clear_non_published_cnt=len(cached_groups),
|
||||||
|
)
|
||||||
|
|
||||||
|
raise CannotUpdateWorkflowDueToCodeCache(
|
||||||
|
workflow_permanent_id=previous_valid_workflow.workflow_permanent_id,
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
groups_to_clear = [*cached_groups, *published_groups]
|
groups_to_clear = [*cached_groups, *published_groups]
|
||||||
await self._clear_cached_block_groups(
|
await self._clear_cached_block_groups(
|
||||||
@@ -2073,7 +2096,38 @@ class WorkflowService:
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
to_delete = candidates
|
to_delete_published = [script for script in candidates if script.status == ScriptStatus.published]
|
||||||
|
to_delete = [script for script in candidates if script.status != ScriptStatus.published]
|
||||||
|
|
||||||
|
if len(to_delete_published) > 0:
|
||||||
|
if not delete_code_cache_is_ok:
|
||||||
|
LOG.info(
|
||||||
|
"Workflow definition changed, asking user if deleting published code is ok",
|
||||||
|
workflow_id=workflow.workflow_id,
|
||||||
|
workflow_permanent_id=previous_valid_workflow.workflow_permanent_id,
|
||||||
|
organization_id=organization_id,
|
||||||
|
previous_version=previous_valid_workflow.version,
|
||||||
|
new_version=workflow.version,
|
||||||
|
to_delete_non_published_cnt=len(to_delete),
|
||||||
|
to_delete_published_cnt=len(to_delete_published),
|
||||||
|
)
|
||||||
|
|
||||||
|
raise CannotUpdateWorkflowDueToCodeCache(
|
||||||
|
workflow_permanent_id=previous_valid_workflow.workflow_permanent_id,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
LOG.info(
|
||||||
|
"Workflow definition changed, user answered yes to deleting published code",
|
||||||
|
workflow_id=workflow.workflow_id,
|
||||||
|
workflow_permanent_id=previous_valid_workflow.workflow_permanent_id,
|
||||||
|
organization_id=organization_id,
|
||||||
|
previous_version=previous_valid_workflow.version,
|
||||||
|
new_version=workflow.version,
|
||||||
|
to_delete_non_published_cnt=len(to_delete),
|
||||||
|
to_delete_published_cnt=len(to_delete_published),
|
||||||
|
)
|
||||||
|
|
||||||
|
to_delete.extend(to_delete_published)
|
||||||
|
|
||||||
if len(to_delete) > 0:
|
if len(to_delete) > 0:
|
||||||
try:
|
try:
|
||||||
@@ -3094,6 +3148,7 @@ class WorkflowService:
|
|||||||
request: WorkflowCreateYAMLRequest,
|
request: WorkflowCreateYAMLRequest,
|
||||||
workflow_permanent_id: str | None = None,
|
workflow_permanent_id: str | None = None,
|
||||||
delete_script: bool = True,
|
delete_script: bool = True,
|
||||||
|
delete_code_cache_is_ok: bool = True,
|
||||||
) -> Workflow:
|
) -> Workflow:
|
||||||
organization_id = organization.organization_id
|
organization_id = organization.organization_id
|
||||||
LOG.info(
|
LOG.info(
|
||||||
@@ -3187,6 +3242,7 @@ class WorkflowService:
|
|||||||
workflow_definition=workflow_definition,
|
workflow_definition=workflow_definition,
|
||||||
organization_id=organization_id,
|
organization_id=organization_id,
|
||||||
delete_script=delete_script,
|
delete_script=delete_script,
|
||||||
|
delete_code_cache_is_ok=delete_code_cache_is_ok,
|
||||||
)
|
)
|
||||||
|
|
||||||
return updated_workflow
|
return updated_workflow
|
||||||
|
|||||||
Reference in New Issue
Block a user