fix(cli): skip json crew sync when locked

This commit is contained in:
Joao Moura
2026-06-15 10:32:45 -07:00
parent ce74cdf02c
commit b8c89a81f6
2 changed files with 41 additions and 11 deletions

View File

@@ -256,9 +256,16 @@ def _run_json_crew(trained_agents_file: str | None = None) -> Any:
return app._crew_result
def _install_json_crew_dependencies() -> None:
"""Lock and sync JSON crew projects before loading them in-process."""
if not (Path.cwd() / "pyproject.toml").is_file():
def _has_lockfile(project_root: Path | None = None) -> bool:
"""Return True when the project already has a dependency lockfile."""
root = project_root or Path.cwd()
return (root / "uv.lock").is_file() or (root / "poetry.lock").is_file()
def _install_json_crew_dependencies_if_needed() -> None:
"""Lock and sync JSON crew projects only when no lockfile exists."""
project_root = Path.cwd()
if not (project_root / "pyproject.toml").is_file() or _has_lockfile(project_root):
return
from crewai_cli.install_crew import install_crew
@@ -286,7 +293,7 @@ def _run_json_crew_in_project_env(trained_agents_file: str | None = None) -> Any
if not (Path.cwd() / "pyproject.toml").is_file():
return _run_json_crew(trained_agents_file=trained_agents_file)
_install_json_crew_dependencies()
_install_json_crew_dependencies_if_needed()
command = ["uv", "run", "--no-sync", "python", "-c", _JSON_CREW_RUNNER_CODE]
env = build_env_with_all_tool_credentials()

View File

@@ -39,7 +39,7 @@ def test_json_run_uses_project_env_when_pyproject_exists(monkeypatch, tmp_path:
monkeypatch.setattr(
run_crew_module,
"_install_json_crew_dependencies",
"_install_json_crew_dependencies_if_needed",
lambda: install_calls.append(True),
)
monkeypatch.setattr(
@@ -161,7 +161,9 @@ def test_json_project_env_run_failure_exits_nonzero(monkeypatch, tmp_path: Path)
monkeypatch.chdir(tmp_path)
(tmp_path / "pyproject.toml").write_text("[project]\nname = 'demo'\n")
monkeypatch.setattr(run_crew_module, "_install_json_crew_dependencies", lambda: None)
monkeypatch.setattr(
run_crew_module, "_install_json_crew_dependencies_if_needed", lambda: None
)
monkeypatch.setattr(
run_crew_module, "build_env_with_all_tool_credentials", lambda: {}
)
@@ -177,10 +179,10 @@ def test_json_project_env_run_failure_exits_nonzero(monkeypatch, tmp_path: Path)
assert exc_info.value.code == 7
def test_json_run_installs_dependencies_when_pyproject_exists(
def test_json_run_installs_dependencies_when_pyproject_has_no_lockfile(
monkeypatch, tmp_path: Path
):
"""JSON crew runs should lock/sync project dependencies before loading."""
"""JSON crew runs should lock/sync project dependencies only once."""
monkeypatch.chdir(tmp_path)
(tmp_path / "pyproject.toml").write_text("[project]\nname = 'demo'\n")
calls = []
@@ -192,11 +194,32 @@ def test_json_run_installs_dependencies_when_pyproject_exists(
monkeypatch.setattr("crewai_cli.install_crew.install_crew", fake_install_crew)
run_crew_module._install_json_crew_dependencies()
run_crew_module._install_json_crew_dependencies_if_needed()
assert calls == [([], True, False)]
@pytest.mark.parametrize("lockfile", ["uv.lock", "poetry.lock"])
def test_json_run_skips_dependency_install_when_lockfile_exists(
monkeypatch, tmp_path: Path, lockfile: str
):
monkeypatch.chdir(tmp_path)
(tmp_path / "pyproject.toml").write_text("[project]\nname = 'demo'\n")
(tmp_path / lockfile).write_text("# lock\n")
calls = []
def fake_install_crew(
proxy_options, *, raise_on_error=False, install_project=None
):
calls.append((proxy_options, raise_on_error, install_project))
monkeypatch.setattr("crewai_cli.install_crew.install_crew", fake_install_crew)
run_crew_module._install_json_crew_dependencies_if_needed()
assert calls == []
def test_json_run_skips_dependency_install_without_pyproject(
monkeypatch, tmp_path: Path
):
@@ -210,7 +233,7 @@ def test_json_run_skips_dependency_install_without_pyproject(
monkeypatch.setattr("crewai_cli.install_crew.install_crew", fake_install_crew)
run_crew_module._install_json_crew_dependencies()
run_crew_module._install_json_crew_dependencies_if_needed()
assert calls == []
@@ -227,7 +250,7 @@ def test_json_run_install_failure_exits_nonzero(monkeypatch, tmp_path: Path):
monkeypatch.setattr("crewai_cli.install_crew.install_crew", fake_install_crew)
with pytest.raises(SystemExit) as exc_info:
run_crew_module._install_json_crew_dependencies()
run_crew_module._install_json_crew_dependencies_if_needed()
assert exc_info.value.code == 42