mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-07-02 13:48:09 +00:00
fix(cli): skip project install for json crew sync
This commit is contained in:
@@ -1,20 +1,63 @@
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
|
||||
import click
|
||||
|
||||
from crewai_cli.utils import build_env_with_all_tool_credentials
|
||||
from crewai_cli.utils import build_env_with_all_tool_credentials, parse_toml
|
||||
|
||||
|
||||
def _find_json_crew_file(project_root: Path | None = None) -> Path | None:
|
||||
"""Return the JSON crew definition path when present."""
|
||||
root = project_root or Path.cwd()
|
||||
for filename in ("crew.jsonc", "crew.json"):
|
||||
crew_path = root / filename
|
||||
if crew_path.is_file():
|
||||
return crew_path
|
||||
return None
|
||||
|
||||
|
||||
def _is_json_crew_project(project_root: Path | None = None) -> bool:
|
||||
"""Return True for JSON crew projects that do not need package install."""
|
||||
root = project_root or Path.cwd()
|
||||
if _find_json_crew_file(root) is None:
|
||||
return False
|
||||
|
||||
pyproject_path = root / "pyproject.toml"
|
||||
if not pyproject_path.is_file():
|
||||
return True
|
||||
|
||||
try:
|
||||
pyproject = parse_toml(pyproject_path.read_text())
|
||||
except Exception:
|
||||
return True
|
||||
|
||||
declared_type: str | None = (
|
||||
(pyproject.get("tool") or {}).get("crewai", {}).get("type")
|
||||
)
|
||||
return declared_type != "flow"
|
||||
|
||||
|
||||
# Be mindful about changing this.
|
||||
# on some environments we don't use this command but instead uv sync directly
|
||||
# so if you expect this to support more things you will need to replicate it there
|
||||
# ask @joaomdmoura if you are unsure
|
||||
def install_crew(proxy_options: list[str], *, raise_on_error: bool = False) -> None:
|
||||
def install_crew(
|
||||
proxy_options: list[str],
|
||||
*,
|
||||
raise_on_error: bool = False,
|
||||
install_project: bool | None = None,
|
||||
) -> None:
|
||||
"""
|
||||
Install the crew by running the UV command to lock and install.
|
||||
"""
|
||||
try:
|
||||
command = ["uv", "sync", *proxy_options]
|
||||
if install_project is None:
|
||||
install_project = not _is_json_crew_project()
|
||||
|
||||
command = ["uv", "sync"]
|
||||
if not install_project and "--no-install-project" not in proxy_options:
|
||||
command.append("--no-install-project")
|
||||
command.extend(proxy_options)
|
||||
|
||||
# Inject tool repository credentials so uv can authenticate
|
||||
# against private package indexes (e.g. crewai tool repository).
|
||||
|
||||
@@ -231,7 +231,7 @@ def _install_json_crew_dependencies() -> None:
|
||||
|
||||
try:
|
||||
click.echo("Installing dependencies...")
|
||||
install_crew([], raise_on_error=True)
|
||||
install_crew([], raise_on_error=True, install_project=False)
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise SystemExit(e.returncode) from e
|
||||
except Exception as e:
|
||||
|
||||
66
lib/cli/tests/test_install_crew.py
Normal file
66
lib/cli/tests/test_install_crew.py
Normal file
@@ -0,0 +1,66 @@
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
import crewai_cli.install_crew as install_crew_module
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _tool_credentials(monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
install_crew_module,
|
||||
"build_env_with_all_tool_credentials",
|
||||
lambda: {"CREWAI_TEST": "1"},
|
||||
)
|
||||
|
||||
|
||||
def test_install_crew_json_project_skips_project_install(
|
||||
fp, monkeypatch, tmp_path: Path
|
||||
):
|
||||
monkeypatch.chdir(tmp_path)
|
||||
(tmp_path / "pyproject.toml").write_text(
|
||||
"""
|
||||
[project]
|
||||
name = "json_crew"
|
||||
|
||||
[tool.crewai]
|
||||
type = "crew"
|
||||
""".strip()
|
||||
)
|
||||
(tmp_path / "crew.jsonc").write_text("{}\n")
|
||||
fp.register(["uv", "sync", "--no-install-project"], stdout="")
|
||||
|
||||
install_crew_module.install_crew([])
|
||||
|
||||
|
||||
def test_install_crew_flow_project_installs_project(fp, monkeypatch, tmp_path: Path):
|
||||
monkeypatch.chdir(tmp_path)
|
||||
(tmp_path / "pyproject.toml").write_text(
|
||||
"""
|
||||
[project]
|
||||
name = "flow_project"
|
||||
|
||||
[tool.crewai]
|
||||
type = "flow"
|
||||
""".strip()
|
||||
)
|
||||
(tmp_path / "crew.jsonc").write_text("{}\n")
|
||||
fp.register(["uv", "sync"], stdout="")
|
||||
|
||||
install_crew_module.install_crew([])
|
||||
|
||||
|
||||
def test_install_crew_classic_project_installs_project(
|
||||
fp, monkeypatch, tmp_path: Path
|
||||
):
|
||||
monkeypatch.chdir(tmp_path)
|
||||
(tmp_path / "pyproject.toml").write_text("[project]\nname = 'classic'\n")
|
||||
fp.register(["uv", "sync"], stdout="")
|
||||
|
||||
install_crew_module.install_crew([])
|
||||
|
||||
|
||||
def test_install_crew_install_project_false_adds_no_install_project(fp):
|
||||
fp.register(["uv", "sync", "--no-install-project", "--frozen"], stdout="")
|
||||
|
||||
install_crew_module.install_crew(["--frozen"], install_project=False)
|
||||
@@ -127,14 +127,16 @@ def test_json_run_installs_dependencies_when_pyproject_exists(
|
||||
(tmp_path / "pyproject.toml").write_text("[project]\nname = 'demo'\n")
|
||||
calls = []
|
||||
|
||||
def fake_install_crew(proxy_options, *, raise_on_error=False):
|
||||
calls.append((proxy_options, raise_on_error))
|
||||
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()
|
||||
|
||||
assert calls == [([], True)]
|
||||
assert calls == [([], True, False)]
|
||||
|
||||
|
||||
def test_json_run_skips_dependency_install_without_pyproject(
|
||||
@@ -143,7 +145,9 @@ def test_json_run_skips_dependency_install_without_pyproject(
|
||||
monkeypatch.chdir(tmp_path)
|
||||
calls = []
|
||||
|
||||
def fake_install_crew(proxy_options, *, raise_on_error=False):
|
||||
def fake_install_crew(
|
||||
proxy_options, *, raise_on_error=False, install_project=None
|
||||
):
|
||||
calls.append((proxy_options, raise_on_error))
|
||||
|
||||
monkeypatch.setattr("crewai_cli.install_crew.install_crew", fake_install_crew)
|
||||
@@ -157,7 +161,9 @@ def test_json_run_install_failure_exits_nonzero(monkeypatch, tmp_path: Path):
|
||||
monkeypatch.chdir(tmp_path)
|
||||
(tmp_path / "pyproject.toml").write_text("[project]\nname = 'demo'\n")
|
||||
|
||||
def fake_install_crew(proxy_options, *, raise_on_error=False):
|
||||
def fake_install_crew(
|
||||
proxy_options, *, raise_on_error=False, install_project=None
|
||||
):
|
||||
raise subprocess.CalledProcessError(42, ["uv", "sync"])
|
||||
|
||||
monkeypatch.setattr("crewai_cli.install_crew.install_crew", fake_install_crew)
|
||||
|
||||
Reference in New Issue
Block a user