CDK doesn't support executing a command with no arguments to run an app. Suppose that "foobar" is an executable in your $PATH. The following command doesn't work as expected:
$ cdk --app "foobar" ls
ENOENT: no such file or directory, stat 'foobar'
while the command below works:
$ cdk --app "foobar arg" ls
You can reproduce this behavior with any executable. For instance:
$ cdk --app "cp" ls
and
$ cdk --app "cp /path1 /path2" ls
On the other hand, if the executable doesn't exist for real, the error is:
/bin/sh: foobar: command not found
Subprocess exited with error 127
The same goes if the "no argument" app is specified in the cdk.json configuration file instead of the command line.
{
"app": "foobar"
}
I found the bug. The culprit is this fs.stat call. If a command without arguments is specified it tries to stat it. In turn that forces the user to specify the executable's full path or a command with at least 1 argument. The logic of guessExecutable function is wrong. The easy fix would be to simply ignore any fs.stat error and return the commandLine argument untouched. A more robust solution would involve using a package like lookpath to check if a command exists and where the executable file is.
@rix0rrr sorry for pinging directly but that one is an easy fix and it's blocking us from using CDK. Thanks
@philtay - investigating your suggestion re: using lookpath
@shivlaks thanks a lot for looking into this. Whatever mimics golang LookPath would do. Using the suggested package the guessExecutable function would look something like this:
async function guessExecutable(commandLine: string[]) {
if (commandLine.length === 1) {
const exec = await lookpath(commandLine[0]);
if (!exec) {
return commandLine;
}
const fstat = await fs.stat(exec);
// tslint:disable-next-line:no-bitwise
const isExecutable = (fstat.mode & fs.constants.X_OK) !== 0;
const isWindows = process.platform === "win32";
const handler = EXTENSION_MAP.get(path.extname(exec));
if (handler && (!isExecutable || isWindows)) {
return handler(exec);
}
}
return commandLine;
}
@philtay we discussed using lookPath and elected to go with the simpler workaround and make it more robust following that instead of taking on a new dependency.
I'll try to get to it this week!
Thank you @shivlaks. That's a perfectly fine solution. If possible, please also add a unit test. These things are a little tricky and it's easy to introduce a regression.