Rhodawk AI commited on
Commit
4ba73c1
Β·
1 Parent(s): 58491d5

fix: BUG-009 git clone creds + BUG-010 pip fallback + BUG-011 per-repo venv

Browse files
Files changed (2) hide show
  1. app.py +15 -2
  2. language_runtime.py +16 -4
app.py CHANGED
@@ -770,7 +770,16 @@ def enterprise_audit_loop(repo_override: str = None, branch: str = "main", speci
770
 
771
  if not os.path.exists(REPO_DIR):
772
  ui_log(f"Cloning {target_repo} β†’ {REPO_DIR} ...")
773
- Repo.clone_from(f"https://github.com/{target_repo}.git", REPO_DIR)
 
 
 
 
 
 
 
 
 
774
  else:
775
  ui_log(f"Repo dir exists β€” syncing {target_repo} to latest origin/main ...")
776
  safe_git_pull()
@@ -1187,7 +1196,11 @@ def _research_clone(repo: str) -> str:
1187
  repo_dir = f"/tmp/research_{repo.replace('/', '_')}"
1188
  if not os.path.exists(repo_dir):
1189
  ui_log(f"Cloning {repo} for static analysis...", "INFO")
1190
- Repo.clone_from(f"https://github.com/{repo}.git", repo_dir)
 
 
 
 
1191
  return repo_dir
1192
 
1193
 
 
770
 
771
  if not os.path.exists(REPO_DIR):
772
  ui_log(f"Cloning {target_repo} β†’ {REPO_DIR} ...")
773
+ # FIX-009: Use run_subprocess_safe instead of Repo.clone_from so that
774
+ # GIT_CONFIG_GLOBAL (set by configure_git_credentials) is propagated to
775
+ # the git subprocess via os.environ.copy(). gitpython's Repo.clone_from
776
+ # spawns its own subprocess which inherits os.environ, but only when the
777
+ # env parameter is not overridden β€” using run_subprocess_safe is safer
778
+ # because it explicitly copies os.environ (including GIT_CONFIG_GLOBAL).
779
+ run_subprocess_safe(
780
+ ["git", "clone", "-v", f"https://github.com/{target_repo}.git", REPO_DIR],
781
+ cwd="/tmp", raise_on_error=True,
782
+ )
783
  else:
784
  ui_log(f"Repo dir exists β€” syncing {target_repo} to latest origin/main ...")
785
  safe_git_pull()
 
1196
  repo_dir = f"/tmp/research_{repo.replace('/', '_')}"
1197
  if not os.path.exists(repo_dir):
1198
  ui_log(f"Cloning {repo} for static analysis...", "INFO")
1199
+ # FIX-009: Use run_subprocess_safe so GIT_CONFIG_GLOBAL credentials are inherited.
1200
+ run_subprocess_safe(
1201
+ ["git", "clone", "-v", f"https://github.com/{repo}.git", repo_dir],
1202
+ cwd="/tmp", raise_on_error=True,
1203
+ )
1204
  return repo_dir
1205
 
1206
 
language_runtime.py CHANGED
@@ -247,7 +247,13 @@ class PythonRuntime(LanguageRuntime):
247
 
248
  def setup_env(self, repo_dir: str, persistent_dir: str = "/data") -> EnvConfig:
249
  import sys
250
- venv_dir = os.path.join(persistent_dir, "target_venv")
 
 
 
 
 
 
251
 
252
  # FIX: guarantee the parent directory exists before uv/venv tries to write into it.
253
  # In HuggingFace Spaces /data is a mounted volume that may not be pre-created.
@@ -285,10 +291,14 @@ class PythonRuntime(LanguageRuntime):
285
  raise_on_error=True,
286
  )
287
 
288
- pip_bin = os.path.join(venv_dir, "bin", "pip")
 
 
 
 
289
 
290
  def _install_deps(args: list[str]) -> bool:
291
- """Try uv pip install first; fall back to pip on failure."""
292
  out, code = self._run(
293
  ["uv", "pip", "install", "--python", venv_dir, "--quiet"] + args,
294
  cwd=repo_dir, timeout=600, extra_env=uv_env,
@@ -296,8 +306,10 @@ class PythonRuntime(LanguageRuntime):
296
  if code != 0:
297
  import warnings
298
  warnings.warn(f"uv pip install failed (exit {code}) β€” falling back to pip. {out.strip()[:200]}")
 
 
299
  _, pip_code = self._run(
300
- [pip_bin, "install", "--quiet"] + args,
301
  cwd=repo_dir, timeout=600,
302
  )
303
  return pip_code == 0
 
247
 
248
  def setup_env(self, repo_dir: str, persistent_dir: str = "/data") -> EnvConfig:
249
  import sys
250
+ # FIX-011: Use a per-repo venv name derived from repo_dir so that switching
251
+ # between target repos never reuses a stale virtualenv with different deps.
252
+ # The old shared "target_venv" caused "[Errno 2] No such file or directory:
253
+ # '/data/target_venv/bin/pip'" when the venv belonged to a different repo.
254
+ import hashlib as _hashlib
255
+ _repo_hash = _hashlib.md5(repo_dir.encode()).hexdigest()[:8]
256
+ venv_dir = os.path.join(persistent_dir, f"target_venv_{_repo_hash}")
257
 
258
  # FIX: guarantee the parent directory exists before uv/venv tries to write into it.
259
  # In HuggingFace Spaces /data is a mounted volume that may not be pre-created.
 
291
  raise_on_error=True,
292
  )
293
 
294
+ # FIX-010: Resolve the venv's python interpreter to use as the pip fallback.
295
+ # Using `python -m pip` via the venv's python binary avoids the "No such file or
296
+ # directory: '/data/target_venv/bin/pip'" error seen when a fresh venv was created
297
+ # via `python -m venv` (which includes pip) but the bare pip script is absent.
298
+ venv_python = os.path.join(venv_dir, "bin", "python")
299
 
300
  def _install_deps(args: list[str]) -> bool:
301
+ """Try uv pip install first; fall back to the venv python -m pip on failure."""
302
  out, code = self._run(
303
  ["uv", "pip", "install", "--python", venv_dir, "--quiet"] + args,
304
  cwd=repo_dir, timeout=600, extra_env=uv_env,
 
306
  if code != 0:
307
  import warnings
308
  warnings.warn(f"uv pip install failed (exit {code}) β€” falling back to pip. {out.strip()[:200]}")
309
+ # FIX-010: use venv_python -m pip instead of a bare pip_bin path β€”
310
+ # the `pip` script may be absent in freshly-created stdlib venvs.
311
  _, pip_code = self._run(
312
+ [venv_python, "-m", "pip", "install", "--quiet"] + args,
313
  cwd=repo_dir, timeout=600,
314
  )
315
  return pip_code == 0