Files
wehub-resource-sync 0ef5fcb1c5
Security / Dependency audit (pip-audit) (push) Has been cancelled
Security / CodeQL (javascript-typescript) (push) Has been cancelled
Security / CodeQL (python) (push) Has been cancelled
Security / Secret scan (gitleaks) (push) Has been cancelled
rust / test (ubuntu) (push) Has been cancelled
rust / simulator e2e (macos-latest) (push) Has been cancelled
rust / simulator e2e (ubuntu-latest) (push) Has been cancelled
rust / simulator e2e (windows-latest) (push) Has been cancelled
rust / wheels (aarch64-apple-darwin) (push) Has been cancelled
rust / wheels (x86_64-unknown-linux-gnu) (push) Has been cancelled
rust / wheels (x86_64-apple-darwin) (push) Has been cancelled
rust / audit (push) Has been cancelled
rust / parity (nightly, allowed to fail during Phase 0) (push) Has been cancelled
CI / commitlint (push) Has been skipped
Dev Containers / validate (.devcontainer/devcontainer.json, default) (push) Failing after 0s
Dev Containers / validate (.devcontainer/memory-stack/devcontainer.json, memory-stack) (push) Failing after 0s
Dev Containers / validate-worktree (push) Failing after 0s
CI / changes (push) Failing after 4s
Deploy Documentation / validate (push) Has been skipped
Deploy Documentation / deploy (push) Failing after 1s
Init Native E2E / init-native (ubuntu-latest, claude) (push) Failing after 1s
Init Native E2E / init-native (ubuntu-latest, codex) (push) Failing after 1s
Install Native E2E / install-native (ubuntu-latest) (push) Failing after 1s
OpenCode Plugin / typecheck + build + test (push) Failing after 1s
Init Native E2E / init-native (ubuntu-latest, copilot) (push) Failing after 1s
Release Please / release-please (push) Failing after 1s
Wrap E2E / docker-wrap-e2e (push) Failing after 1s
Wrap Native E2E / wrap-native (ubuntu-latest) (push) Failing after 1s
Init E2E / docker-init-e2e (push) Failing after 4s
Merge Conflicts / merge-conflicts (push) Failing after 4s
CI / lint (push) Has been cancelled
CI / build-wheel (push) Has been cancelled
CI / build-wheel-windows (push) Has been cancelled
CI / prefetch-model (push) Has been cancelled
CI / test-dashboard-ui (push) Has been cancelled
CI / test (1) (push) Has been cancelled
CI / test (2) (push) Has been cancelled
CI / test (3) (push) Has been cancelled
CI / test (4) (push) Has been cancelled
CI / test-extras (push) Has been cancelled
CI / test-agno (push) Has been cancelled
CI / build (push) Has been cancelled
CI / workflow-validation (push) Has been cancelled
CI / docker-native-e2e (push) Has been cancelled
CI / windows-native-wrapper (push) Has been cancelled
CI / macos-native-wrapper (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code-nonroot name:code-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code-slim name:code-slim]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code-slim-nonroot name:code-slim-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-nonroot name:nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-slim name:slim]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-slim-nonroot name:slim-nonroot]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime name:]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-code name:code]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-code-nonroot name:code-nonroot]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-code-slim name:code-slim]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-code-slim-nonroot name:code-slim-nonroot]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-nonroot name:nonroot]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-slim name:slim]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-slim-nonroot name:slim-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime name:]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code name:code]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code-nonroot name:code-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code-slim name:code-slim]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code-slim-nonroot name:code-slim-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-nonroot name:nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-slim name:slim]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-slim-nonroot name:slim-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime name:]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code name:code]) (push) Has been cancelled
Docker / promote-latest (push) Has been cancelled
Init Native E2E / init-native (macos-latest, claude) (push) Has been cancelled
Init Native E2E / init-native (macos-latest, codex) (push) Has been cancelled
Init Native E2E / init-native (macos-latest, copilot) (push) Has been cancelled
Install Native E2E / install-native (macos-latest) (push) Has been cancelled
Wrap Native E2E / wrap-native (macos-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:03:20 +08:00

190 lines
6.4 KiB
Python

from __future__ import annotations
import click
import pytest
from headroom.install.models import ConfigScope, InstallPreset, ProviderSelectionMode, ToolTarget
from headroom.install.planner import PROVIDER_SCOPE_TARGETS, build_manifest, resolve_targets
def test_resolve_targets_auto_falls_back_when_detection_empty(monkeypatch) -> None:
monkeypatch.setattr("headroom.install.planner.detect_targets", lambda: [])
targets = resolve_targets(ProviderSelectionMode.AUTO.value, [])
assert targets == [
ToolTarget.CLAUDE.value,
ToolTarget.CODEX.value,
ToolTarget.COPILOT.value,
]
def test_build_manifest_for_persistent_docker_sets_expected_defaults() -> None:
manifest = build_manifest(
profile="default",
preset=InstallPreset.PERSISTENT_DOCKER.value,
runtime_kind="docker",
scope="user",
provider_mode="manual",
targets=["claude", "copilot"],
port=8787,
backend="anthropic",
anyllm_provider=None,
region=None,
proxy_mode="token",
memory_enabled=True,
telemetry_enabled=False,
image="ghcr.io/chopratejas/headroom:latest",
)
assert manifest.supervisor_kind == "none"
assert manifest.runtime_kind == "docker"
assert manifest.health_url == "http://127.0.0.1:8787/readyz"
assert manifest.base_env["HEADROOM_PORT"] == "8787"
assert manifest.base_env["HEADROOM_TELEMETRY"] == "off"
assert "--no-telemetry" in manifest.proxy_args
assert manifest.tool_envs["claude"]["ANTHROPIC_BASE_URL"] == "http://127.0.0.1:8787"
assert manifest.tool_envs["copilot"]["COPILOT_PROVIDER_TYPE"] == "anthropic"
assert "--memory" in manifest.proxy_args
def test_build_manifest_uses_provider_slice_env_builders_for_all_supported_targets() -> None:
manifest = build_manifest(
profile="default",
preset=InstallPreset.PERSISTENT_SERVICE.value,
runtime_kind="python",
scope="user",
provider_mode="manual",
targets=["claude", "copilot", "codex", "aider", "cursor"],
port=9999,
backend="anyllm",
anyllm_provider="groq",
region=None,
proxy_mode="token",
memory_enabled=False,
telemetry_enabled=True,
image="ghcr.io/chopratejas/headroom:latest",
)
# telemetry_enabled=True must write the explicit opt-in value + flag.
assert manifest.base_env["HEADROOM_TELEMETRY"] == "on"
assert "--telemetry" in manifest.proxy_args
assert manifest.tool_envs["claude"]["ANTHROPIC_BASE_URL"] == "http://127.0.0.1:9999"
assert manifest.tool_envs["codex"]["OPENAI_BASE_URL"] == "http://127.0.0.1:9999/v1"
assert manifest.tool_envs["aider"] == {
"OPENAI_API_BASE": "http://127.0.0.1:9999/v1",
"ANTHROPIC_BASE_URL": "http://127.0.0.1:9999",
}
assert manifest.tool_envs["cursor"] == {
"OPENAI_BASE_URL": "http://127.0.0.1:9999/v1",
"ANTHROPIC_BASE_URL": "http://127.0.0.1:9999",
}
assert manifest.tool_envs["copilot"] == {
"COPILOT_PROVIDER_TYPE": "openai",
"COPILOT_PROVIDER_BASE_URL": "http://127.0.0.1:9999/v1",
"COPILOT_PROVIDER_WIRE_API": "completions",
}
def test_resolve_targets_provider_scope_auto_excludes_copilot(monkeypatch) -> None:
monkeypatch.setattr("headroom.install.planner.detect_targets", lambda: [])
targets = resolve_targets(
ProviderSelectionMode.AUTO.value,
[],
scope=ConfigScope.PROVIDER.value,
)
assert targets == [ToolTarget.CLAUDE.value, ToolTarget.CODEX.value]
def test_resolve_targets_manual_dedupes_and_filters_invalid() -> None:
targets = resolve_targets(
ProviderSelectionMode.MANUAL.value,
["claude", "copilot", "claude", "invalid"],
)
assert targets == [ToolTarget.CLAUDE.value, ToolTarget.COPILOT.value]
def test_build_manifest_omits_no_http2_by_default() -> None:
manifest = build_manifest(
profile="default",
preset=InstallPreset.PERSISTENT_SERVICE.value,
runtime_kind="python",
scope="user",
provider_mode="manual",
targets=["claude"],
port=8787,
backend="anthropic",
anyllm_provider=None,
region=None,
proxy_mode="token",
memory_enabled=False,
telemetry_enabled=True,
image="ghcr.io/chopratejas/headroom:latest",
)
assert "--no-http2" not in manifest.proxy_args
def test_build_manifest_persists_no_http2_override() -> None:
manifest = build_manifest(
profile="default",
preset=InstallPreset.PERSISTENT_SERVICE.value,
runtime_kind="python",
scope="user",
provider_mode="manual",
targets=["claude"],
port=8787,
backend="anthropic",
anyllm_provider=None,
region=None,
proxy_mode="token",
memory_enabled=False,
telemetry_enabled=True,
image="ghcr.io/chopratejas/headroom:latest",
no_http2=True,
)
assert manifest.proxy_args.count("--no-http2") == 1
assert "HEADROOM_HTTP2" not in manifest.base_env
def test_resolve_targets_provider_scope_all_ignores_unsupported_requested() -> None:
"""`all` mode never consults the requested list, so an unsupported entry
like `cursor` must not make it raise — it should return the full provider
target set (regression: this used to raise a ClickException)."""
targets = resolve_targets(
ProviderSelectionMode.ALL.value,
["cursor"],
scope=ConfigScope.PROVIDER.value,
)
assert targets == [t.value for t in PROVIDER_SCOPE_TARGETS]
def test_resolve_targets_provider_scope_auto_ignores_unsupported_requested(monkeypatch) -> None:
"""`auto` mode also ignores the requested list, so an unsupported entry
must not raise."""
monkeypatch.setattr("headroom.install.planner.detect_targets", lambda: [])
targets = resolve_targets(
ProviderSelectionMode.AUTO.value,
["cursor"],
scope=ConfigScope.PROVIDER.value,
)
assert targets == [ToolTarget.CLAUDE.value, ToolTarget.CODEX.value]
def test_resolve_targets_provider_scope_manual_rejects_unsupported() -> None:
"""The manual path DOES consult the requested list, so an unsupported
target under provider scope must still be rejected."""
with pytest.raises(click.ClickException, match="cursor"):
resolve_targets(
ProviderSelectionMode.MANUAL.value,
["cursor"],
scope=ConfigScope.PROVIDER.value,
)