mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-09-17 15:17:57 +02:00
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cac7783bd | ||
|
|
1bf8293d38 | ||
|
|
d85ae52b85 | ||
|
|
3a6885d58c | ||
|
|
48051304a9 | ||
|
|
c416b6561c |
@@ -51,6 +51,7 @@ RESERVED_ENV_VARS = frozenset(
|
|||||||
"LANGGRAPH_AUTH_TYPE",
|
"LANGGRAPH_AUTH_TYPE",
|
||||||
"LANGSMITH_AUTH_ENDPOINT",
|
"LANGSMITH_AUTH_ENDPOINT",
|
||||||
"LANGSMITH_TENANT_ID",
|
"LANGSMITH_TENANT_ID",
|
||||||
|
"LANGSMITH_WORKSPACE_ID",
|
||||||
"LANGSMITH_AUTH_VERIFY_TENANT_ID",
|
"LANGSMITH_AUTH_VERIFY_TENANT_ID",
|
||||||
"LANGSMITH_HOST_PROJECT_ID",
|
"LANGSMITH_HOST_PROJECT_ID",
|
||||||
"LANGSMITH_HOST_PROJECT_NAME",
|
"LANGSMITH_HOST_PROJECT_NAME",
|
||||||
@@ -1229,6 +1230,24 @@ def _run_remote_build(
|
|||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def _get_tenant_id(env_vars: dict[str, str]) -> str | None:
|
||||||
|
"""Get the tenant ID from LANGSMITH_TENANT_ID or LANGSMITH_WORKSPACE_ID."""
|
||||||
|
tenant_id = env_vars.get("LANGSMITH_TENANT_ID") or os.environ.get(
|
||||||
|
"LANGSMITH_TENANT_ID"
|
||||||
|
)
|
||||||
|
fallback_tenant_id = env_vars.get("LANGSMITH_WORKSPACE_ID") or os.environ.get(
|
||||||
|
"LANGSMITH_WORKSPACE_ID"
|
||||||
|
)
|
||||||
|
if tenant_id and fallback_tenant_id:
|
||||||
|
raise click.UsageError(
|
||||||
|
"LANGSMITH_TENANT_ID and LANGSMITH_WORKSPACE_ID cannot both be set. "
|
||||||
|
"Set only one."
|
||||||
|
)
|
||||||
|
if tenant_id:
|
||||||
|
return tenant_id
|
||||||
|
return fallback_tenant_id or None
|
||||||
|
|
||||||
|
|
||||||
def _create_host_backend_client(
|
def _create_host_backend_client(
|
||||||
host_url: str | None,
|
host_url: str | None,
|
||||||
api_key: str | None,
|
api_key: str | None,
|
||||||
@@ -1236,6 +1255,7 @@ def _create_host_backend_client(
|
|||||||
) -> HostBackendClient:
|
) -> HostBackendClient:
|
||||||
if env_vars is None:
|
if env_vars is None:
|
||||||
env_vars = _parse_env_from_config({}, pathlib.Path.cwd() / DEFAULT_CONFIG)
|
env_vars = _parse_env_from_config({}, pathlib.Path.cwd() / DEFAULT_CONFIG)
|
||||||
|
tenant_id = _get_tenant_id(env_vars)
|
||||||
resolved_api_key = api_key
|
resolved_api_key = api_key
|
||||||
if not resolved_api_key:
|
if not resolved_api_key:
|
||||||
for key_name in _API_KEY_ENV_NAMES:
|
for key_name in _API_KEY_ENV_NAMES:
|
||||||
@@ -1258,9 +1278,6 @@ def _create_host_backend_client(
|
|||||||
fg="yellow",
|
fg="yellow",
|
||||||
)
|
)
|
||||||
resolved_api_key = click.prompt("Enter LangSmith API key", hide_input=True)
|
resolved_api_key = click.prompt("Enter LangSmith API key", hide_input=True)
|
||||||
tenant_id = env_vars.get("LANGSMITH_TENANT_ID") or os.environ.get(
|
|
||||||
"LANGSMITH_TENANT_ID"
|
|
||||||
)
|
|
||||||
return HostBackendClient(host_url, resolved_api_key, tenant_id=tenant_id)
|
return HostBackendClient(host_url, resolved_api_key, tenant_id=tenant_id)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ from langgraph_cli.deploy import (
|
|||||||
_parse_env_from_config,
|
_parse_env_from_config,
|
||||||
_resolve_env_path,
|
_resolve_env_path,
|
||||||
_resolve_pushed_image_digest,
|
_resolve_pushed_image_digest,
|
||||||
|
_secrets_from_env,
|
||||||
_smith_dashboard_base_url,
|
_smith_dashboard_base_url,
|
||||||
_validate_prebuilt_image,
|
_validate_prebuilt_image,
|
||||||
normalize_image_tag,
|
normalize_image_tag,
|
||||||
@@ -540,6 +541,63 @@ class TestCreateHostBackendClientNoInput:
|
|||||||
assert client is not None
|
assert client is not None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("source", ["config", "shell"])
|
||||||
|
@pytest.mark.parametrize("name", ["LANGSMITH_TENANT_ID", "LANGSMITH_WORKSPACE_ID"])
|
||||||
|
def test_workspace_id_alias(monkeypatch, source, name):
|
||||||
|
monkeypatch.delenv("LANGSMITH_WORKSPACE_ID", raising=False)
|
||||||
|
monkeypatch.delenv("LANGSMITH_TENANT_ID", raising=False)
|
||||||
|
env_vars = {}
|
||||||
|
if source == "config":
|
||||||
|
env_vars[name] = "workspace"
|
||||||
|
else:
|
||||||
|
monkeypatch.setenv(name, "workspace")
|
||||||
|
|
||||||
|
def handler(request):
|
||||||
|
assert request.headers["X-Tenant-ID"] == "workspace"
|
||||||
|
return httpx.Response(200, json={"resources": []})
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
httpx, "HTTPTransport", lambda **kwargs: httpx.MockTransport(handler)
|
||||||
|
)
|
||||||
|
client = _create_host_backend_client(
|
||||||
|
"https://api.example.com", "test-key", env_vars
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
client.list_deployments()
|
||||||
|
finally:
|
||||||
|
client._client.close()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("tenant_source", ["config", "shell"])
|
||||||
|
@pytest.mark.parametrize("workspace_source", ["config", "shell"])
|
||||||
|
@pytest.mark.parametrize("workspace_id", ["tenant-id", "workspace-id"])
|
||||||
|
def test_rejects_both_workspace_names(
|
||||||
|
monkeypatch, tenant_source, workspace_source, workspace_id
|
||||||
|
):
|
||||||
|
env_vars = {}
|
||||||
|
for name, source, value in [
|
||||||
|
("LANGSMITH_TENANT_ID", tenant_source, "tenant-id"),
|
||||||
|
("LANGSMITH_WORKSPACE_ID", workspace_source, workspace_id),
|
||||||
|
]:
|
||||||
|
monkeypatch.delenv(name, raising=False)
|
||||||
|
if source == "config":
|
||||||
|
env_vars[name] = value
|
||||||
|
else:
|
||||||
|
monkeypatch.setenv(name, value)
|
||||||
|
|
||||||
|
with pytest.raises(
|
||||||
|
click.UsageError,
|
||||||
|
match="LANGSMITH_TENANT_ID and LANGSMITH_WORKSPACE_ID cannot both be set",
|
||||||
|
):
|
||||||
|
_create_host_backend_client("https://api.example.com", "test-key", env_vars)
|
||||||
|
|
||||||
|
|
||||||
|
def test_workspace_id_is_not_uploaded_as_secret():
|
||||||
|
assert _secrets_from_env(
|
||||||
|
{"LANGSMITH_WORKSPACE_ID": "workspace", "APP_SETTING": "value"}
|
||||||
|
) == [{"name": "APP_SETTING", "value": "value"}]
|
||||||
|
|
||||||
|
|
||||||
class TestSmithDashboardBaseUrl:
|
class TestSmithDashboardBaseUrl:
|
||||||
def test_none_returns_default(self):
|
def test_none_returns_default(self):
|
||||||
assert _smith_dashboard_base_url(None) == "https://smith.langchain.com"
|
assert _smith_dashboard_base_url(None) == "https://smith.langchain.com"
|
||||||
|
|||||||
Reference in New Issue
Block a user