Files
nisse/tests/integration/test_gitea_live.py
T
dongarandClaude Opus 5.5 c931ac939b
CI / checks (push) Skipped
CI / checks (pull_request) Failing after 56s
Let pushes go by an HTTPS token or an SSH deploy key
The push credential is either a push-only account's token, handed to git
through a credential helper that names environment variables, never
values, or a deploy key in a short-lived ssh-agent. The remote URL
follows the credential. Configured as gitea.push_user and push_token, or
gitea.push_key.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-10-02 21:59:56 +00:00

98 lines
3.4 KiB
Python

"""Live Gitea round trip against the sandbox repo: push a branch, open a PR,
comment, and prove the L8 reconciler reads external truth correctly.
Cleans up after itself (closes the PR, deletes the branch) so repeated runs
do not silt up the sandbox.
"""
import uuid
from pathlib import Path
import pytest
from nisse_dev.agent import push_credential, remote_url
from nisse_dev.config import AgentConfig
from nisse_dev.execution import SSHHost
from nisse_dev.git import GitError, GitRepo
from nisse_dev.gitea import GiteaClient, pull_request_reconciler
from nisse_dev.state import Intent
pytestmark = pytest.mark.integration
def intent_for(branch: str) -> Intent:
return Intent(
id=1,
kind="open_pr",
payload={"branch": branch},
status="pending",
created_at="t",
resolved_at=None,
)
def test_push_open_pr_and_reconcile(
tmp_path: Path, live_config: AgentConfig, gitea: GiteaClient, ssh_host: SSHHost
) -> None:
repo_path = live_config.gitea_repo # the sandbox
client = gitea
account = client.whoami()
assert "testing" in account, (
f"live tests must run as a testing account, not {account}"
)
branch = f"live-test-{uuid.uuid4().hex[:8]}"
reconcile = pull_request_reconciler(client, repo_path)
# Before the PR exists, external truth says the effect has not happened.
assert reconcile(intent_for(branch)) is False
# Pushed the way the agent does: from the build VM (here the throwaway
# sshd), with the push credential the config names, never the API token.
key = push_credential(live_config)
assert key is not None, "nisse-test.yaml names no push credential (D4)"
url = remote_url(client, repo_path, key)
repo = GitRepo(ssh_host, tmp_path / "work", known_hosts=str(tmp_path / "kh"))
repo.init()
repo.configure_identity(account, f"{account}@example.test")
(repo.root / f"{branch}.txt").write_text("live test artifact\n")
assert repo.commit_all("Live test commit") is not None
pr = None
try:
repo.push(url, branch, credential=key)
pr = client.open_pull_request(
repo_path,
head=branch,
base="main",
title=f"live test {branch}",
body="Opened by the nisse-dev live test suite.",
)
assert pr.head == branch
client.post_comment(repo_path, pr.number, "live test comment")
bodies = [c.body for c in client.list_comments(repo_path, pr.number)]
assert "live test comment" in bodies
# Now the same reconciler must see the effect and refuse to repeat it.
assert reconcile(intent_for(branch)) is True
# D4 is only real if the server enforces it. The agent's own token
# must not be able to merge the PR it just opened, and its push credential
# must not be able to push to the protected default branch at all.
merged = client._http.post(
f"/repos/{repo_path}/pulls/{pr.number}/merge", json={"Do": "merge"}
)
assert merged.status_code >= 400, (
"the agent merged its own PR: branch protection is not enforcing "
"the human gate"
)
with pytest.raises(GitError):
repo.push(url, "main", credential=key)
finally:
if pr is not None:
client.close_pull_request(repo_path, pr.number)
repo.delete_remote_branch(url, branch, credential=key)
client.close()