@@ -136,7 +136,8 @@ def cherry_pick_commits(commits, source, branch_name, repo_path=None):
repo_path))
-async def run_review_agent(mr_iid, branch_name, comments, remote, repo_path=None):
+async def run_review_agent(mr_iid, branch_name, comments, remote, target='master',
+ repo_path=None):
"""Run the Claude agent to handle MR comments
Args:
@@ -144,6 +145,7 @@ async def run_review_agent(mr_iid, branch_name, comments, remote, repo_path=None
branch_name (str): Source branch name
comments (list): List of comment dicts with 'author', 'body' keys
remote (str): Git remote name
+ target (str): Target branch for rebase operations
repo_path (str): Path to repository (defaults to current directory)
Returns:
@@ -182,7 +184,7 @@ Important:
- If a comment is unclear or cannot be addressed, note this in your report
- Local branch: {branch_name}-v2 (or -v3, -v4 etc.)
- Remote push: always to '{branch_name}' to update the existing MR
-- If rebasing is requested, use: git rebase --keep-empty <base>
+- If rebasing is requested, use: git rebase --keep-empty {remote}/{target}
This preserves empty merge commits which are important for tracking
"""
@@ -208,7 +210,8 @@ Important:
return False, '\n\n'.join(conversation_log)
-def handle_mr_comments(mr_iid, branch_name, comments, remote, repo_path=None):
+def handle_mr_comments(mr_iid, branch_name, comments, remote, target='master',
+ repo_path=None):
"""Synchronous wrapper for running the review agent
Args:
@@ -216,6 +219,7 @@ def handle_mr_comments(mr_iid, branch_name, comments, remote, repo_path=None):
branch_name (str): Source branch name
comments (list): List of comment dicts
remote (str): Git remote name
+ target (str): Target branch for rebase operations
repo_path (str): Path to repository (defaults to current directory)
Returns:
@@ -223,4 +227,4 @@ def handle_mr_comments(mr_iid, branch_name, comments, remote, repo_path=None):
conversation_log is the agent's output text
"""
return asyncio.run(run_review_agent(mr_iid, branch_name, comments, remote,
- repo_path))
+ target, repo_path))
@@ -648,7 +648,7 @@ def do_commit_source(args, dbs):
return 0
-def process_mr_reviews(remote, mrs, dbs):
+def process_mr_reviews(remote, mrs, dbs, target='master'):
"""Process review comments on open MRs
Checks each MR for unresolved comments and uses Claude agent to address
@@ -658,10 +658,15 @@ def process_mr_reviews(remote, mrs, dbs):
remote (str): Remote name
mrs (list): List of MR dicts from get_open_pickman_mrs()
dbs (Database): Database instance for tracking processed comments
+ target (str): Target branch for rebase operations
Returns:
int: Number of MRs with comments processed
"""
+ # Fetch to get latest remote state (needed for rebase)
+ tout.info(f'Fetching {remote}...')
+ run_git(['fetch', remote])
+
processed = 0
for merge_req in mrs:
@@ -692,6 +697,7 @@ def process_mr_reviews(remote, mrs, dbs):
merge_req.source_branch,
unresolved,
remote,
+ target,
)
if success:
@@ -911,13 +917,17 @@ def do_step(args, dbs):
tout.info(f" !{merge_req.iid}: {merge_req.title}")
# Process any review comments on open MRs
- process_mr_reviews(remote, mrs, dbs)
+ process_mr_reviews(remote, mrs, dbs, args.target)
tout.info('')
tout.info('Not creating new MR while others are pending')
return 0
# No pending MRs, run apply with push
+ # First fetch to get latest remote state
+ tout.info(f'Fetching {remote}...')
+ run_git(['fetch', remote])
+
tout.info('No pending pickman MRs, creating new one...')
args.push = True
args.branch = None # Let do_apply generate branch name
@@ -1900,13 +1900,14 @@ class TestProcessMrReviewsCommentTracking(unittest.TestCase):
resolved=False),
]
- with mock.patch.object(gitlab_api, 'get_mr_comments',
- return_value=comments):
- with mock.patch.object(agent, 'handle_mr_comments',
- return_value=(True, 'Done')) as mock_agent:
- with mock.patch.object(gitlab_api, 'update_mr_description'):
- with mock.patch.object(control, 'update_history_with_review'):
- control.process_mr_reviews('ci', mrs, dbs)
+ with mock.patch.object(control, 'run_git'):
+ with mock.patch.object(gitlab_api, 'get_mr_comments',
+ return_value=comments):
+ with mock.patch.object(agent, 'handle_mr_comments',
+ return_value=(True, 'Done')) as mock_agent:
+ with mock.patch.object(gitlab_api, 'update_mr_description'):
+ with mock.patch.object(control, 'update_history_with_review'):
+ control.process_mr_reviews('ci', mrs, dbs)
# Agent should only receive the new comment
call_args = mock_agent.call_args