diff --git a/src/specify_cli/workflows/_commands.py b/src/specify_cli/workflows/_commands.py index 716b6c8a19..a82af12a70 100644 --- a/src/specify_cli/workflows/_commands.py +++ b/src/specify_cli/workflows/_commands.py @@ -1733,9 +1733,11 @@ def workflow_add( from_url: str | None = typer.Option(None, "--from", help="Install from a custom URL"), ): """Install a workflow from catalog, URL, or local path.""" + from . import load_custom_steps from .engine import WorkflowDefinition project_root = _require_specify_project() + load_custom_steps(project_root) _open_workflow_registry(project_root) workflows_dir = project_root / ".specify" / "workflows" # With --from, source names the expected workflow ID: validate it up diff --git a/tests/test_workflows.py b/tests/test_workflows.py index 9b1c17881e..b0c20776c3 100644 --- a/tests/test_workflows.py +++ b/tests/test_workflows.py @@ -10079,6 +10079,68 @@ def test_lowercase_extension_still_installs(self, temp_dir, monkeypatch, sample_ assert result.exit_code == 0, result.output assert "installed" in result.output + def test_add_installs_workflow_with_custom_step(self, temp_dir, monkeypatch): + from typer.testing import CliRunner + from specify_cli import app + + (temp_dir / ".specify" / "workflows").mkdir(parents=True) + step_dir = temp_dir / ".specify" / "workflows" / "steps" / "test-add-step" + step_dir.mkdir(parents=True) + step_manifest = { + "schema_version": "1.0", + "step": { + "type_key": "test-add-step", + "name": "Test Add Step", + "version": "1.0.0", + }, + } + (step_dir / "step.yml").write_text( + yaml.safe_dump(step_manifest, sort_keys=False), + encoding="utf-8", + ) + (step_dir / "__init__.py").write_text( + """ +from specify_cli.workflows.base import StepBase, StepResult + + +class TestAddStep(StepBase): + type_key = "test-add-step" + + def execute(self, config, context): + return StepResult() +""", + encoding="utf-8", + ) + + src = temp_dir / "sample.yml" + workflow_definition = { + "schema_version": "1.0", + "workflow": { + "id": "test-workflow-with-custom-step", + "name": "Test Workflow With Custom Step", + "version": "1.0.0", + }, + "steps": [ + {"id": "custom-step", "type": "test-add-step"}, + ], + } + src.write_text( + yaml.safe_dump(workflow_definition, sort_keys=False), + encoding="utf-8", + ) + monkeypatch.chdir(temp_dir) + result = CliRunner().invoke(app, ["workflow", "add", str(src)]) + + assert result.exit_code == 0, result.output + installed_workflow = ( + temp_dir + / ".specify" + / "workflows" + / "test-workflow-with-custom-step" + / "workflow.yml" + ) + assert installed_workflow.is_file() + class TestWorkflowInfoStepGraph: """`workflow info` must render each step as `→ []` with LITERAL