I'm having one hell of a time with system_binary. ...
# general
g
I'm having one hell of a time with system_binary. Does anyone know how I can troubleshoot this?
Copy code
ValueError: Could not find a binary with name `node`. The following paths were searched: /usr/bin, /bin, /usr/local/bin, /opt/homebrew/bin.
Copy code
$ PATH=/usr/bin:/bin:/usr/local/bin:/opt/homebrew/bin which node
/opt/homebrew/bin/node
Copy code
$ PATH=/usr/bin:/bin:/usr/local/bin:/opt/homebrew/bin node --version
v18.19.1
$ echo $?
0
Copy code
system_binary(
    name="node",
    binary_name="node",
    fingerprint_args=["--version"],
)
w
I remember running into something like this a LONNNNNG time ago, so my memory is super foggy. It was dirname, and I had to do some shenanigans to get it working... Not the same, obviously, as you have fingerprint args - but 🤷
Copy code
# Vite needs `dirname` to be in the environment
system_binary(
    name="dirname",
    binary_name="dirname",
    # MacOS doesn't have a `--version` flag, so we need to pass something otherwise dirname errors
    fingerprint_args=["some-random-string-so-dirname-doesnt-fail"], 
)
This is how I currently grab
node
Copy code
# Pull the host's `node` into the environment
system_binary(
    name="node",
    binary_name="node",
    fingerprint=r"v(20|[1-9][0-9])\..*\..*",
    fingerprint_args=["--version"],
)
If you keep sandboxes, can you check the path that the sandbox uses?
g
Thanks @wide-midnight-78598. I'll take a look at that.
This is a Mac OS specific issue. It works fine on Linux.
I even did this:
Copy code
diff --git i/src/python/pants/backend/adhoc/run_system_binary.py w/src/python/pants/backend/adhoc/run_system_binary.py
index 4b6e8272fc..6b5ca74a52 100644
--- i/src/python/pants/backend/adhoc/run_system_binary.py
+++ w/src/python/pants/backend/adhoc/run_system_binary.py
@@ -103,18 +103,29 @@ async def _find_binary(
         for path in binaries.paths
     )

+    logger.debug(f"[{binary_name}] tests: {tests}")
+    logger.debug(f"[{binary_name}] binaries.paths: {binaries.paths}")
+
     for test, binary in zip(tests, binaries.paths):
+        <http://logger.info|logger.info>(f"{binary} for loop entrance")
         if test.exit_code != 0:
+            logger.warn(f"[{binary_name}] {binary} did not exit 0")
             continue

         if fingerprint_pattern:
             fingerprint = test.stdout.decode().strip()
             match = re.match(fingerprint_pattern, fingerprint)
             if not match:
+                logger.warn(
+                    f"[{binary_name}] {binary} did not match fingerprint pattern"
+                )
                 continue

+        <http://logger.info|logger.info>(f"returning binary: {binary}")
         return binary

