From 80e496d1347f8fea8f29a0a41df12f6d3e31e187 Mon Sep 17 00:00:00 2001 From: Robert Brennan Date: Wed, 4 Jun 2025 11:32:27 -0700 Subject: [PATCH] Unrevert "Add username parameter to AsyncBashSession" (#8771) Co-authored-by: Engel Nyst Co-authored-by: openhands --- openhands/runtime/action_execution_server.py | 4 ++- openhands/runtime/base.py | 2 +- openhands/runtime/utils/async_bash.py | 34 +++++++++++++++++--- tests/unit/test_runtime_git_tokens.py | 10 ++++-- 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/openhands/runtime/action_execution_server.py b/openhands/runtime/action_execution_server.py index 8567c04639..4118b5a0d5 100644 --- a/openhands/runtime/action_execution_server.py +++ b/openhands/runtime/action_execution_server.py @@ -390,7 +390,9 @@ class ActionExecutor: try: if action.is_static: path = action.cwd or self._initial_cwd - result = await AsyncBashSession.execute(action.command, path) + result = await AsyncBashSession.execute( + action.command, path, self.username + ) obs = CmdOutputObservation( content=result.content, exit_code=result.exit_code, diff --git a/openhands/runtime/base.py b/openhands/runtime/base.py index 858f4291cd..2591647d27 100644 --- a/openhands/runtime/base.py +++ b/openhands/runtime/base.py @@ -400,7 +400,7 @@ class Runtime(FileEditRuntimeMixin): 'No repository selected. Initializing a new git repository in the workspace.' ) action = CmdRunAction( - command='git init', + command=f'git init && git config --global --add safe.directory {self.workspace_root}' ) self.run_action(action) else: diff --git a/openhands/runtime/utils/async_bash.py b/openhands/runtime/utils/async_bash.py index b7ac3823e5..d705c5b770 100644 --- a/openhands/runtime/utils/async_bash.py +++ b/openhands/runtime/utils/async_bash.py @@ -1,12 +1,17 @@ import asyncio import os +import pwd +import sys +from typing import Any, Optional from openhands.runtime.base import CommandResult class AsyncBashSession: @staticmethod - async def execute(command: str, work_dir: str) -> CommandResult: + async def execute( + command: str, work_dir: str, username: Optional[str] = None + ) -> CommandResult: """Execute a command in the bash session asynchronously.""" work_dir = os.path.abspath(work_dir) @@ -17,12 +22,31 @@ class AsyncBashSession: if not command: return CommandResult(content='', exit_code=0) + # Create subprocess arguments + subprocess_kwargs: dict[str, Any] = { + 'stdout': asyncio.subprocess.PIPE, + 'stderr': asyncio.subprocess.PIPE, + 'cwd': work_dir, + } + + # Only apply user-specific settings on non-Windows platforms + if username and sys.platform != 'win32': + try: + user_info = pwd.getpwnam(username) + env: dict[str, str] = { + 'HOME': user_info.pw_dir, + 'USER': username, + 'LOGNAME': username, + } + subprocess_kwargs['env'] = env + subprocess_kwargs['user'] = username + except KeyError: + raise ValueError(f'User {username} does not exist.') + + # Prepare to run the command try: process = await asyncio.subprocess.create_subprocess_shell( - command, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - cwd=work_dir, + command, **subprocess_kwargs ) try: diff --git a/tests/unit/test_runtime_git_tokens.py b/tests/unit/test_runtime_git_tokens.py index fb880d9aec..b28c718d8f 100644 --- a/tests/unit/test_runtime_git_tokens.py +++ b/tests/unit/test_runtime_git_tokens.py @@ -234,7 +234,10 @@ async def test_clone_or_init_repo_no_repo_with_user_id(temp_dir): # Verify that git init was called assert len(runtime.run_action_calls) == 1 assert isinstance(runtime.run_action_calls[0], CmdRunAction) - assert runtime.run_action_calls[0].command == 'git init' + assert ( + runtime.run_action_calls[0].command + == f'git init && git config --global --add safe.directory {runtime.workspace_root}' + ) assert result == '' @@ -255,7 +258,10 @@ async def test_clone_or_init_repo_no_repo_no_user_id_no_workspace_base(temp_dir) # Verify that git init was called assert len(runtime.run_action_calls) == 1 assert isinstance(runtime.run_action_calls[0], CmdRunAction) - assert runtime.run_action_calls[0].command == 'git init' + assert ( + runtime.run_action_calls[0].command + == f'git init && git config --global --add safe.directory {runtime.workspace_root}' + ) assert result == ''