Files
wehub-resource-sync 4b6817381b
Benchmark image — build + push to ECR (any adapter) / build + push (push) Waiting to run
CI / quality (ubuntu-latest) (push) Waiting to run
CI / test (tools-runtime) (push) Waiting to run
CI / test (e2e-general) (push) Waiting to run
CI / test (cli-runtime) (push) Waiting to run
CI / test (e2e-provider-and-openclaw) (push) Waiting to run
CI / test (integrations-and-misc) (push) Waiting to run
CI / coverage-report (push) Blocked by required conditions
CI / test-kubernetes (push) Waiting to run
CI / should-run-thorough (push) Waiting to run
CI / test-thorough (cloudwatch-demo) (push) Blocked by required conditions
CI / test-thorough (flink-ecs) (push) Blocked by required conditions
CI / test-thorough (upstream-lambda) (push) Blocked by required conditions
CI / test-thorough (prefect-ecs-fargate) (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Blocked by required conditions
Release / publish-release (push) Blocked by required conditions
Release / publish-main-release (push) Blocked by required conditions
Release / prepare (push) Waiting to run
Release / verify (push) Blocked by required conditions
Release / build-python-dist (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Blocked by required conditions
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Waiting to run
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

268 lines
8.7 KiB
Python

from __future__ import annotations
import pytest
from pydantic import ValidationError
from integrations.config_models import (
AWSIntegrationConfig,
BetterStackIntegrationConfig,
CoralogixIntegrationConfig,
HoneycombIntegrationConfig,
SlackWebhookConfig,
SnowflakeIntegrationConfig,
TracerIntegrationConfig,
)
from integrations.datadog.client import DatadogConfig
from integrations.github.mcp import (
_remote_github_mcp_session_url,
build_github_mcp_config,
)
from integrations.grafana.config import GrafanaAccountConfig
from integrations.sentry import build_sentry_config
from integrations.snowflake import classify as classify_snowflake
def test_betterstack_config_rejects_unknown_fields_with_suggestion() -> None:
with pytest.raises(ValidationError, match="query_endpont.*query_endpoint"):
BetterStackIntegrationConfig(
query_endpont="https://x", # type: ignore[call-arg]
username="u",
)
def test_betterstack_config_strips_trailing_slash_and_whitespace() -> None:
cfg = BetterStackIntegrationConfig(
query_endpoint=" https://eu-nbg-2-connect.betterstackdata.com/ ",
username=" user ",
)
assert cfg.query_endpoint == "https://eu-nbg-2-connect.betterstackdata.com"
assert cfg.username == "user"
def test_betterstack_config_sources_from_comma_string() -> None:
cfg = BetterStackIntegrationConfig(
query_endpoint="https://x",
username="u",
sources="t1_myapp, t2_gateway", # type: ignore[arg-type]
)
assert cfg.sources == ["t1_myapp", "t2_gateway"]
def test_sentry_config_rejects_unknown_fields_with_suggestion() -> None:
with pytest.raises(ValidationError, match="organiztion_slug.*organization_slug"):
build_sentry_config(
{
"base_url": "https://sentry.io",
"organiztion_slug": "demo-org",
"auth_token": "sntrys_test",
}
)
def test_github_mcp_config_rejects_unknown_fields_with_suggestion() -> None:
with pytest.raises(ValidationError, match="toolset.*toolsets"):
build_github_mcp_config(
{
"url": "https://api.githubcopilot.com/mcp/",
"mode": "streamable-http",
"auth_token": "ghp_test",
"toolset": ["repos"],
}
)
def test_github_mcp_stdio_requires_command() -> None:
with pytest.raises(ValidationError, match="requires a non-empty command"):
build_github_mcp_config({"mode": "stdio"})
def test_github_mcp_remote_request_headers_include_x_mcp_toolsets() -> None:
"""Explicit Copilot MCP paths use X-MCP-Toolsets to merge toolsets (remote-server.md)."""
cfg = build_github_mcp_config(
{
"url": "https://api.githubcopilot.com/mcp/x/issues",
"mode": "streamable-http",
"auth_token": "ghp_test",
"toolsets": ["repos", "issues"],
}
)
assert cfg.request_headers["X-MCP-Toolsets"] == "repos,issues"
def test_github_mcp_generic_copilot_root_omits_x_mcp_toolsets() -> None:
"""Generic /mcp uses rewritten /x/all/readonly; subset header would hide search tools."""
cfg = build_github_mcp_config(
{
"url": "https://api.githubcopilot.com/mcp/",
"mode": "streamable-http",
"auth_token": "ghp_test",
"toolsets": ["repos", "issues"],
}
)
assert "X-MCP-Toolsets" not in cfg.request_headers
def test_github_mcp_stdio_omits_x_mcp_toolsets_header() -> None:
cfg = build_github_mcp_config(
{
"mode": "stdio",
"command": "github-mcp-server",
"toolsets": ["repos"],
}
)
assert "X-MCP-Toolsets" not in cfg.request_headers
def test_remote_github_mcp_root_url_rewrites_to_x_all_readonly() -> None:
assert (
_remote_github_mcp_session_url("https://api.githubcopilot.com/mcp/")
== "https://api.githubcopilot.com/mcp/x/all/readonly"
)
assert (
_remote_github_mcp_session_url("https://api.githubcopilot.com/mcp")
== "https://api.githubcopilot.com/mcp/x/all/readonly"
)
def test_remote_github_mcp_explicit_paths_not_rewritten() -> None:
url = "https://api.githubcopilot.com/mcp/x/repos"
assert _remote_github_mcp_session_url(url) == url
assert _remote_github_mcp_session_url("https://api.githubcopilot.com/mcp/readonly") == (
"https://api.githubcopilot.com/mcp/readonly"
)
def test_remote_github_mcp_other_hosts_unchanged() -> None:
url = "https://example.com/mcp/"
assert _remote_github_mcp_session_url(url) == url
def test_github_mcp_custom_headers_can_override_x_mcp_toolsets() -> None:
cfg = build_github_mcp_config(
{
"url": "https://api.githubcopilot.com/mcp/",
"mode": "streamable-http",
"toolsets": ["repos"],
"headers": {"X-MCP-Toolsets": "repos,pull_requests"},
}
)
assert cfg.request_headers["X-MCP-Toolsets"] == "repos,pull_requests"
def test_datadog_config_rejects_unknown_fields_with_suggestion() -> None:
with pytest.raises(ValidationError, match="siet.*site"):
DatadogConfig.model_validate(
{
"api_key": "dd-api",
"app_key": "dd-app",
"siet": "datadoghq.com",
}
)
def test_honeycomb_config_rejects_unknown_fields_with_suggestion() -> None:
with pytest.raises(ValidationError, match="datset.*dataset"):
HoneycombIntegrationConfig.model_validate(
{
"api_key": "hny_test",
"datset": "prod-api",
}
)
def test_coralogix_config_rejects_unknown_fields_with_suggestion() -> None:
with pytest.raises(ValidationError, match="base_ul.*base_url"):
CoralogixIntegrationConfig.model_validate(
{
"api_key": "cx_test",
"base_ul": "https://api.coralogix.com",
}
)
def test_snowflake_config_accepts_schema_without_reserved_field() -> None:
cfg = SnowflakeIntegrationConfig.model_validate(
{
"account_identifier": "xy12345.us-east-1",
"token": "sf-token",
"schema": " PUBLIC ",
}
)
assert cfg.db_schema == "PUBLIC"
assert "schema" not in SnowflakeIntegrationConfig.model_fields
def test_snowflake_classifier_preserves_schema_source_key() -> None:
config, service = classify_snowflake(
{
"account_identifier": "xy12345.us-east-1",
"token": "sf-token",
"schema": "PUBLIC",
},
"snowflake-prod",
)
assert service == "snowflake"
assert isinstance(config, dict)
assert config["schema"] == "PUBLIC"
assert "db_schema" not in config
def test_grafana_config_rejects_unknown_fields_with_suggestion() -> None:
with pytest.raises(ValidationError, match="instnce_url.*instance_url"):
GrafanaAccountConfig.model_validate(
{
"account_id": "grafana-1",
"instance_url": "https://grafana.example.com",
"read_token": "token",
"instnce_url": "https://grafana.example.com",
}
)
def test_aws_config_requires_auth_method() -> None:
with pytest.raises(ValidationError, match="requires either role_arn or credentials"):
AWSIntegrationConfig.model_validate({"region": "us-east-1"})
def test_slack_config_rejects_non_slack_host() -> None:
with pytest.raises(ValidationError, match="Slack webhook host must be a Slack domain"):
SlackWebhookConfig.model_validate({"webhook_url": "https://example.com/webhook"})
@pytest.mark.parametrize(
"webhook_url",
[
"https://hooks.slack.com.evil.test/services/T000/B000/test",
"https://evilslack.com/services/T000/B000/test",
"https://hooks.slack.com@evil.test/services/T000/B000/test",
],
)
def test_slack_config_rejects_spoofed_slack_hosts(webhook_url: str) -> None:
with pytest.raises(ValidationError, match="Slack webhook host must be a Slack domain"):
SlackWebhookConfig.model_validate({"webhook_url": webhook_url})
def test_tracer_config_strips_bearer_prefix() -> None:
config = TracerIntegrationConfig.model_validate(
{
"base_url": "https://app.tracer.cloud",
"jwt_token": "Bearer test-token",
}
)
assert config.jwt_token == "test-token"
def test_posthog_config_rejects_unknown_fields_with_suggestion() -> None:
from integrations.posthog import build_posthog_config
with pytest.raises(ValidationError, match="proejct_id.*project_id"):
build_posthog_config(
{
"personal_api_key": "phx_test",
"proejct_id": "12345",
}
)