Files
2026-09-04 14:58:42 +08:00

133 lines
4.6 KiBLFS
Python

from __future__ import annotations
import subprocess
import pytest
from skillsbench_agentbeats import ghcr_preflight as ghcr_preflight_module
from skillsbench_agentbeats.ghcr_preflight import (
active_account_scopes,
ensure_ghcr_package_scopes,
missing_ghcr_package_scopes,
run_gh_token_scope_status,
)
GH_AUTH_STATUS = """github.com
- Logged in to github.com account benchflow-bot (keyring)
- Active account: true
- Git operations protocol: https
- Token: gho_************************************
- Token scopes: 'gist', 'read:org', 'repo', 'workflow', 'read:packages', 'write:packages'
- Logged in to github.com account FayeZC (keyring)
- Active account: false
- Git operations protocol: https
- Token: gho_************************************
- Token scopes: 'gist', 'read:org', 'repo', 'workflow'
"""
def test_active_account_scopes_parses_only_active_account() -> None:
scopes = active_account_scopes(GH_AUTH_STATUS)
assert scopes == {"gist", "read:org", "repo", "workflow", "read:packages", "write:packages"}
def test_missing_ghcr_package_scopes_detects_required_package_scopes() -> None:
missing = missing_ghcr_package_scopes({"gist", "read:org", "repo", "workflow"})
assert missing == {"read:packages", "write:packages"}
def test_ensure_ghcr_package_scopes_accepts_complete_scope_set() -> None:
assert "write:packages" in ensure_ghcr_package_scopes(GH_AUTH_STATUS)
def test_ensure_ghcr_package_scopes_rejects_missing_package_scopes() -> None:
output = GH_AUTH_STATUS.replace(", 'read:packages', 'write:packages'", "")
with pytest.raises(ValueError, match="gh auth refresh"):
ensure_ghcr_package_scopes(output)
def test_active_account_scopes_rejects_missing_active_account() -> None:
with pytest.raises(ValueError, match="active GitHub account"):
active_account_scopes("github.com\n - no active account")
def test_run_gh_token_scope_status_reads_pat_from_environment(monkeypatch: pytest.MonkeyPatch) -> None:
seen: dict[str, object] = {}
def fake_run(
cmd: list[str],
*,
check: bool,
capture_output: bool,
text: bool,
env: dict[str, str] | None = None,
) -> subprocess.CompletedProcess[str]:
seen["cmd"] = cmd
seen["env"] = env
return subprocess.CompletedProcess(cmd, 0, stdout="x-oauth-scopes: repo, read:packages, write:packages\n", stderr="")
monkeypatch.setenv("GH_TOKEN", "github_pat_secret_value")
monkeypatch.setattr(ghcr_preflight_module.subprocess, "run", fake_run)
assert run_gh_token_scope_status() == {"repo", "read:packages", "write:packages"}
assert seen["cmd"] == ["gh", "api", "-i", "user"]
assert seen["env"]["GH_TOKEN"] == "github_pat_secret_value"
def test_run_gh_token_scope_status_prefers_gh_token_over_github_token(monkeypatch: pytest.MonkeyPatch) -> None:
seen_env: dict[str, str] = {}
def fake_run(
cmd: list[str],
*,
check: bool,
capture_output: bool,
text: bool,
env: dict[str, str] | None = None,
) -> subprocess.CompletedProcess[str]:
assert env is not None
seen_env.update(env)
return subprocess.CompletedProcess(cmd, 0, stdout="x-oauth-scopes: read:packages, write:packages\n", stderr="")
monkeypatch.setenv("GH_TOKEN", "gh_token_secret")
monkeypatch.setenv("GITHUB_TOKEN", "github_token_secret")
monkeypatch.setattr(ghcr_preflight_module.subprocess, "run", fake_run)
run_gh_token_scope_status()
assert seen_env["GH_TOKEN"] == "gh_token_secret"
assert "GITHUB_TOKEN" not in seen_env
def test_run_gh_token_scope_status_rejects_missing_env_token(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.delenv("GH_TOKEN", raising=False)
monkeypatch.delenv("GITHUB_TOKEN", raising=False)
with pytest.raises(ValueError, match="GH_TOKEN"):
run_gh_token_scope_status()
def test_run_gh_token_scope_status_redacts_token_on_error(monkeypatch: pytest.MonkeyPatch) -> None:
def fake_run(
cmd: list[str],
*,
check: bool,
capture_output: bool,
text: bool,
env: dict[str, str] | None = None,
) -> subprocess.CompletedProcess[str]:
return subprocess.CompletedProcess(cmd, 1, stdout="", stderr="bad github_pat_secret_value")
monkeypatch.setenv("GH_TOKEN", "github_pat_secret_value")
monkeypatch.setattr(ghcr_preflight_module.subprocess, "run", fake_run)
with pytest.raises(RuntimeError) as exc_info:
run_gh_token_scope_status()
assert "github_pat_secret_value" not in str(exc_info.value)
assert "[REDACTED_TOKEN]" in str(exc_info.value)