open-swe/tests/test_github_app.py
Johannes du Plessis 0a2e682364
fix: scope public reviewer tokens (#1389)
* fix: scope public reviewer tokens

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>

* refactor: simplify reviewer token wiring; fix push re-scope + red test

- Remove the redundant _check_or_recreate_sandbox_for_proxy /
  _refresh_github_proxy_or_recreate_for_proxy wrappers and call the
  underlying functions directly (they already default the token to None).
- process_github_push_event: re-scope the GitHub App token when the push
  payload lacked repo privacy/id but PR metadata reveals a public repo, so
  reviewer.py never proxies a full-installation token for a public PR.
- Clarify the two-token sequence in trigger_pr_review_from_ref.
- Fix pre-existing failing test test_proxy_refresh_failure_recreates_sandbox
  and add coverage for _reviewer_token_for_repo + push-event scoping.

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-06-03 09:25:17 -07:00

65 lines
2.1 KiB
Python

from __future__ import annotations
from typing import Any
import pytest
from agent.utils import github_app
class _FakeResponse:
def raise_for_status(self) -> None:
pass
def json(self) -> dict[str, str]:
return {"token": "token", "expires_at": "expires"}
class _FakeAsyncClient:
last_post: dict[str, Any] | None = None
async def __aenter__(self) -> _FakeAsyncClient:
return self
async def __aexit__(self, exc_type: object, exc: object, tb: object) -> None:
return None
async def post(self, url: str, **kwargs: Any) -> _FakeResponse:
type(self).last_post = {"url": url, **kwargs}
return _FakeResponse()
@pytest.mark.asyncio
async def test_installation_token_can_be_scoped_to_repository_ids(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(github_app, "GITHUB_APP_ID", "1")
monkeypatch.setattr(github_app, "GITHUB_APP_PRIVATE_KEY", "key")
monkeypatch.setattr(github_app, "GITHUB_APP_INSTALLATION_ID", "2")
monkeypatch.setattr(github_app, "_generate_app_jwt", lambda: "jwt")
monkeypatch.setattr(github_app.httpx, "AsyncClient", _FakeAsyncClient)
token, expires_at = await github_app.get_github_app_installation_token_with_expiry(
repository_ids=[123]
)
assert token == "token"
assert expires_at == "expires"
assert _FakeAsyncClient.last_post is not None
assert _FakeAsyncClient.last_post["json"] == {"repository_ids": [123]}
@pytest.mark.asyncio
async def test_installation_token_omits_scope_for_full_installation(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(github_app, "GITHUB_APP_ID", "1")
monkeypatch.setattr(github_app, "GITHUB_APP_PRIVATE_KEY", "key")
monkeypatch.setattr(github_app, "GITHUB_APP_INSTALLATION_ID", "2")
monkeypatch.setattr(github_app, "_generate_app_jwt", lambda: "jwt")
monkeypatch.setattr(github_app.httpx, "AsyncClient", _FakeAsyncClient)
await github_app.get_github_app_installation_token_with_expiry()
assert _FakeAsyncClient.last_post is not None
assert _FakeAsyncClient.last_post["json"] is None