diff --git a/dvc/schema.py b/dvc/schema.py index 451399b26..48baa6123 100644 --- a/dvc/schema.py +++ b/dvc/schema.py @@ -79,7 +79,7 @@ PARAM_PSTAGE_NON_DEFAULT_SCHEMA = {str: [str]} VARS_SCHEMA = [str, dict] STAGE_DEFINITION = { - StageParams.PARAM_CMD: Any(str, list), + Required(StageParams.PARAM_CMD): Any(str, list), Optional(StageParams.PARAM_WDIR): str, Optional(StageParams.PARAM_DEPS): [str], Optional(StageParams.PARAM_PARAMS): [Any(str, dict)], @@ -100,7 +100,7 @@ FOREACH_IN = { Required(FOREACH_KWD): Any(dict, list, str), Required(DO_KWD): STAGE_DEFINITION, } -SINGLE_PIPELINE_STAGE_SCHEMA = {str: Any(STAGE_DEFINITION, FOREACH_IN)} +SINGLE_PIPELINE_STAGE_SCHEMA = {str: Any(FOREACH_IN, STAGE_DEFINITION)} MULTI_STAGE_SCHEMA = { STAGES: SINGLE_PIPELINE_STAGE_SCHEMA, VARS_KWD: VARS_SCHEMA, diff --git a/dvc/stage/serialize.py b/dvc/stage/serialize.py index a165f3c69..f726cc8a8 100644 --- a/dvc/stage/serialize.py +++ b/dvc/stage/serialize.py @@ -129,6 +129,12 @@ def to_pipeline_file(stage: "PipelineStage"): params = _serialize_params_keys(params) outs, metrics, plots, live = _serialize_outs(stage.outs) + + cmd = stage.cmd + assert cmd, ( + f"'{stage.PARAM_CMD}' cannot be empty for stage '{stage.name}', " + f"got: '{cmd}'(type: '{type(cmd).__name__}')" + ) res = [ (stage.PARAM_DESC, stage.desc), (stage.PARAM_CMD, stage.cmd), diff --git a/tests/conftest.py b/tests/conftest.py index 68b7d9ba4..f165646f6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -145,8 +145,9 @@ def dummy_stage(tmp_dir, dvc): def make(path="dvc.yaml", name="dummy_stage", **kwargs): from dvc.stage import PipelineStage, create_stage + cmd = kwargs.get("cmd", "command") stage = create_stage( - PipelineStage, dvc, path, name=name, cmd="", **kwargs + PipelineStage, dvc, path, name=name, cmd=cmd, **kwargs ) stage.dump() return stage diff --git a/tests/unit/command/test_status.py b/tests/unit/command/test_status.py index f2e1c5746..575bf3b21 100644 --- a/tests/unit/command/test_status.py +++ b/tests/unit/command/test_status.py @@ -6,7 +6,7 @@ from dvc.cli import parse_args from dvc.command.status import CmdDataStatus -def test_cloud_status(mocker): +def test_cloud_status(tmp_dir, dvc, mocker): cli_args = parse_args( [ "status",