Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/specify_cli/bundler/services/primitives.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,16 @@ def install(self, component: ComponentRef) -> None:
with _chdir(self._root):
_delegate_command(
"install", f"workflow '{component.id}'",
lambda: workflow_add(component.id),
# Pass the options explicitly. Called in-process rather than
# through Typer, an omitted ``typer.Option`` parameter keeps its
# ``OptionInfo`` sentinel as the value -- which is TRUTHY and is
# not ``None`` -- so ``workflow_add``'s ``if dev:`` took the
# local-path branch for every catalog install and failed with
# "--dev source must be a workflow YAML file ...". It is the only
# one of the four delegated commands that declares options;
# workflow_remove / workflow_step_add / workflow_step_remove take
# a bare ``typer.Argument`` and are safe as written.
lambda: workflow_add(component.id, dev=False, from_url=None),
)

def refresh(self, component: ComponentRef) -> None:
Expand Down
38 changes: 37 additions & 1 deletion tests/unit/test_bundler_primitives.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,50 @@ def test_offline_workflow_allows_bundled(tmp_path: Path, monkeypatch):
assets, "_locate_bundled_workflow", lambda wid: tmp_path / "wf"
)
calls: list[str] = []
monkeypatch.setattr(specify_cli, "workflow_add", lambda wid: calls.append(wid))
monkeypatch.setattr(
specify_cli, "workflow_add", lambda wid, **kwargs: calls.append(wid)
)

manager = primitive_manager("workflows", tmp_path, allow_network=False)
manager.install(_component("workflows", "bundled-wf"))

assert calls == ["bundled-wf"]


def test_workflow_install_passes_explicit_typer_options(tmp_path: Path, monkeypatch):
"""The bundler calls ``workflow_add`` in-process, so it must pass the
``typer.Option`` values explicitly.

Outside Typer, an omitted option parameter keeps its ``OptionInfo``
sentinel as the value. That sentinel is truthy and is not ``None``, so
``workflow_add``'s ``if dev:`` took the local-path branch for *every*
catalog install and failed with "--dev source must be a workflow YAML
file, supported archive, or directory containing workflow.yml".
"""
import specify_cli
import specify_cli._assets as assets

monkeypatch.setattr(
assets, "_locate_bundled_workflow", lambda wid: tmp_path / "wf"
)
seen: list[dict] = []

def _capture(wid, *args, **kwargs):
seen.append({"id": wid, "args": args, "kwargs": kwargs})

monkeypatch.setattr(specify_cli, "workflow_add", _capture)

manager = primitive_manager("workflows", tmp_path, allow_network=False)
manager.install(_component("workflows", "bundled-wf"))

assert len(seen) == 1, seen
call = seen[0]
assert call["id"] == "bundled-wf"
# Both options must arrive as real values, never as Typer sentinels.
assert call["kwargs"].get("dev") is False, call["kwargs"]
assert call["kwargs"].get("from_url") is None, call["kwargs"]


def test_assert_pinned_version_matches_passes():
from specify_cli.bundler.services.primitives import _assert_pinned_version

Expand Down