fix: clone workspace into repo-named subdirectory directly

Git clone with an explicit destination puts the working copy directly into
that directory; it does not create a repo-named subdirectory. The previous
change assumed the opposite, so workspaces ended up at
/data/working-copies/{workspace_id}/ with the repo contents mixed in,
causing a 500 when the expected repo-named subdirectory was missing.

- Build the target path as /data/working-copies/{workspace_id}/{repo_name}/
  and pass it directly to GitService.clone
- Remove stale directory detection and fallback logic that is no longer
  needed
- Keep diagnostic logging around git clone failures

Quality gates:
- pytest tests/unit: 219 passed
- mypy: clean on changed files
This commit is contained in:
Developer
2026-06-15 10:09:30 +00:00
parent 83928d0f02
commit 1658767cf4
13 changed files with 28 additions and 50 deletions
@@ -104,20 +104,21 @@ class WorkspaceManager:
repo_dir_name = self._repo_directory_name(repo)
workspace_id = uuid.uuid4()
parent_path = os.path.join(self.BASE_PATH, str(workspace_id))
clone_target = parent_path # git clone creates {repo_dir_name}/ inside this
expected_path = os.path.join(parent_path, repo_dir_name)
logger.info(
"Creating workspace: id=%s name=%s repo=%s branch=%s",
"Creating workspace: id=%s name=%s repo=%s branch=%s target=%s",
workspace_id,
name,
repo.id,
branch,
expected_path,
)
# Remove stale directory from previous failed/aborted clone
if os.path.exists(parent_path):
logger.warning("Removing stale workspace directory: %s", parent_path)
shutil.rmtree(parent_path, ignore_errors=True)
if os.path.exists(expected_path):
logger.warning("Removing stale workspace directory: %s", expected_path)
shutil.rmtree(expected_path, ignore_errors=True)
os.makedirs(parent_path, exist_ok=True)
# Ensure container users (various UIDs) can write to workspace dirs
@@ -141,7 +142,7 @@ class WorkspaceManager:
try:
await GitService.clone(
repo.remote_url, branch, clone_target, ssh_key=ssh_key
repo.remote_url, branch, expected_path, ssh_key=ssh_key
)
except Exception as exc:
logger.error(
@@ -153,29 +154,6 @@ class WorkspaceManager:
)
raise
expected_path = os.path.join(parent_path, repo_dir_name)
if not os.path.isdir(expected_path):
# git clone can create a different directory name than expected for
# some URL shapes; fall back to the single directory git created.
entries = [
entry
for entry in os.listdir(parent_path)
if os.path.isdir(os.path.join(parent_path, entry))
]
logger.info(
"Workspace %s: expected %s/ but found directories: %s",
workspace_id,
repo_dir_name,
entries,
)
if len(entries) == 1:
expected_path = os.path.join(parent_path, entries[0])
else:
raise RuntimeError(
f"Expected git clone to create {repo_dir_name}/ under "
f"{parent_path}, but found: {entries}"
)
self._make_world_writable(expected_path)
workspace = Workspace(