Repository: pantsbuild/pants

Issue:
Use of relative PATH for docker-tool shims prevents use of credential helpers
**Describe the bug**
I'm trying to set up [tools](https://www.pantsbuild.org/docs/reference-docker#section-tools) in my repo's `docker` subsystem, to plug in the [ECR credential helper](https://github.com/awslabs/amazon-ecr-credential-helper). To do so I added the following to `pants.toml`:
```toml
[docker]
tools = ["docker-credential-ecr-login", "sh"]
```
When I run `./pants package path/to/Dockerfile`, I get the error:
```
failed to solve with frontend dockerfile.v0: failed to create LLB definition: rpc error: code = Unknown desc = error getting credentials - err: docker-credential-ecr-login resolves to executable in current directory (./.shims/bin/docker-credential-ecr-login), out: ``
```
If I run the above with `--no-process-cleanup` and `cd` into the tmpdir, I see:
1. There are shims for both tools under `.shims/bin`
2. The shims behave as expected when I use them directly
3. `__run.sh` sets `PATH=.shims/bin`

If I edit `__run.sh` to instead set `PATH=<absolute-path-to-tmpdir>/.shims/bin`, the build works.

**Pants version**
2.11.0+git9ac327d4

**OS**
MacOS

**Additional info**
Docker Desktop v4.7.1 (77678)
Docker Engine v20.10.14



Discussion:
EDIT: Turns out fixing this isn't as easy as I expected 😅 the `PATH` for the tool shims is set [here](https://github.com/pantsbuild/pants/blob/main/src/python/pants/backend/docker/util_rules/docker_binary.py#L152-L154), where (AFAICT) there's no knowledge of the ultimate working dir. It [looks like](https://github.com/pantsbuild/pants/blob/main/src/rust/engine/process_execution/src/local.rs#L733-L737) we escape all our env vars before writing them to `__run.sh` so hacking in a `${PWD}` won't work.
I believe the root cause of the error is https://github.com/docker/cli/commit/8d199d5bba9db46b6610bd959d815ce7197402b3, which switched the `docker` CLI from `os/exec` to `golang.org/x/sys/execabs`. A primary difference between the packages is that `LookPath` in `execabs` returns an error if the lookup would return an executable from the current directory (docs [here](https://pkg.go.dev/golang.org/x/sys/execabs#LookPath)). As of ~yesterday the Go team has replaced `os/exec` with the `execabs` logic (see https://github.com/golang/go/issues/43724), so I don't think this behavior is going anywhere 😢 

EDIT: I also think it means that this issue _isn't_ isolated to Docker for Mac or the ECR credential helper specifically
To fix this without needing bigger refactors outside of the `docker` subsystem, I'm thinking that (only when `tools` are configured for `docker`) the logic could generate an extra `__docker.sh` script that's basically:
```shell
#!/bin/bash
export PATH=$(pwd)/.shims/bin:${PATH}
"<path-to-docker-binary>" "${@}"
```
And then `__run.sh` would invoke `__docker.sh` instead of `<path-to-docker-binary>`.
Thank you so much for finding the root cause of this issue!

It's clear that is not sustainable to use `.` in PATH for the BinaryShims. I'll take a look at your PR for this.

Resolving patch:
diff --git a/src/python/pants/backend/docker/util_rules/docker_binary.py b/src/python/pants/backend/docker/util_rules/docker_binary.py
--- a/src/python/pants/backend/docker/util_rules/docker_binary.py
+++ b/src/python/pants/backend/docker/util_rules/docker_binary.py
@@ -150,7 +150,7 @@ async def find_docker(
         ),
     )
     tools_path = ".shims"
-    extra_env = {"PATH": os.path.join(tools_path, tools.bin_directory)}
+    extra_env = {"PATH": os.path.join("{chroot}", tools_path, tools.bin_directory)}
     extra_input_digests = {tools_path: tools.digest}
 
     return DockerBinary(


Test patch: