fix(plan): clean up stale worktree branch before re-creating sandbox #10000

Closed
hamza.khyari wants to merge 1 commits from bugfix/sandbox-reexecute-cleanup into master
+68
View File
@@ -1345,6 +1345,70 @@ def _get_lifecycle_service():
return container.plan_lifecycle_service()
def _cleanup_stale_sandbox(repo_path: str, plan_id: str) -> None:
"""Remove a stale worktree branch and directory for a plan.
If a previous execute left behind a worktree branch
``cleveragents/plan-<plan_id>``, this function removes the worktree
directory and deletes the branch so that a fresh sandbox can be
created. Silently does nothing if no stale branch exists.
"""
import subprocess
branch_name = f"cleveragents/plan-{plan_id}"
# Check if the branch exists
check = subprocess.run(
["git", "rev-parse", "--verify", f"refs/heads/{branch_name}"],
cwd=repo_path,
capture_output=True,
check=False,
timeout=10,
)
if check.returncode != 0:
return # No stale branch — nothing to clean
# Find and remove the worktree directory
wt_list = subprocess.run(
["git", "worktree", "list", "--porcelain"],
cwd=repo_path,
capture_output=True,
text=True,
check=False,
timeout=10,
)
for wt_block in wt_list.stdout.split("\n\n"):
if f"branch refs/heads/{branch_name}" in wt_block:
for line in wt_block.splitlines():
if line.startswith("worktree "):
wt_path = line.split("worktree ", 1)[1]
subprocess.run(
["git", "worktree", "remove", "--force", wt_path],
cwd=repo_path,
capture_output=True,
check=False,
timeout=10,
)
# Delete the branch
subprocess.run(
["git", "branch", "-D", branch_name],
cwd=repo_path,
capture_output=True,
check=False,
timeout=10,
)
# Prune stale worktree references
subprocess.run(
["git", "worktree", "prune"],
cwd=repo_path,
capture_output=True,
check=False,
timeout=10,
)
def _create_sandbox_for_plan(
plan_id: str,
service: PlanLifecycleService,
@@ -1387,6 +1451,10 @@ def _create_sandbox_for_plan(
and resource.location
and os.path.isdir(os.path.join(resource.location, ".git"))
):
_cleanup_stale_sandbox(
resource.location,
plan_id,
)
sandbox = GitWorktreeSandbox(
resource_id=resource.resource_id,
original_path=resource.location,