"""The trust dial's hard wall, on a real Gitea (D4, D5; M3.3): with the protection a `merge: approved` project has, the agent's own token can't merge its PR until an operator approves the PR as it is now; it can then; and a commit pushed after the approval needs approving again.""" import base64 import uuid from pathlib import Path import pytest from e2e_support import fresh_repo, operator_gitea from nisse_core.gitea import GiteaClient, GiteaError from nisse_dev.config import AgentConfig pytestmark = pytest.mark.integration def add_file(gitea: GiteaClient, repo: str, branch: str, path: str) -> None: gitea._request( "POST", f"/repos/{repo}/contents/{path}", json={ "content": base64.b64encode(f"{path}\n".encode()).decode(), "message": f"add {path}", "branch": branch, }, ) def approve(operator: GiteaClient, repo: str, pr: int) -> None: operator._request( "POST", f"/repos/{repo}/pulls/{pr}/reviews", json={"event": "APPROVED"} ) def test_merging_needs_the_operators_approval_of_the_pr_as_it_is( tmp_path: Path, live_config: AgentConfig, gitea: GiteaClient ) -> None: operator = operator_gitea(live_config.gitea_url) run = uuid.uuid4().hex[:8] with fresh_repo(operator, run, tmp_path / "keys", agent=gitea.whoami()) as repo: name = repo.name # The agent's PR, its branch made through the API. gitea.branch_with_file( name, base="main", branch="m-1", path="a.txt", text="a\n", message="a" ) pr = gitea.open_pull_request(name, head="m-1", base="main", title="a", body="") with pytest.raises(GiteaError): gitea.merge_pull_request(name, pr.number) # no approval yet approve(operator, name, pr.number) [approval] = gitea.approvals(name, pr.number) head = gitea.pull_request(name, pr.number).head_sha assert (approval.author, approval.commit) == (operator.whoami(), head) gitea.merge_pull_request(name, pr.number) # approved: the agent may assert gitea.pull_request(name, pr.number).merged # Approved, then changed: the approval no longer stands. gitea.branch_with_file( name, base="main", branch="m-2", path="b.txt", text="b\n", message="b" ) second = gitea.open_pull_request( name, head="m-2", base="main", title="b", body="" ) approve(operator, name, second.number) add_file(gitea, name, "m-2", "c.txt") # a fix pushed after the approval after = gitea.pull_request(name, second.number).head_sha assert not [ a for a in gitea.approvals(name, second.number) if a.commit == after and not a.stale ] with pytest.raises(GiteaError): gitea.merge_pull_request(name, second.number)