From f6bbada2849c80e39bb8b92557a8b10df82e22e4 Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Wed, 31 Dec 2025 21:04:15 +0100 Subject: [PATCH] Replace workflow_step_id_path with workflow_step_index_path --- client/src/api/schema/schema.ts | 48 +++++++++---------- .../InvocationMessage.vue | 18 +++---- .../WorkflowInvocationError.vue | 6 +-- .../useInvocationMessageStepData.ts | 2 +- lib/galaxy/model/__init__.py | 8 ++-- .../312602e3191d_add_workflow_step_id_path.py | 4 +- lib/galaxy/schema/invocation.py | 2 +- lib/galaxy/workflow/run.py | 4 +- lib/galaxy_test/api/test_workflows.py | 14 +++--- 9 files changed, 54 insertions(+), 52 deletions(-) diff --git a/client/src/api/schema/schema.ts b/client/src/api/schema/schema.ts index c29f7facea9..350644c440e 100644 --- a/client/src/api/schema/schema.ts +++ b/client/src/api/schema/schema.ts @@ -15652,10 +15652,10 @@ export interface components { */ reason: "history_deleted"; /** - * Workflow Step Id Path + * Workflow Step Index Path * @description Path of workflow step IDs from parent workflow through subworkflows (excludes the failing step itself). */ - workflow_step_id_path?: number[] | null; + workflow_step_index_path?: number[] | null; }; /** InvocationCancellationReviewFailedResponse */ InvocationCancellationReviewFailedResponse: { @@ -15670,10 +15670,10 @@ export interface components { */ workflow_step_id: number; /** - * Workflow Step Id Path + * Workflow Step Index Path * @description Path of workflow step IDs from parent workflow through subworkflows (excludes the failing step itself). */ - workflow_step_id_path?: number[] | null; + workflow_step_index_path?: number[] | null; }; /** InvocationCancellationUserRequestResponse */ InvocationCancellationUserRequestResponse: { @@ -15683,10 +15683,10 @@ export interface components { */ reason: "user_request"; /** - * Workflow Step Id Path + * Workflow Step Index Path * @description Path of workflow step IDs from parent workflow through subworkflows (excludes the failing step itself). */ - workflow_step_id_path?: number[] | null; + workflow_step_index_path?: number[] | null; }; /** InvocationEvaluationWarningWorkflowOutputNotFoundResponse */ InvocationEvaluationWarningWorkflowOutputNotFoundResponse: { @@ -15703,10 +15703,10 @@ export interface components { /** Workflow step id of step that caused a warning. */ workflow_step_id: number; /** - * Workflow Step Id Path + * Workflow Step Index Path * @description Path of workflow step IDs from parent workflow through subworkflows (excludes the failing step itself). */ - workflow_step_id_path?: number[] | null; + workflow_step_index_path?: number[] | null; }; /** InvocationFailureCollectionFailedResponse */ InvocationFailureCollectionFailedResponse: { @@ -15732,10 +15732,10 @@ export interface components { */ workflow_step_id: number; /** - * Workflow Step Id Path + * Workflow Step Index Path * @description Path of workflow step IDs from parent workflow through subworkflows (excludes the failing step itself). */ - workflow_step_id_path?: number[] | null; + workflow_step_index_path?: number[] | null; }; /** InvocationFailureDatasetFailedResponse */ InvocationFailureDatasetFailedResponse: { @@ -15761,10 +15761,10 @@ export interface components { */ workflow_step_id: number; /** - * Workflow Step Id Path + * Workflow Step Index Path * @description Path of workflow step IDs from parent workflow through subworkflows (excludes the failing step itself). */ - workflow_step_id_path?: number[] | null; + workflow_step_index_path?: number[] | null; }; /** InvocationFailureExpressionEvaluationFailedResponse */ InvocationFailureExpressionEvaluationFailedResponse: { @@ -15784,10 +15784,10 @@ export interface components { */ workflow_step_id: number; /** - * Workflow Step Id Path + * Workflow Step Index Path * @description Path of workflow step IDs from parent workflow through subworkflows (excludes the failing step itself). */ - workflow_step_id_path?: number[] | null; + workflow_step_index_path?: number[] | null; }; /** InvocationFailureJobFailedResponse */ InvocationFailureJobFailedResponse: { @@ -15813,10 +15813,10 @@ export interface components { */ workflow_step_id: number; /** - * Workflow Step Id Path + * Workflow Step Index Path * @description Path of workflow step IDs from parent workflow through subworkflows (excludes the failing step itself). */ - workflow_step_id_path?: number[] | null; + workflow_step_index_path?: number[] | null; }; /** InvocationFailureOutputNotFoundResponse */ InvocationFailureOutputNotFoundResponse: { @@ -15838,10 +15838,10 @@ export interface components { */ workflow_step_id: number; /** - * Workflow Step Id Path + * Workflow Step Index Path * @description Path of workflow step IDs from parent workflow through subworkflows (excludes the failing step itself). */ - workflow_step_id_path?: number[] | null; + workflow_step_index_path?: number[] | null; }; /** InvocationFailureWhenNotBooleanResponse */ InvocationFailureWhenNotBooleanResponse: { @@ -15861,10 +15861,10 @@ export interface components { */ workflow_step_id: number; /** - * Workflow Step Id Path + * Workflow Step Index Path * @description Path of workflow step IDs from parent workflow through subworkflows (excludes the failing step itself). */ - workflow_step_id_path?: number[] | null; + workflow_step_index_path?: number[] | null; }; /** InvocationFailureWorkflowParameterInvalidResponse */ InvocationFailureWorkflowParameterInvalidResponse: { @@ -15881,10 +15881,10 @@ export interface components { /** Workflow parameter step that failed validation */ workflow_step_id: number; /** - * Workflow Step Id Path + * Workflow Step Index Path * @description Path of workflow step IDs from parent workflow through subworkflows (excludes the failing step itself). */ - workflow_step_id_path?: number[] | null; + workflow_step_index_path?: number[] | null; }; /** InvocationInput */ InvocationInput: { @@ -16364,10 +16364,10 @@ export interface components { */ workflow_step_id?: number | null; /** - * Workflow Step Id Path + * Workflow Step Index Path * @description Path of workflow step IDs from parent workflow through subworkflows (excludes the failing step itself). */ - workflow_step_id_path?: number[] | null; + workflow_step_index_path?: number[] | null; }; /** InvocationUpdatePayload */ InvocationUpdatePayload: { diff --git a/client/src/components/WorkflowInvocationState/InvocationMessage.vue b/client/src/components/WorkflowInvocationState/InvocationMessage.vue index d74ccc77746..904aeb8fe47 100644 --- a/client/src/components/WorkflowInvocationState/InvocationMessage.vue +++ b/client/src/components/WorkflowInvocationState/InvocationMessage.vue @@ -31,10 +31,10 @@ const emit = defineEmits<{ const invocationId = computed(() => props.invocation?.id || ""); const pathStepOrderIndices = computed(() => { if ( - "workflow_step_id_path" in props.invocationMessage && - Array.isArray(props.invocationMessage.workflow_step_id_path) + "workflow_step_index_path" in props.invocationMessage && + Array.isArray(props.invocationMessage.workflow_step_index_path) ) { - return props.invocationMessage.workflow_step_id_path as number[]; + return props.invocationMessage.workflow_step_index_path as number[]; } return []; }); @@ -73,16 +73,18 @@ const stepPathInfo = computed(() => { function buildStepPath(message: InvocationMessage): string { if ( - "workflow_step_id_path" in message && + "workflow_step_index_path" in message && "workflow_step_id" in message && - message.workflow_step_id_path && - Array.isArray(message.workflow_step_id_path) && - message.workflow_step_id_path.length > 0 && + message.workflow_step_index_path && + Array.isArray(message.workflow_step_index_path) && + message.workflow_step_index_path.length > 0 && message.workflow_step_id !== null && message.workflow_step_id !== undefined ) { // Build path like "Step 2 → Step 5 → Step 9" - const pathSteps = (message.workflow_step_id_path as number[]).map((id: number) => `Step ${id + 1}`).join(" → "); + const pathSteps = (message.workflow_step_index_path as number[]) + .map((id: number) => `Step ${id + 1}`) + .join(" → "); return `${pathSteps} → Step ${message.workflow_step_id + 1}`; } if ("workflow_step_id" in message && message.workflow_step_id !== null && message.workflow_step_id !== undefined) { diff --git a/client/src/components/WorkflowInvocationState/WorkflowInvocationError.vue b/client/src/components/WorkflowInvocationState/WorkflowInvocationError.vue index c9304eed924..5d364932cf9 100644 --- a/client/src/components/WorkflowInvocationState/WorkflowInvocationError.vue +++ b/client/src/components/WorkflowInvocationState/WorkflowInvocationError.vue @@ -34,10 +34,10 @@ const { stepData } = useInvocationMessageStepData( computed(() => props.invocation?.id || ""), computed(() => { if ( - "workflow_step_id_path" in props.invocationMessage && - Array.isArray(props.invocationMessage.workflow_step_id_path) + "workflow_step_index_path" in props.invocationMessage && + Array.isArray(props.invocationMessage.workflow_step_index_path) ) { - return props.invocationMessage.workflow_step_id_path as number[]; + return props.invocationMessage.workflow_step_index_path as number[]; } return []; }), diff --git a/client/src/composables/useInvocationMessageStepData.ts b/client/src/composables/useInvocationMessageStepData.ts index a34a402c192..b613c7332e6 100644 --- a/client/src/composables/useInvocationMessageStepData.ts +++ b/client/src/composables/useInvocationMessageStepData.ts @@ -57,7 +57,7 @@ function generateStepLabel(orderIndex: number, workflowStep: WorkflowStep): stri * the necessary invocation and workflow data to properly display step information in error messages. * * @param invocationId - The workflow invocation ID - * @param pathStepOrderIndices - Array of step order indices from workflow_step_id_path + * @param pathStepOrderIndices - Array of step order indices from workflow_step_index_path * @param finalStepOrderIndex - The failing step order index from workflow_step_id * @returns Object containing stepData array, loading state, and error message */ diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py index acc7bc7d320..9018fdb2a74 100644 --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -9891,9 +9891,9 @@ class WorkflowInvocation(Base, UsesCreateAndUpdateTime, Dictifiable, Serializabl exclude_unset=True, exclude={"history_id"}, # history_id comes in through workflow_invocation and isn't persisted in database ) - # Convert workflow_step_id_path list to JSON string for database storage - if "workflow_step_id_path" in message_dict and message_dict["workflow_step_id_path"] is not None: - message_dict["workflow_step_id_path"] = message_dict["workflow_step_id_path"] + # Convert workflow_step_index_path list to JSON string for database storage + if "workflow_step_index_path" in message_dict and message_dict["workflow_step_index_path"] is not None: + message_dict["workflow_step_index_path"] = message_dict["workflow_step_index_path"] self.messages.append( WorkflowInvocationMessage( # type:ignore[abstract] workflow_invocation_id=self.id, @@ -9977,7 +9977,7 @@ class WorkflowInvocationMessage(Base, Dictifiable, Serializable): job_id: Mapped[Optional[int]] = mapped_column(ForeignKey("job.id")) hda_id: Mapped[Optional[int]] = mapped_column(ForeignKey("history_dataset_association.id")) hdca_id: Mapped[Optional[int]] = mapped_column(ForeignKey("history_dataset_collection_association.id")) - workflow_step_id_path: Mapped[Optional[list[int]]] = mapped_column(JSON) + workflow_step_index_path: Mapped[Optional[list[int]]] = mapped_column(JSON) workflow_invocation: Mapped["WorkflowInvocation"] = relationship(back_populates="messages", lazy=True) workflow_step: Mapped[Optional["WorkflowStep"]] = relationship(foreign_keys=workflow_step_id, lazy=True) diff --git a/lib/galaxy/model/migrations/alembic/versions_gxy/312602e3191d_add_workflow_step_id_path.py b/lib/galaxy/model/migrations/alembic/versions_gxy/312602e3191d_add_workflow_step_id_path.py index f6e7bfb2585..e3413ebf989 100644 --- a/lib/galaxy/model/migrations/alembic/versions_gxy/312602e3191d_add_workflow_step_id_path.py +++ b/lib/galaxy/model/migrations/alembic/versions_gxy/312602e3191d_add_workflow_step_id_path.py @@ -1,4 +1,4 @@ -"""Add workflow_step_id_path column to workflow_invocation_message table +"""Add workflow_step_index_path column to workflow_invocation_message table Revision ID: 312602e3191d Revises: 75b461a2b24a @@ -20,7 +20,7 @@ depends_on = None # database object names used in this revision table_name = "workflow_invocation_message" -column_name = "workflow_step_id_path" +column_name = "workflow_step_index_path" def upgrade(): diff --git a/lib/galaxy/schema/invocation.py b/lib/galaxy/schema/invocation.py index 26525ee3c60..e474e75088b 100644 --- a/lib/galaxy/schema/invocation.py +++ b/lib/galaxy/schema/invocation.py @@ -117,7 +117,7 @@ class CancelReason(str, Enum): class InvocationMessageBase(GenericModel): reason: Union[CancelReason, FailureReason, WarningReason] - workflow_step_id_path: Optional[List[int]] = Field( + workflow_step_index_path: Optional[List[int]] = Field( None, description="Path of workflow step IDs from parent workflow through subworkflows (excludes the failing step itself).", ) diff --git a/lib/galaxy/workflow/run.py b/lib/galaxy/workflow/run.py index 98568787b52..ff65ad439c2 100644 --- a/lib/galaxy/workflow/run.py +++ b/lib/galaxy/workflow/run.py @@ -289,9 +289,9 @@ class WorkflowInvoker: # If this step is a subworkflow, prepend its ID to the path if step.type == "subworkflow": error_dict = e.why.model_dump() - current_path = error_dict.get("workflow_step_id_path") or [] + current_path = error_dict.get("workflow_step_index_path") or [] current_path.append(step.order_index) - error_dict["workflow_step_id_path"] = current_path + error_dict["workflow_step_index_path"] = current_path error_class = type(e.why) e.why = error_class(**error_dict) if isinstance(e, MessageException): diff --git a/lib/galaxy_test/api/test_workflows.py b/lib/galaxy_test/api/test_workflows.py index bb9a338107a..f23371b1a99 100644 --- a/lib/galaxy_test/api/test_workflows.py +++ b/lib/galaxy_test/api/test_workflows.py @@ -3982,7 +3982,7 @@ steps: "details": "Subworkflow has disconnected required input.", "reason": "unexpected_failure", "workflow_step_id": 0, - "workflow_step_id_path": [0], + "workflow_step_index_path": [0], } ] @@ -4079,13 +4079,13 @@ some_file: assert message["reason"] == "when_not_boolean" assert message["details"] == "Type is: str" # workflow_step_id should be the conditional_step in the subworkflow - # workflow_step_id_path should contain the subworkflow_step from the parent workflow - assert "workflow_step_id_path" in message - assert message["workflow_step_id_path"] is not None - assert len(message["workflow_step_id_path"]) == 1 + # workflow_step_index_path should contain the subworkflow_step from the parent workflow + assert "workflow_step_index_path" in message + assert message["workflow_step_index_path"] is not None + assert len(message["workflow_step_index_path"]) == 1 # Verify the path contains the step ID (order_index, not the database id) - assert isinstance(message["workflow_step_id_path"][0], int) - assert message["workflow_step_id_path"][0] > 0 + assert isinstance(message["workflow_step_index_path"][0], int) + assert message["workflow_step_index_path"][0] > 0 def test_workflow_request(self): workflow = self.workflow_populator.load_workflow(name="test_for_queue")