feat: complete PR creation via GiteaClient in commit_and_open_pr and open_pr
This commit is contained in:
parent
af7bd2cdc3
commit
816415dd24
@ -16,6 +16,7 @@ from langchain.agents.middleware import AgentState, after_agent
|
||||
from langgraph.config import get_config
|
||||
from langgraph.runtime import Runtime
|
||||
|
||||
from ..utils.gitea_client import get_gitea_client
|
||||
from ..utils.git_utils import (
|
||||
git_add_all,
|
||||
git_checkout_branch,
|
||||
@ -135,8 +136,21 @@ async def open_pr_if_needed(
|
||||
git_push, sandbox_backend, repo_dir, target_branch, gitea_token
|
||||
)
|
||||
|
||||
# TODO: Phase 2 - use GiteaClient to create PR via Gitea API
|
||||
logger.info("Pushed to branch %s, PR creation pending Gitea integration", target_branch)
|
||||
# --- PR 생성 (GiteaClient) ---
|
||||
default_branch = os.environ.get("DEFAULT_BRANCH", "main")
|
||||
client = get_gitea_client()
|
||||
try:
|
||||
pr_result = await client.create_pull_request(
|
||||
owner=repo_owner,
|
||||
repo=repo_name,
|
||||
title=pr_title,
|
||||
head=target_branch,
|
||||
base=default_branch,
|
||||
body=pr_body,
|
||||
)
|
||||
logger.info("Safety net PR created: %s", pr_result.get("html_url"))
|
||||
except Exception:
|
||||
logger.exception("Safety net PR creation failed (changes were pushed)")
|
||||
|
||||
logger.info("After-agent middleware completed successfully")
|
||||
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
from langgraph.config import get_config
|
||||
|
||||
from agent.utils.gitea_client import get_gitea_client
|
||||
|
||||
from ..utils.git_utils import (
|
||||
git_add_all,
|
||||
git_checkout_branch,
|
||||
@ -95,7 +98,6 @@ def commit_and_open_pr(
|
||||
"pr_url": None,
|
||||
}
|
||||
|
||||
import os
|
||||
gitea_token = os.environ.get("GITEA_TOKEN", "")
|
||||
if not gitea_token:
|
||||
logger.error("commit_and_open_pr missing Gitea token for thread %s", thread_id)
|
||||
@ -113,8 +115,39 @@ def commit_and_open_pr(
|
||||
"pr_url": None,
|
||||
}
|
||||
|
||||
# TODO: Phase 2 - use GiteaClient to create PR
|
||||
return {"success": True, "pr_url": "pending-gitea-implementation"}
|
||||
# --- PR 생성 (GiteaClient) ---
|
||||
gitea_external_url = os.environ.get("GITEA_EXTERNAL_URL", "")
|
||||
gitea_internal_url = os.environ.get("GITEA_URL", "http://gitea:3000")
|
||||
default_branch = os.environ.get("DEFAULT_BRANCH", "main")
|
||||
client = get_gitea_client()
|
||||
|
||||
try:
|
||||
pr_result = asyncio.run(
|
||||
client.create_pull_request(
|
||||
owner=repo_owner,
|
||||
repo=repo_name,
|
||||
title=title,
|
||||
head=target_branch,
|
||||
base=default_branch,
|
||||
body=body,
|
||||
)
|
||||
)
|
||||
pr_url = pr_result.get("html_url", "")
|
||||
if gitea_external_url and pr_url:
|
||||
pr_url = pr_url.replace(gitea_internal_url, gitea_external_url)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"pr_url": pr_url,
|
||||
"pr_number": pr_result.get("number"),
|
||||
}
|
||||
except Exception as e:
|
||||
logger.exception("Failed to create PR (push succeeded)")
|
||||
return {
|
||||
"success": True,
|
||||
"pr_url": "",
|
||||
"error": f"Push succeeded but PR creation failed: {e}",
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.exception("commit_and_open_pr failed")
|
||||
|
||||
129
tests/test_commit_and_open_pr.py
Normal file
129
tests/test_commit_and_open_pr.py
Normal file
@ -0,0 +1,129 @@
|
||||
import pytest
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
|
||||
def test_pr_creation_after_push():
|
||||
"""push 성공 후 GiteaClient로 PR을 생성한다."""
|
||||
mock_gitea = MagicMock()
|
||||
mock_gitea.create_pull_request = AsyncMock(
|
||||
return_value={
|
||||
"number": 1,
|
||||
"html_url": "http://gitea:3000/quant/galaxis-po/pulls/1",
|
||||
}
|
||||
)
|
||||
mock_sandbox = MagicMock()
|
||||
mock_result = MagicMock(exit_code=0, output="")
|
||||
|
||||
with patch(
|
||||
"agent.tools.commit_and_open_pr.get_gitea_client", return_value=mock_gitea
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.get_sandbox_backend_sync",
|
||||
return_value=mock_sandbox,
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.get_config",
|
||||
return_value={
|
||||
"configurable": {
|
||||
"thread_id": "test-thread",
|
||||
"repo": {"owner": "quant", "name": "galaxis-po"},
|
||||
}
|
||||
},
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.resolve_repo_dir",
|
||||
return_value="/workspace/galaxis-po",
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_has_uncommitted_changes",
|
||||
return_value=True,
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_fetch_origin",
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_has_unpushed_commits",
|
||||
return_value=False,
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_current_branch",
|
||||
return_value="galaxis-agent/test-thread",
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_checkout_branch",
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_config_user",
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_add_all",
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_commit",
|
||||
return_value=mock_result,
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_push",
|
||||
return_value=mock_result,
|
||||
), patch.dict(
|
||||
"os.environ", {"GITEA_TOKEN": "test-token"},
|
||||
):
|
||||
from agent.tools.commit_and_open_pr import commit_and_open_pr
|
||||
result = commit_and_open_pr(title="feat: add feature", body="PR description")
|
||||
assert result["success"] is True
|
||||
assert "pulls/1" in result["pr_url"]
|
||||
mock_gitea.create_pull_request.assert_called_once()
|
||||
|
||||
|
||||
def test_pr_creation_converts_internal_to_external_url():
|
||||
"""PR URL이 내부 URL에서 외부 URL로 변환된다."""
|
||||
mock_gitea = MagicMock()
|
||||
mock_gitea.create_pull_request = AsyncMock(
|
||||
return_value={
|
||||
"number": 5,
|
||||
"html_url": "http://gitea:3000/quant/galaxis-po/pulls/5",
|
||||
}
|
||||
)
|
||||
mock_sandbox = MagicMock()
|
||||
mock_result = MagicMock(exit_code=0, output="")
|
||||
|
||||
with patch(
|
||||
"agent.tools.commit_and_open_pr.get_gitea_client", return_value=mock_gitea
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.get_sandbox_backend_sync",
|
||||
return_value=mock_sandbox,
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.get_config",
|
||||
return_value={
|
||||
"configurable": {
|
||||
"thread_id": "test-thread",
|
||||
"repo": {"owner": "quant", "name": "galaxis-po"},
|
||||
}
|
||||
},
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.resolve_repo_dir",
|
||||
return_value="/workspace/galaxis-po",
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_has_uncommitted_changes",
|
||||
return_value=True,
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_fetch_origin",
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_has_unpushed_commits",
|
||||
return_value=False,
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_current_branch",
|
||||
return_value="galaxis-agent/test-thread",
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_checkout_branch",
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_config_user",
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_add_all",
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_commit",
|
||||
return_value=mock_result,
|
||||
), patch(
|
||||
"agent.tools.commit_and_open_pr.git_push",
|
||||
return_value=mock_result,
|
||||
), patch.dict(
|
||||
"os.environ",
|
||||
{
|
||||
"GITEA_TOKEN": "test-token",
|
||||
"GITEA_EXTERNAL_URL": "https://ayuriel.duckdns.org",
|
||||
"GITEA_URL": "http://gitea:3000",
|
||||
},
|
||||
):
|
||||
from agent.tools.commit_and_open_pr import commit_and_open_pr
|
||||
result = commit_and_open_pr(title="feat: test", body="body")
|
||||
assert result["success"] is True
|
||||
assert "ayuriel.duckdns.org" in result["pr_url"]
|
||||
assert "gitea:3000" not in result["pr_url"]
|
||||
Loading…
x
Reference in New Issue
Block a user