+    logger.error(f"Couldn't find any binary for {binary_name}")
+
     raise ValueError(
         f"Could not find a binary with name `{binary_name}`"
         + (
@@ -134,7 +145,9 @@ async def create_system_binary_run_request(
     assert field_set.name.value is not None
     extra_search_paths = field_set.extra_search_paths.value or ()

-    search_path = SearchPath((*extra_search_paths, *system_binaries.system_binary_paths))
+    search_path = SearchPath(
+        (*extra_search_paths, *system_binaries.system_binary_paths)
+    )

     path = await _find_binary(
         field_set.address,
This shows pants looking up node twice, one time it finds it, another time it doesn't.
w
Ah man, I literally ran into exactly this..... Was debugging, could find the binary, but for some reason - it just wasn't being picked up by
system_binary
Is there an
extra_search_paths=["/opt/homebrew/bin"]
type of thing you can try?
Also, maybe try adding a
fingerprint
and seeing if that helps? Or alternatively, what about ditching
fingerprint_args
in case that helps? I think these are often used if you have multiple binaries, but 🤷
Oh, also, which pants version? I can try on my repo with the same args
g
I've tried both main and 2.19.1 -- it happens on both. I'm also using
--no-pantsd --no-local-cache
w
Have you tried adding/removing both fingerprint args, or using extra search paths? Anything from the sandbox?
g
I've tried extra search paths.
I haven't tried removing fingerprint args
w
pants --no-pantsd --keep-sandboxes=always run blahblah/web:node
Copy code
Preserving local process execution dir /private/var/folders/dy/q08y_dts5vd71rm99t4gc9lr0000gp/T/pants-sandbox-Z7g6oc for Searching for `node` on PATH=/usr/bin:/bin:/usr/local/bin:/opt/homebrew/bin
Then you can open that, and run
sh __run.sh
Maybe there is a hint in there?
g
try now...
That works...
Copy code
$ pants --keep-sandboxes=always --no-pantsd --no-local-cache -ldebug run apps/atlas-interactive:node -- --version
Copy code
12:33:11.43 [DEBUG] Completed: setup_sandbox
v18.19.1
this is what I'm saying, something is off. With the additional logging I added to
src/python/pants/backend/adhoc/run_system_binary.py
I know for a fact it finds it, but for some reason it's looking twice and the second one fails.
w
🤯
g
exactly...
very weird indeed.
w
And downstream, you're using it as a
runnable_dependencies=[":node", ":sh"],
?
g
Copy code
runnable_dependencies=[":node", ":sed", ":readlink", ":dirname", ":uname"],
for some reason I needed all of those
no idea why
I didn't know yarn requires that crap, but it seems like it was using it.
Copy code
system_binary(
    name="sed",
    binary_name="sed",
    fingerprint_args=["--help"],
    extra_search_paths=["/opt/homebrew/opt/gnu-sed/libexec/gnubin"],
)

system_binary(
    name="readlink",
    binary_name="readlink",
    fingerprint_args=["--help"],
    extra_search_paths=["/opt/homebrew/opt/coreutils/libexec/gnubin"],
)

system_binary(
    name="dirname",
    binary_name="dirname",
    fingerprint_args=["--help"],
    extra_search_paths=["/opt/homebrew/opt/coreutils/libexec/gnubin"],
)

system_binary(
    name="uname",
    binary_name="uname",
    fingerprint_args=["--help"],
    extra_search_paths=["/opt/homebrew/opt/coreutils/libexec/gnubin"],
)

system_binary(
    name="node",
    binary_name="node",
)

system_binary(
    name="yarn",
    binary_name="yarn",
    fingerprint_dependencies=[":node"],
)

adhoc_tool(
    name="yarn_install",
    runnable=":yarn",
    runnable_dependencies=[":node", ":sed", ":readlink", ":dirname", ":uname"],
    args=[
        "install",
        "--non-interactive",
        "--frozen-lockfile",
        "--prefer-offline",
        "--cache-folder",
        "./yarn-cache",
    ],
    extra_env_vars=["NODE_ENV=production", "NEXT_TELEMETRY_DISABLED=1"],
    output_directories=["node_modules/"],
    output_dependencies=[":package_config"],
    execution_dependencies=[":package_config"],
)
w
I ran into something similar with Svelte, needed 3-4 tools (to my surprise)
g
In the preserved dir it returns...
Copy code
$ ./__run.sh                   
+ CHECK_FILE_ENTRIES=
+ for path in '${PATH//:/ }'
+ [[ -d /usr/bin ]]
+ maybe_exe=/usr/bin/node
+ [[ node == \n\o\d\e ]]
+ [[ -f /usr/bin/node ]]
+ for path in '${PATH//:/ }'
+ [[ -d /bin ]]
+ maybe_exe=/bin/node
+ [[ node == \n\o\d\e ]]
+ [[ -f /bin/node ]]
+ for path in '${PATH//:/ }'
+ [[ -d /usr/local/bin ]]
+ maybe_exe=/usr/local/bin/node
+ [[ node == \n\o\d\e ]]
+ [[ -f /usr/local/bin/node ]]
+ for path in '${PATH//:/ }'
+ [[ -d /opt/homebrew/bin ]]
+ maybe_exe=/opt/homebrew/bin/node
+ [[ node == \n\o\d\e ]]
+ [[ -f /opt/homebrew/bin/node ]]
+ [[ -x /opt/homebrew/bin/node ]]
+ echo /opt/homebrew/bin/node
/opt/homebrew/bin/node
This is spooky weird.
w
Yeah, it feels like the error is a red herring or something. Like, you know it can find
node
so, is the problem being called because of something else, and
node
is the error returned (e.g. like, yarn's dependency, or something)
Is
yarn
globally available too?
g
The tests and binaries.pathes are empty for the one that error's out.
Copy code
12:34:55.34 [DEBUG] [node] tests: ()
12:34:55.34 [DEBUG] [node] binaries.paths: ()
but in the same run there is one above that succeeds...
Copy code
12:34:54.90 [DEBUG] [node] tests: (FallibleProcessResult(stdout=b'', stdout_digest=FileDigest('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 0), stderr=b'', stderr_digest=FileDigest('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 0), exit_code=0, output_digest=Digest('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 0), metadata=ProcessResultMetadata(total_elapsed_ms=301, execution_environment=ProcessExecutionEnvironment(environment=ProcessExecutionEnvironment { name: None, platform: Macos_arm64, strategy: Local }), _source='ran', source_run_id=0)),)
12:34:54.90 [DEBUG] [node] binaries.paths: (BinaryPath(path='/opt/homebrew/bin/node', fingerprint='e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'),)
so somehow pants is trying two different node's and yielding different results. I'm out of my depths on where to look next.
adding another debug statement to get the target address
w
Copy code
pants --keep-sandboxes=always --no-pantsd --no-local-cache -ldebug run apps/atlas-interactive:node -- --version
So that works, what about:
Copy code
pants --keep-sandboxes=always --no-pantsd --no-local-cache -ldebug run apps/atlas-interactive:yarn -- --version
g
I need to run single thread to get to the bottom of this too
that works too 🙂
w
If you can narrowly carve out a sample repo, I can try on my machine to see what happens
Because the example svelte app I have works, even with yarn
g
I'll try to carve out a repro case.
w
👍