Repository: pantsbuild/pants

Issue:
Pants 2.15.x breaks `--debug-adapter` on Python `run`
**Describe the bug**
The title says it all. Worth noting `test` is not afflicted.

**Pants version**
2.15.0rc3

**OS**
Linux

**Additional info**
N/A



Discussion:
So everything works if I run the command from the sandbox. This leads me to believe that this is broken because our path mappings have us expecting to hit code relative to the sandbox root, and not the build root.

The real challenge is we really have 2 "roots". The build root, and the sandbox root. The sandbox root is still important in case there are Pants-generated Python files... although those can't have breakpoints set, so I think that's our answer?
On a side note, I wish there was infrastructure in place to actually run a client process so we can test breakpoints are hit instead of hand-testing this :cry: 
Ah I see the issue. Previously we did all the path monkeypatching to support `run_in_sandbox=False`, but we broke `run_in_sandbox=True`.

Will post PR and test with both

Resolving patch:
diff --git a/src/python/pants/backend/python/goals/run_helper.py b/src/python/pants/backend/python/goals/run_helper.py
--- a/src/python/pants/backend/python/goals/run_helper.py
+++ b/src/python/pants/backend/python/goals/run_helper.py
@@ -128,6 +128,7 @@ async def _create_python_source_run_dap_request(
     *,
     debugpy: DebugPy,
     debug_adapter: DebugAdapterSubsystem,
+    run_in_sandbox: bool,
 ) -> RunDebugAdapterRequest:
     launcher_digest = await Get(
         Digest,
@@ -142,14 +143,6 @@ async def _create_python_source_run_dap_request(
 
                             del os.environ["PEX_INTERPRETER"]
 
-                            # See https://github.com/pantsbuild/pants/issues/17540
-                            # For `run --debug-adapter`, the client might send a `pathMappings`
-                            # (this is likely as VS Code likes to configure that by default) with
-                            # a `remoteRoot` of ".". For `run`, CWD is set to the build root, so
-                            # breakpoints set in-repo will never be hit. We fix this by monkeypatching
-                            # pydevd (the library powering debugpy) so that a remoteRoot of "."
-                            # means the sandbox root.
-
                             import debugpy._vendored.force_pydevd
                             from _pydevd_bundle.pydevd_process_net_command_json import PyDevJsonCommandProcessor
                             orig_resolve_remote_root = PyDevJsonCommandProcessor._resolve_remote_root
@@ -181,7 +174,18 @@ def patched_resolve_remote_root(self, local_root, remote_root):
     )
     extra_env = dict(regular_run_request.extra_env)
     extra_env["PEX_INTERPRETER"] = "1"
-    extra_env["PANTS_CHROOT"] = _in_chroot("").rstrip("/")
+    # See https://github.com/pantsbuild/pants/issues/17540
+    # and https://github.com/pantsbuild/pants/issues/18243
+    # For `run --debug-adapter`, the client might send a `pathMappings`
+    # (this is likely as VS Code likes to configure that by default) with a `remoteRoot` of ".".
+    #
+    # For `run`, CWD is the build root. If `run_in_sandbox` is False, everything is OK.
+    # If `run_in_sandbox` is True, breakpoints won't be hit as CWD != sandbox root.
+    #
+    # We fix this by monkeypatching pydevd (the library powering debugpy) so that a remoteRoot of "."
+    # means the sandbox root.
+    # See https://github.com/fabioz/PyDev.Debugger/pull/243 for a better solution.
+    extra_env["PANTS_CHROOT"] = _in_chroot("").rstrip("/") if run_in_sandbox else "."
     args = [
         *regular_run_request.args,
         _in_chroot("__debugpy_launcher.py"),
diff --git a/src/python/pants/backend/python/goals/run_python_source.py b/src/python/pants/backend/python/goals/run_python_source.py
--- a/src/python/pants/backend/python/goals/run_python_source.py
+++ b/src/python/pants/backend/python/goals/run_python_source.py
@@ -97,18 +97,20 @@ async def create_python_source_debug_adapter_request(
         ),
     )
 
+    run_in_sandbox = field_set.should_use_sandbox(python_setup)
     run_request = await _create_python_source_run_request(
         field_set.address,
         entry_point_field=PexEntryPointField(field_set.source.value, field_set.address),
         pex_env=pex_env,
         pex_path=[debugpy_pex],
-        run_in_sandbox=field_set.should_use_sandbox(python_setup),
+        run_in_sandbox=run_in_sandbox,
     )
 
     return await _create_python_source_run_dap_request(
         run_request,
         debugpy=debugpy,
         debug_adapter=debug_adapter,
+        run_in_sandbox=run_in_sandbox,
     )
 
 


Test patch: