Compare commits

...

3 Commits

Author SHA1 Message Date
João Moura
e10c17fcf6 Open deployment page after CLI deploy (#6343)
Some checks are pending
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (python) (push) Waiting to run
Vulnerability Scan / pip-audit (push) Waiting to run
* Open deployment page after CLI deploy

* Format deploy browser URL helper

* Handle browser launch failures

* Prefer nested deployment identifiers
2026-06-26 14:34:07 -03:00
João Moura
f364a7d988 Fix JSON crew version pin (#6342)
Some checks failed
Check Documentation Broken Links / Check broken links (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
* Fix JSON crew version pin

* Use bounded CrewAI dependency range
2026-06-26 05:19:14 -03:00
João Moura
2771c02f45 docs: improve coding agent setup CTA (#6344)
* docs: improve coding agent setup CTA

* docs: move home CTA to published index

* docs: address CTA review feedback
2026-06-26 05:10:55 -03:00
19 changed files with 414 additions and 44 deletions

View File

@@ -5,15 +5,49 @@ icon: wrench
mode: "wide"
---
### Watch: Building CrewAI Agents & Flows with Coding Agent Skills
<div
style={{
display: "flex",
flexDirection: "column",
gap: 18,
padding: "24px",
marginBottom: 32,
borderRadius: 12,
border: "1px solid rgba(235,102,88,0.28)",
background: "linear-gradient(180deg, rgba(235,102,88,0.14) 0%, rgba(235,102,88,0.06) 100%)"
}}
>
<div>
<p style={{ margin: 0, color: "#EB6658", fontSize: 13, fontWeight: 700, textTransform: "uppercase" }}>
Coding agent setup
</p>
<h2 style={{ margin: "6px 0 8px" }}>Set up CrewAI in your coding agent</h2>
<p style={{ margin: 0, color: "var(--mint-text-2)", maxWidth: 760 }}>
Copy a ready-to-paste setup prompt for Claude Code, Codex, Cursor, or any coding agent. It installs the official CrewAI skills, checks the CLI, and points the agent at the right docs before it edits code.
</p>
</div>
Install our coding agent skills (Claude Code, Codex, ...) to quickly get your coding agents up and running with CrewAI.
<button
type="button"
className="button button-primary"
onClick={async (event) => {
const prompt = `Set up this environment so I can build with CrewAI.
<div style={{ display: "flex", flexWrap: "wrap", gap: 12, alignItems: "center" }}>
<button
type="button"
style={{
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
minHeight: 42,
padding: "0 16px",
borderRadius: 8,
border: "1px solid #EB6658",
background: "#EB6658",
color: "#FFFFFF",
fontSize: 15,
fontWeight: 700,
lineHeight: 1,
cursor: "pointer",
boxShadow: "0 10px 24px rgba(235,102,88,0.22)"
}}
onClick={async (event) => {
const prompt = `Set up this environment so I can build with CrewAI.
First install the official CrewAI coding-agent skills if this environment supports npx:
@@ -48,21 +82,49 @@ Setup steps:
Do not hardcode API keys. Use .env.
Do not invent CLI flags. Validate with crewai --help or crewai create --help.
If a command fails, show the exact command and error, explain the likely cause, fix what you can safely fix, and retry once.`;
const button = event.currentTarget;
try {
await navigator.clipboard.writeText(prompt);
button.textContent = "Copied";
} catch {
button.textContent = "Copy failed";
} finally {
window.setTimeout(() => {
button.textContent = "Copy instructions for coding agents";
}, 1600);
}
}}
>
Copy instructions for coding agents
</button>
const button = event.currentTarget;
const resetTimeout = button.dataset.resetTimeout;
if (resetTimeout) {
window.clearTimeout(Number(resetTimeout));
}
try {
await navigator.clipboard.writeText(prompt);
button.textContent = "Copied";
} catch {
button.textContent = "Copy failed";
} finally {
button.dataset.resetTimeout = String(window.setTimeout(() => {
button.textContent = "Copy agent setup prompt";
delete button.dataset.resetTimeout;
}, 1600));
}
}}
>
Copy agent setup prompt
</button>
<a
href="/en/guides/coding-tools/build-with-ai"
style={{
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
minHeight: 42,
padding: "0 16px",
borderRadius: 8,
border: "1px solid rgba(235,102,88,0.36)",
color: "#EB6658",
fontSize: 15,
fontWeight: 700,
lineHeight: 1,
textDecoration: "none"
}}
>
View coding-agent guide
</a>
</div>
</div>
### Watch: Building CrewAI Agents & Flows with Coding Agent Skills
<iframe src="https://www.loom.com/embed/befb9f68b81f42ad8112bfdd95a780af" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen style={{width: "100%", height: "400px"}}></iframe>

View File

@@ -27,9 +27,133 @@ mode: "wide"
</div>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 12, justifyContent: 'center' }}>
<a className="button button-primary" href="/en/quickstart">Get started</a>
<a className="button" href="/en/changelog">View changelog</a>
<a className="button" href="/en/api-reference/introduction">API Reference</a>
<a
href="/en/quickstart"
style={{
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
minHeight: 42,
padding: "0 16px",
borderRadius: 8,
border: "1px solid #EB6658",
background: "#EB6658",
color: "#FFFFFF",
fontWeight: 700,
lineHeight: 1,
textDecoration: "none"
}}
>
Get started
</a>
<button
type="button"
style={{
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
minHeight: 42,
padding: "0 16px",
borderRadius: 8,
border: "1px solid rgba(235,102,88,0.36)",
background: "rgba(235,102,88,0.08)",
color: "#EB6658",
fontWeight: 700,
lineHeight: 1,
cursor: "pointer"
}}
onClick={async (event) => {
const prompt = `Set up this environment so I can build with CrewAI.
First install the official CrewAI coding-agent skills if this environment supports npx:
npx skills add crewaiinc/skills
If npx is missing or the current agent cannot load skills, do not fail the whole setup. Report the exact issue and continue using the CrewAI docs directly.
Use these CrewAI docs as source of truth before making assumptions:
- https://skills.crewai.com
- https://docs.crewai.com/llms.txt
- https://docs.crewai.com/en/installation
- https://docs.crewai.com/en/guides/coding-tools/build-with-ai
Setup steps:
1. Check python3 --version. CrewAI requires Python >=3.10 and <3.14.
2. Install uv if missing:
curl -LsSf https://astral.sh/uv/install.sh | sh
3. Source the uv environment if needed:
source "$HOME/.local/bin/env"
4. Install the CrewAI CLI:
uv tool install crewai
5. Verify the CLI:
crewai version
crewai create --help
6. Create a project:
CREWAI_DMN=true crewai create
7. After project creation, inspect the generated files before editing.
8. Run:
crewai install
crewai run
Do not hardcode API keys. Use .env.
Do not invent CLI flags. Validate with crewai --help or crewai create --help.
If a command fails, show the exact command and error, explain the likely cause, fix what you can safely fix, and retry once.`;
const button = event.currentTarget;
const resetTimeout = button.dataset.resetTimeout;
if (resetTimeout) {
window.clearTimeout(Number(resetTimeout));
}
try {
await navigator.clipboard.writeText(prompt);
button.textContent = "Copied";
} catch {
button.textContent = "Copy failed";
} finally {
button.dataset.resetTimeout = String(window.setTimeout(() => {
button.textContent = "Copy agent setup prompt";
delete button.dataset.resetTimeout;
}, 1600));
}
}}
>
Copy agent setup prompt
</button>
<a
href="/guides/coding-tools/build-with-ai"
style={{
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
minHeight: 42,
padding: "0 16px",
borderRadius: 8,
border: "1px solid rgba(235,102,88,0.28)",
color: "#EB6658",
fontWeight: 700,
lineHeight: 1,
textDecoration: "none"
}}
>
Coding-agent guide
</a>
<a
href="/en/api-reference/introduction"
style={{
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
minHeight: 42,
padding: "0 16px",
borderRadius: 8,
border: "1px solid rgba(235,102,88,0.18)",
color: "var(--mint-text-2)",
fontWeight: 700,
lineHeight: 1,
textDecoration: "none"
}}
>
API Reference
</a>
</div>
</div>

View File

@@ -4,6 +4,8 @@ import shutil
import click
from crewai_core.telemetry import Telemetry
from crewai_cli.version import get_crewai_tools_dependency
DECLARATIVE_FLOW_FOLDERS = ("crews", "tools", "knowledge", "skills")
@@ -71,6 +73,9 @@ def _create_python_flow(
content = content.replace("{{name}}", name)
content = content.replace("{{flow_name}}", class_name)
content = content.replace("{{folder_name}}", folder_name)
content = content.replace(
"{{crewai_tools_dependency}}", get_crewai_tools_dependency()
)
with open(dst_file, "w") as file:
file.write(content)
@@ -138,6 +143,9 @@ def _create_declarative_flow(
content = content.replace("{{name}}", name)
content = content.replace("{{flow_name}}", class_name)
content = content.replace("{{folder_name}}", folder_name)
content = content.replace(
"{{crewai_tools_dependency}}", get_crewai_tools_dependency()
)
dst_file.write_text(content, encoding="utf-8")
(project_root / ".env").write_text("OPENAI_API_KEY=YOUR_API_KEY", encoding="utf-8")

View File

@@ -20,6 +20,7 @@ from crewai_cli.utils import (
load_env_vars,
write_env_file,
)
from crewai_cli.version import get_crewai_tools_dependency
# ── Provider / model data ───────────────────────────────────────
@@ -89,7 +90,7 @@ description = "{name} using crewAI"
authors = [{{ name = "Your Name", email = "you@example.com" }}]
requires-python = ">=3.10,<3.14"
dependencies = [
"crewai[tools]==1.14.8a1"
"{crewai_tools_dependency}"
]
[build-system]
@@ -1134,7 +1135,11 @@ def create_json_crew(
# Write pyproject.toml
(folder_path / "pyproject.toml").write_text(
_PYPROJECT_TOML.format(folder_name=folder_name, name=name),
_PYPROJECT_TOML.format(
folder_name=folder_name,
name=name,
crewai_tools_dependency=get_crewai_tools_dependency(),
),
encoding="utf-8",
)

View File

@@ -1,12 +1,15 @@
from pathlib import Path
import subprocess
from typing import Any
from urllib.parse import quote
import webbrowser
from crewai_core.plus_api import CreateCrewPayload
from rich.console import Console
from crewai_cli import git
from crewai_cli.command import BaseCommand, PlusAPIMixin
from crewai_cli.constants import DEFAULT_CREWAI_ENTERPRISE_URL
from crewai_cli.deploy.archive import create_project_zip
from crewai_cli.deploy.validate import DeployValidator, Severity, render_report
from crewai_cli.utils import fetch_and_json_env_file, get_project_name
@@ -14,6 +17,8 @@ from crewai_cli.utils import fetch_and_json_env_file, get_project_name
console = Console()
_MISSING_LOCKFILE_ERROR_CODES = {"missing_lockfile"}
_DEPLOYMENT_ID_KEYS = ("deployment_id", "deploymentId")
_DEPLOYMENT_FALLBACK_IDENTIFIER_KEYS = ("id", "uuid")
def _run_predeploy_validation(
@@ -79,6 +84,39 @@ def _env_summary(env_vars: dict[str, str]) -> str:
return f"{len(env_vars)} env vars: {keys}"
def _deployment_identifier(json_response: dict[str, Any]) -> str | None:
"""Return the best available identifier for a deployment show URL."""
deployment = json_response.get("deployment")
for key in _DEPLOYMENT_ID_KEYS:
value = json_response.get(key)
if value:
return str(value)
if isinstance(deployment, dict):
for key in _DEPLOYMENT_ID_KEYS + _DEPLOYMENT_FALLBACK_IDENTIFIER_KEYS:
value = deployment.get(key)
if value:
return str(value)
for key in _DEPLOYMENT_FALLBACK_IDENTIFIER_KEYS:
value = json_response.get(key)
if value:
return str(value)
return None
def _deployment_page_url(base_url: str, json_response: dict[str, Any]) -> str | None:
"""Build the CrewAI deployment show URL for a response payload."""
identifier = _deployment_identifier(json_response)
if not identifier:
return None
return (
f"{base_url.rstrip('/')}/crewai_plus/deployments/{quote(identifier, safe='')}"
)
def _needs_lockfile_for_deploy(project_root: Path | None = None) -> bool:
"""Return True when deploy should create the project's first lockfile."""
root = project_root or Path.cwd()
@@ -165,6 +203,7 @@ class DeployCommand(BaseCommand, PlusAPIMixin):
console.print("crewai deploy status")
console.print(" or")
console.print(f'crewai deploy status --uuid "{json_response["uuid"]}"')
self._open_deployment_page(json_response)
def _display_logs(self, log_messages: list[dict[str, Any]]) -> None:
"""
@@ -178,6 +217,28 @@ class DeployCommand(BaseCommand, PlusAPIMixin):
f"{log_message['timestamp']} - {log_message['level']}: {log_message['message']}"
)
def _open_deployment_page(self, json_response: dict[str, Any]) -> None:
"""Open the deployment show page in the user's browser when possible."""
base_url = str(
getattr(self.plus_api_client, "base_url", None)
or DEFAULT_CREWAI_ENTERPRISE_URL
)
deployment_url = _deployment_page_url(base_url, json_response)
if not deployment_url:
return
console.print(f"\nOpening deployment page: [blue]{deployment_url}[/blue]")
try:
opened = webbrowser.open(deployment_url)
except Exception:
opened = False
if not opened:
console.print(
"Could not open the deployment page automatically.",
style="yellow",
)
def deploy(self, uuid: str | None = None, skip_validate: bool = False) -> None:
"""
Deploy a crew using either UUID or project name.
@@ -438,6 +499,7 @@ class DeployCommand(BaseCommand, PlusAPIMixin):
console.print("crewai deploy push")
console.print(" or")
console.print(f"crewai deploy push --uuid {json_response['uuid']}")
self._open_deployment_page(json_response)
def list_crews(self) -> None:
"""

View File

@@ -19,7 +19,7 @@ from crewai_cli.utils import (
is_dmn_mode_enabled,
read_toml,
)
from crewai_cli.version import get_crewai_version
from crewai_cli.version import get_crewai_tools_dependency, get_crewai_version
if TYPE_CHECKING:
@@ -32,12 +32,12 @@ if TYPE_CHECKING:
_INPUT_PLACEHOLDER_RE = re.compile(r"(?<!{){([A-Za-z_][A-Za-z0-9_\-]*)}(?!})")
_CREWAI_CLI_RUNNER_PACKAGE_DIR_ENV = "CREWAI_CLI_RUNNER_PACKAGE_DIR"
_CREWAI_RUNNER_SOURCE_DIR_ENV = "CREWAI_RUNNER_SOURCE_DIR"
_FULL_CREWAI_INSTALL_MESSAGE = """\
_FULL_CREWAI_INSTALL_MESSAGE = f"""\
CrewAI CLI is installed without the `crewai` package required to run crews.
Install the full CrewAI prerelease package:
Install the full CrewAI package:
uv tool install --force --prerelease=allow 'crewai[tools]==1.14.8a1'
uv tool install --force '{get_crewai_tools_dependency()}'
The quotes are required in zsh so `crewai[tools]` is not treated as a glob.
"""

View File

@@ -5,7 +5,7 @@ description = "{{name}} using crewAI"
authors = [{ name = "Your Name", email = "you@example.com" }]
requires-python = ">=3.10,<3.14"
dependencies = [
"crewai[tools]==1.15.0"
"{{crewai_tools_dependency}}"
]
[project.scripts]

View File

@@ -5,7 +5,7 @@ description = "{{name}} using crewAI"
authors = [{ name = "Your Name", email = "you@example.com" }]
requires-python = ">=3.10,<3.14"
dependencies = [
"crewai[tools]==1.15.0"
"{{crewai_tools_dependency}}"
]
[build-system]

View File

@@ -5,7 +5,7 @@ description = "{{name}} using crewAI"
authors = [{ name = "Your Name", email = "you@example.com" }]
requires-python = ">=3.10,<3.14"
dependencies = [
"crewai[tools]==1.15.0"
"{{crewai_tools_dependency}}"
]
[project.scripts]

View File

@@ -5,7 +5,7 @@ description = "Power up your crews with {{folder_name}}"
readme = "README.md"
requires-python = ">=3.10,<3.14"
dependencies = [
"crewai[tools]==1.15.0"
"{{crewai_tools_dependency}}"
]
[tool.crewai]

View File

@@ -23,6 +23,7 @@ from crewai_cli.utils import (
tree_copy,
tree_find_and_replace,
)
from crewai_cli.version import get_crewai_tools_dependency
console = Console()
@@ -81,6 +82,9 @@ class ToolCommand(BaseCommand, PlusAPIMixin):
tree_copy(template_dir, project_root)
tree_find_and_replace(project_root, "{{folder_name}}", folder_name)
tree_find_and_replace(project_root, "{{class_name}}", class_name)
tree_find_and_replace(
project_root, "{{crewai_tools_dependency}}", get_crewai_tools_dependency()
)
agents_md_src = Path(__file__).parent.parent / "templates" / "AGENTS.md"
if agents_md_src.exists():

View File

@@ -19,6 +19,8 @@ from crewai_core.tool_credentials import (
)
from rich.console import Console
from crewai_cli.version import get_crewai_tools_dependency
__all__ = [
"build_env_with_all_tool_credentials",
@@ -73,6 +75,9 @@ def copy_template(
content = content.replace("{{name}}", name)
content = content.replace("{{crew_name}}", class_name)
content = content.replace("{{folder_name}}", folder_name)
content = content.replace(
"{{crewai_tools_dependency}}", get_crewai_tools_dependency()
)
with open(dst, "w") as file:
file.write(content)

View File

@@ -13,10 +13,26 @@ from crewai_core.version import (
is_current_version_yanked as is_current_version_yanked,
is_newer_version_available as is_newer_version_available,
)
from packaging.version import Version
from crewai_cli import __version__ as _crewai_cli_version
def get_crewai_dependency_range(current_version: str | None = None) -> str:
"""Return the supported CrewAI dependency range for generated projects."""
parsed_version = Version(current_version or _crewai_cli_version)
return f">={parsed_version},<{parsed_version.major + 1}.0.0"
def get_crewai_tools_dependency(current_version: str | None = None) -> str:
"""Return the generated-project dependency for CrewAI with tools."""
return f"crewai[tools]{get_crewai_dependency_range(current_version)}"
__all__ = [
"check_version",
"get_crewai_dependency_range",
"get_crewai_tools_dependency",
"get_crewai_version",
"get_latest_version_from_pypi",
"is_current_version_yanked",

View File

@@ -176,7 +176,7 @@ def test_create_project_zip_keeps_json_project_root_shape(tmp_path: Path):
[project]
name = "json_crew"
version = "0.1.0"
dependencies = ["crewai[tools]==1.14.8a1"]
dependencies = ["crewai[tools]>=1.15.0,<2.0.0"]
[tool.crewai]
type = "crew"

View File

@@ -167,6 +167,36 @@ def test_prepare_project_for_deploy_creates_missing_lock_after_validation(
assert validators == []
def test_deployment_page_url_prefers_deployment_id():
assert (
deploy_main._deployment_page_url(
"https://app.crewai.com",
{"uuid": "crew-uuid", "deployment_id": 128687},
)
== "https://app.crewai.com/crewai_plus/deployments/128687"
)
def test_deployment_page_url_prefers_nested_deployment_id_over_crew_uuid():
assert (
deploy_main._deployment_page_url(
"https://app.crewai.com",
{"uuid": "crew-uuid", "deployment": {"deployment_id": 128687}},
)
== "https://app.crewai.com/crewai_plus/deployments/128687"
)
def test_deployment_page_url_falls_back_to_nested_uuid():
assert (
deploy_main._deployment_page_url(
"https://app.crewai.com/",
{"deployment": {"uuid": "deployment-uuid"}},
)
== "https://app.crewai.com/crewai_plus/deployments/deployment-uuid"
)
class TestDeployCommand(unittest.TestCase):
@patch("crewai_cli.command.get_auth_token")
@patch("crewai_cli.deploy.main.get_project_name")
@@ -186,6 +216,12 @@ class TestDeployCommand(unittest.TestCase):
self.deploy_command = deploy_main.DeployCommand()
self.mock_client = self.deploy_command.plus_api_client
self.mock_client.base_url = "https://app.crewai.com"
self.mock_browser_open_patcher = patch(
"crewai_cli.deploy.main.webbrowser.open"
)
self.mock_browser_open = self.mock_browser_open_patcher.start()
self.addCleanup(self.mock_browser_open_patcher.stop)
def test_init_success(self):
self.assertEqual(self.deploy_command.project_name, "test_project")
@@ -272,11 +308,50 @@ class TestDeployCommand(unittest.TestCase):
def test_display_deployment_info(self):
with patch("sys.stdout", new=StringIO()) as fake_out:
self.deploy_command._display_deployment_info(
{"uuid": "test-uuid", "status": "deployed"}
{"uuid": "test-uuid", "id": 128687, "status": "deployed"}
)
self.assertIn("Deploying the crew...", fake_out.getvalue())
self.assertIn("test-uuid", fake_out.getvalue())
self.assertIn("deployed", fake_out.getvalue())
self.assertIn(
"https://app.crewai.com/crewai_plus/deployments/128687",
fake_out.getvalue(),
)
self.mock_browser_open.assert_called_once_with(
"https://app.crewai.com/crewai_plus/deployments/128687"
)
def test_display_deployment_info_warns_when_browser_open_returns_false(self):
self.mock_browser_open.return_value = False
with patch("sys.stdout", new=StringIO()) as fake_out:
self.deploy_command._display_deployment_info(
{"uuid": "test-uuid", "id": 128687, "status": "deployed"}
)
self.assertIn(
"Could not open the deployment page automatically.",
fake_out.getvalue(),
)
self.mock_browser_open.assert_called_once_with(
"https://app.crewai.com/crewai_plus/deployments/128687"
)
def test_display_deployment_info_warns_when_browser_open_raises(self):
self.mock_browser_open.side_effect = RuntimeError("no browser")
with patch("sys.stdout", new=StringIO()) as fake_out:
self.deploy_command._display_deployment_info(
{"uuid": "test-uuid", "id": 128687, "status": "deployed"}
)
self.assertIn(
"Could not open the deployment page automatically.",
fake_out.getvalue(),
)
self.mock_browser_open.assert_called_once_with(
"https://app.crewai.com/crewai_plus/deployments/128687"
)
def test_display_logs(self):
with patch("sys.stdout", new=StringIO()) as fake_out:

View File

@@ -735,8 +735,9 @@ def test_json_create_provider_preselects_default_model(tmp_path, monkeypatch):
pyproject = tomli.loads((tmp_path / "json_crew" / "pyproject.toml").read_text())
dependency = pyproject["project"]["dependencies"][0]
assert dependency == "crewai[tools]==1.14.8a1"
assert Version("1.14.8a1") in Requirement(dependency).specifier
assert dependency == "crewai[tools]>=1.15.0,<2.0.0"
assert Version("1.15.0") in Requirement(dependency).specifier
assert Version("2.0.0") not in Requirement(dependency).specifier
assert pyproject["tool"]["hatch"]["build"]["targets"]["wheel"][
"only-include"
] == ["agents", "crew.jsonc", "tools", "knowledge", "skills"]

View File

@@ -25,10 +25,7 @@ def test_missing_crewai_package_shows_full_install_hint(monkeypatch):
message = exc_info.value.message
assert "CrewAI CLI is installed without the `crewai` package" in message
assert (
"uv tool install --force --prerelease=allow 'crewai[tools]==1.14.8a1'"
in message
)
assert "uv tool install --force 'crewai[tools]>=1.15.0,<2.0.0'" in message
assert "quotes are required in zsh" in message

View File

@@ -7,6 +7,8 @@ from unittest.mock import MagicMock, patch
from crewai_cli.version import get_crewai_version as _get_ver
from crewai_cli.version import (
get_crewai_dependency_range,
get_crewai_tools_dependency,
get_crewai_version,
get_latest_version_from_pypi,
is_current_version_yanked,
@@ -31,6 +33,11 @@ def test_dynamic_versioning_consistency() -> None:
assert len(package_version.strip()) > 0
def test_generated_project_dependency_uses_next_major_upper_bound() -> None:
assert get_crewai_dependency_range("1.15.0") == ">=1.15.0,<2.0.0"
assert get_crewai_tools_dependency("1.15.0") == "crewai[tools]>=1.15.0,<2.0.0"
class TestVersionChecking:
"""Test version checking utilities."""

View File

@@ -54,6 +54,10 @@ def test_create_success(mock_subprocess, capsys, tool_command):
)
assert os.path.isfile(os.path.join("test_tool", "src", "test_tool", "tool.py"))
with open(os.path.join("test_tool", "pyproject.toml"), "r") as f:
content = f.read()
assert '"crewai[tools]>=1.15.0,<2.0.0"' in content
with open(os.path.join("test_tool", "src", "test_tool", "tool.py"), "r") as f:
content = f.read()
assert "class TestTool" in content