Files
tracer-cloud--opensre/tests/cli/test_integrations_setup_github.py
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

274 lines
10 KiB
Python

"""Tests for legacy `opensre integrations setup github` flow."""
from __future__ import annotations
from unittest.mock import patch
import pytest
from click.testing import CliRunner
from integrations.cli import _setup_github, cmd_setup
from integrations.github.mcp import GitHubMCPValidationResult
from surfaces.cli.__main__ import cli
def _upsert_should_not_run(*_a: object, **_k: object) -> None:
raise AssertionError("upsert_integration should not be called when validation fails")
def _mock_confirm(monkeypatch: pytest.MonkeyPatch, *, advanced: bool) -> None:
"""Mock the advanced-settings confirm prompt at the top of ``_setup_github``."""
monkeypatch.setattr(
"integrations.cli.questionary.confirm",
lambda *_a, **_k: type("X", (), {"ask": lambda *_aa, **_kk: advanced})(),
)
def test_setup_github_prints_connected_and_saves_on_validation_success(
monkeypatch: pytest.MonkeyPatch,
capsys: pytest.CaptureFixture[str],
) -> None:
"""_setup_github validates before saving and prints identity + detail on success."""
answers = iter(["https://api.githubcopilot.com/mcp/", "repos,issues"])
def fake_p(_label: str, default: str = "", secret: bool = False) -> str:
return next(answers)
monkeypatch.setattr("integrations.cli._p", fake_p)
_mock_confirm(monkeypatch, advanced=True)
monkeypatch.setattr("integrations.cli._setup_github_auth_token", lambda _mode: "ghp_x")
monkeypatch.setattr("integrations.cli._prompt_github_repo_report_level", lambda: "full")
monkeypatch.setattr(
"integrations.cli.questionary.select",
lambda *_a, **_k: type("X", (), {"ask": lambda *_aa, **_kk: "auto"})(),
)
monkeypatch.setattr(
"integrations.github.mcp.validate_github_mcp_config",
lambda _c, **_kwargs: GitHubMCPValidationResult(
ok=True,
detail=(
"OK @devuser; repos=2; owners=Tracer-Cloud,acme; "
"examples=Tracer-Cloud/opensre,acme/demo; mcp_tools=9"
),
authenticated_user="devuser",
repo_access_count=2,
repo_access_scope_owners=("Tracer-Cloud", "acme"),
repo_access_samples=("Tracer-Cloud/opensre", "acme/demo"),
),
)
saved: list[tuple[str, dict]] = []
monkeypatch.setattr(
"integrations.cli.upsert_integration",
lambda service, entry: saved.append((service, entry)),
)
_setup_github()
out = capsys.readouterr().out
assert "Validating GitHub MCP integration" in out
assert "Configuration validation: succeeded" in out
assert "@devuser" in out
assert "Repositories returned" in out
assert "Tracer-Cloud/opensre" in out
assert saved == [
(
"github",
{
"credentials": {
"mode": "streamable-http",
"url": "https://api.githubcopilot.com/mcp/",
"auth_token": "ghp_x",
"toolsets": ["repos", "issues"],
"username": "devuser",
},
},
),
]
def test_setup_github_simple_path_uses_hosted_defaults(
monkeypatch: pytest.MonkeyPatch,
capsys: pytest.CaptureFixture[str],
) -> None:
"""Declining advanced settings saves hosted defaults without transport/URL prompts."""
def fake_p(_label: str, default: str = "", secret: bool = False) -> str:
raise AssertionError("simple path should not call _p")
def _no_level_prompt() -> str:
raise AssertionError("simple path should not prompt for repo detail level")
monkeypatch.setattr("integrations.cli._p", fake_p)
_mock_confirm(monkeypatch, advanced=False)
monkeypatch.setattr("integrations.cli._setup_github_auth_token", lambda _mode: "gho_browser")
monkeypatch.setattr("integrations.cli._prompt_github_repo_report_level", _no_level_prompt)
monkeypatch.setattr(
"integrations.github.mcp.validate_github_mcp_config",
lambda _c, **_kwargs: GitHubMCPValidationResult(
ok=True,
detail="OK @u; repos=2; owners=acme; examples=acme/a; mcp_tools=5",
authenticated_user="u",
repo_access_count=2,
repo_access_scope_owners=("acme",),
repo_access_samples=("acme/a", "acme/b"),
repo_access_probe_tool="list_starred_repositories",
),
)
saved: list[tuple[str, dict]] = []
monkeypatch.setattr(
"integrations.cli.upsert_integration",
lambda service, entry: saved.append((service, entry)),
)
_setup_github()
out = capsys.readouterr().out
assert out.count("Validating GitHub MCP integration") == 1
# Concise summary: no access-source / starred / repo enumeration noise.
assert "Access source" not in out
assert "Starred" not in out
assert saved == [
(
"github",
{
"credentials": {
"mode": "streamable-http",
"url": "https://api.githubcopilot.com/mcp/",
"auth_token": "gho_browser",
"toolsets": ["repos", "issues", "pull_requests", "actions", "search"],
"username": "u",
},
},
),
]
def test_setup_github_exits_without_save_on_validation_failure(
monkeypatch: pytest.MonkeyPatch,
capsys: pytest.CaptureFixture[str],
) -> None:
answers = iter(["https://api.githubcopilot.com/mcp/", "repos"])
def fake_p(_label: str, default: str = "", secret: bool = False) -> str:
return next(answers)
monkeypatch.setattr("integrations.cli._p", fake_p)
_mock_confirm(monkeypatch, advanced=True)
monkeypatch.setattr("integrations.cli._setup_github_auth_token", lambda _mode: "")
monkeypatch.setattr(
"integrations.cli.questionary.select",
lambda *_a, **_k: type("X", (), {"ask": lambda *_aa, **_kk: "auto"})(),
)
monkeypatch.setattr(
"integrations.github.mcp.validate_github_mcp_config",
lambda _c, **_kwargs: GitHubMCPValidationResult(
ok=False,
detail="GitHub MCP connected, but authentication failed: bad token",
failure_category="authentication",
),
)
monkeypatch.setattr("integrations.cli.upsert_integration", _upsert_should_not_run)
with pytest.raises(SystemExit) as exc:
_setup_github()
assert exc.value.code == 1
out = capsys.readouterr().out
assert "Configuration validation: failed" in out
assert "Failure type:" in out
assert "authentication failed" in out
def test_cmd_setup_github_skips_saved_line_on_validation_failure(
monkeypatch: pytest.MonkeyPatch,
capsys: pytest.CaptureFixture[str],
) -> None:
"""cmd_setup must not print success/saved after a failed GitHub validation."""
answers = iter(["https://api.githubcopilot.com/mcp/", "repos"])
def fake_p(_label: str, default: str = "", secret: bool = False) -> str:
return next(answers)
monkeypatch.setattr("integrations.cli._p", fake_p)
_mock_confirm(monkeypatch, advanced=True)
monkeypatch.setattr("integrations.cli._setup_github_auth_token", lambda _mode: "x")
monkeypatch.setattr(
"integrations.cli.questionary.select",
lambda *_a, **_k: type("X", (), {"ask": lambda *_aa, **_kk: "auto"})(),
)
monkeypatch.setattr(
"integrations.github.mcp.validate_github_mcp_config",
lambda _c, **_kwargs: GitHubMCPValidationResult(
ok=False,
detail="validation failed for test",
failure_category="connectivity",
),
)
monkeypatch.setattr("integrations.cli.upsert_integration", _upsert_should_not_run)
with pytest.raises(SystemExit) as exc:
cmd_setup("github")
assert exc.value.code == 1
out = capsys.readouterr().out
assert "Configuration validation: failed" in out
assert "Saved" not in out
def test_cmd_setup_github_prints_saved_after_success(
monkeypatch: pytest.MonkeyPatch,
capsys: pytest.CaptureFixture[str],
) -> None:
"""Full cmd_setup('github') prints validation, Saved line, and does not duplicate handlers."""
answers = iter(["https://api.githubcopilot.com/mcp/", "repos"])
def fake_p(_label: str, default: str = "", secret: bool = False) -> str:
return next(answers)
monkeypatch.setattr("integrations.cli._p", fake_p)
_mock_confirm(monkeypatch, advanced=True)
monkeypatch.setattr("integrations.cli._setup_github_auth_token", lambda _mode: "tok")
monkeypatch.setattr("integrations.cli._prompt_github_repo_report_level", lambda: "standard")
monkeypatch.setattr(
"integrations.cli.questionary.select",
lambda *_a, **_k: type("X", (), {"ask": lambda *_aa, **_kk: "auto"})(),
)
monkeypatch.setattr(
"integrations.github.mcp.validate_github_mcp_config",
lambda _c, **_kwargs: GitHubMCPValidationResult(
ok=True,
detail="OK @u; repos=0; owners=-; examples=-; mcp_tools=5",
authenticated_user="u",
repo_access_count=0,
repo_access_scope_owners=(),
repo_access_samples=(),
),
)
monkeypatch.setattr("integrations.cli.upsert_integration", lambda *_a, **_k: None)
cmd_setup("github")
out = capsys.readouterr().out
assert "Configuration validation: succeeded" in out
assert "@u" in out
assert "Saved" in out
def test_integrations_setup_github_cli_invokes_cmd_setup() -> None:
runner = CliRunner()
with (
patch("surfaces.cli.commands.integrations.capture_integration_setup_started"),
patch("surfaces.cli.commands.integrations.capture_integration_setup_completed"),
patch("surfaces.cli.commands.integrations.capture_integration_verified"),
patch("integrations.cli.cmd_setup") as mock_cmd,
patch("integrations.cli.cmd_verify", return_value=0),
):
mock_cmd.return_value = "github"
result = runner.invoke(cli, ["integrations", "setup", "github"])
assert result.exit_code == 0
mock_cmd.assert_called_once_with("github")