diff --git a/lib/galaxy/dependencies/pinned-requirements.txt b/lib/galaxy/dependencies/pinned-requirements.txt index d092e211938..253065586f2 100644 --- a/lib/galaxy/dependencies/pinned-requirements.txt +++ b/lib/galaxy/dependencies/pinned-requirements.txt @@ -82,7 +82,7 @@ greenlet==3.2.4 ; (python_full_version < '3.14' and platform_machine == 'AMD64') grpcio==1.74.0 grpcio-status==1.74.0 gunicorn==23.0.0 -gxformat2==0.20.0 +gxformat2==0.21.0 h11==0.16.0 h5grove==2.3.0 h5py==3.14.0 diff --git a/lib/galaxy/workflow/modules.py b/lib/galaxy/workflow/modules.py index 910ba25d516..129845102b2 100644 --- a/lib/galaxy/workflow/modules.py +++ b/lib/galaxy/workflow/modules.py @@ -41,6 +41,7 @@ from galaxy.model.base import ensure_object_added_to_session from galaxy.model.dataset_collections import matching from galaxy.model.dataset_collections.query import HistoryQuery from galaxy.model.dataset_collections.type_description import COLLECTION_TYPE_DESCRIPTION_FACTORY +from galaxy.model.dataset_collections.types.sample_sheet_util import validate_column_definitions from galaxy.schema.invocation import ( CancelReason, FailureReason, @@ -1166,6 +1167,9 @@ class InputDataCollectionModule(InputModule): fields=fields, ) collection_type_description.validate() + column_definitions = state.get("column_definitions") + if column_definitions: + validate_column_definitions(column_definitions) return None def get_runtime_inputs(self, step, connections: Optional[Iterable[WorkflowStepConnection]] = None): diff --git a/lib/galaxy_test/api/test_workflows.py b/lib/galaxy_test/api/test_workflows.py index f09afb51e5e..0c968864cb7 100644 --- a/lib/galaxy_test/api/test_workflows.py +++ b/lib/galaxy_test/api/test_workflows.py @@ -7836,6 +7836,72 @@ steps: assert r.status_code == 400 assert "Invalid collection type:" in r.json()["err_msg"] + @skip_without_tool("multi_data_optional") + def test_invalid_sample_sheet_definitions_rejected(self): + valid_collection_type = """ +class: GalaxyWorkflow +inputs: + input: + type: collection + collection_type: sample_sheet + column_definitions: + - type: string + name: condition + default_value: treatment + optional: false + restrictions: ["treatment", "control"] +steps: + multi_data_optional: + tool_id: multi_data_optional + in: + input1: input +""" + r = self._post("workflows", files={"archive_file": io.StringIO(valid_collection_type)}) + assert r.status_code == 200 + + invalid_collection_type = """ +class: GalaxyWorkflow +inputs: + input: + type: collection + collection_type: sample_sheet + column_definitions: + - type: stringx + name: condition + default_value: treatment + optional: false + restrictions: ["treatment", "control"] +steps: + multi_data_optional: + tool_id: multi_data_optional + in: + input1: input +""" + r = self._post("workflows", files={"archive_file": io.StringIO(invalid_collection_type)}) + assert r.status_code == 400 + + invalid_collection_type = """ +class: GalaxyWorkflow +inputs: + input: + type: collection + collection_type: sample_sheet + column_definitions: + - type: string + name: condition + default_value: treatment + optional: false + restrictions: ["treatment", "control"] + extra_key: not_allowed +steps: + multi_data_optional: + tool_id: multi_data_optional + in: + input1: input +""" + r = self._post("workflows", files={"archive_file": io.StringIO(invalid_collection_type)}) + assert r.status_code == 400 + @skip_without_tool("random_lines1") def test_run_replace_params_over_default_delayed(self): with self.dataset_populator.test_history() as history_id: diff --git a/pyproject.toml b/pyproject.toml index b1d5f3fd27c..00da8edf6b0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ dependencies = [ "future>=1.0.0", # Python 3.12 support "gravity>=1.1.1", "gunicorn", - "gxformat2", + "gxformat2>=0.21.0", "h5grove>=1.2.1", "h5py>=3.12", # Python 3.13 support "httpx",