From 59d65ba5575e666c2a0369db60b8798064135d6b Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Wed, 29 Apr 2026 02:07:19 -0700 Subject: [PATCH] fix: resolve git/gh from PATH instead of hardcoded /usr/local/bin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #2289. Some workspace template images ship `/usr/local/bin/{git,gh}` wrappers that bake `GH_TOKEN` into argv handling (preferred — auto-PR creation authenticates without explicit token plumbing); other templates have plain `/usr/bin/git` installed via apt with no wrapper. The hardcoded `_GIT = "/usr/local/bin/git"` crashed every auto-push attempt on the latter image class: FileNotFoundError: [Errno 2] No such file or directory: '/usr/local/bin/git' File "/app/molecule_runtime/executor_helpers.py", line 524, in _auto_push_and_pr_sync subprocess.run(['/usr/local/bin/git', 'rev-parse', '--is-inside-work-tree'], ...) `shutil.which("git")` walks PATH in order — finds the `/usr/local/bin/` wrapper first when it exists, falls back to `/usr/bin/git` otherwise. GH_TOKEN injection still wins on wrapper-equipped images; auto-push no longer crashes on bare-apt images. Verified locally: `shutil.which("git")` resolves to `/usr/bin/git` on the bug-reporter's image; `shutil.which("gh")` resolves to the homebrew path on dev. Both paths exist + are executable on respective hosts. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 (1M context) --- workspace/executor_helpers.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/workspace/executor_helpers.py b/workspace/executor_helpers.py index 68497d50..8779ea8e 100644 --- a/workspace/executor_helpers.py +++ b/workspace/executor_helpers.py @@ -26,6 +26,7 @@ import logging import mimetypes import os import re +import shutil import subprocess import uuid as _uuid from pathlib import Path @@ -513,9 +514,16 @@ def sanitize_agent_error( # Auto-push hook — push unpushed commits and open PR after task completion # ======================================================================== -# Git/gh wrappers at /usr/local/bin have GH_TOKEN baked in. -_GIT = "/usr/local/bin/git" -_GH = "/usr/local/bin/gh" +# Resolve git/gh from PATH so the runtime works regardless of which +# image the workspace is on. Some templates ship a /usr/local/bin/{git,gh} +# wrapper with GH_TOKEN baked in (preferred — picks up auth automatically); +# other templates have plain /usr/bin/git installed by apt. Hardcoding +# /usr/local/bin/git crashed every auto-push attempt on the latter image +# class with `FileNotFoundError: '/usr/local/bin/git'` (issue #2289). +# `shutil.which` finds the wrapper first if it's earlier in PATH, so the +# GH_TOKEN injection still wins where it exists. +_GIT = shutil.which("git") or "/usr/bin/git" +_GH = shutil.which("gh") or "/usr/bin/gh" _PROTECTED_BRANCHES = frozenset({"staging", "main", "master"})