pinpox / lollypops

Lollypop Operations - NixOS Deployment Tool
https://pinpox.github.io/lollypops/
GNU General Public License v3.0
118 stars 17 forks source link

Broken with none POSIX shell #9

Open Marvin-LOUIS opened 2 years ago

Marvin-LOUIS commented 2 years ago

I'm using nushell as the default shell on my system and when trying to run an action, let's say deploy-secrets, I get the following error:

[homelab:deploy-secrets] Error: nu::parser::unknown_flag (link)
[homelab:deploy-secrets]
[homelab:deploy-secrets]   × The `mkdir` command doesn't have flag `-p`.
[homelab:deploy-secrets]    ╭─[source:1:1]
[homelab:deploy-secrets]  1 │ umask 077; mkdir -p "$(dirname /path/to/secret)"
[homelab:deploy-secrets]    ·                   ┬
[homelab:deploy-secrets]    ·                   ╰── unknown flag
[homelab:deploy-secrets]    ╰────
[homelab:deploy-secrets]   help: use mkdir --help for a list of flags
[homelab:deploy-secrets]
task: Failed to run task "homelab:deploy-secrets": exit status 1

The mkdir implementation of nushell doesn't have the -p option has it creates missing folder by default. I'm not familiar with go-task but would there be a way to force the use a POSIX compliant shell (say sh) to avoid such conflicts ?

Marvin-LOUIS commented 2 years ago

I just played around with go-task to understand it better and when I provide it with a basic Taskfile creating a directory using mkdir -p it works just fine. I suppose it might be specific to the way it's set in lollypops then. I'll dig further to see if I can find a solution.

pinpox commented 2 years ago

Would be great if you find a solution to this, I have no experience with nushell. If you run lollypops with the -v you see the exact commands it runs internally and can use those to debug

One possible solution would be to wrap the commands in a sh call, something like this:

ssh {{.REMOTE_USER}}@{{.REMOTE_HOST}} 'sh -c 'umask 077; mkdir -p "$(dirname ${pkgs.lib.escapeShellArg x.path})'" '

But maybe there is a simpler way of archiving this.

Marvin-LOUIS commented 2 years ago

I spent some time looking into it. The "issue" (it's actually expected behavior) is indeed linked to ssh using the default shell to execute the given command. To my knowledge and from the research I've done there are no option to set in the ssh-config or flag to provide to override the default remote shell. The best option seemingly being to call sh -c "actual_command" directly from the ssh statement as you proposed.

Would that be a satisfactory solution, or is it a bit too hacky? I can understand if you'd rather avoid this solution for what's essentially a niche use case (I doubt that many people use a non-POSIX shell).

Marvin-LOUIS commented 2 years ago

You can take a look at this commit to see the changes it would create. Nothing suspential but it enforces the use of sh on the remote for all the ssh commands.

pinpox commented 2 years ago

I'm okay with wrapping it in sh but I'm not sure how that behaves if a command files on the remote. Does it keep the exit code? Are there any other implications?

Marvin-LOUIS commented 2 years ago

It sadly doesn't keep the exit code of the desired command but rather the exit code of sh -c. So if sh -c fails you still get an error exit code, but maybe not the expected one. For example if you try to directly run a command that doesn't exist on the remote through ssh you get an exit code of 1, but if you wrap that into sh -c you get 127.

The only exception I found so far was with the exit command. when run normaly through ssh it returns the specified exit code but when wrapped by sh -c it returns 0.

As far as other implications, configuration of the default remote shell won't be taken into account (unless the default shell is sh). I don't think that's much of an issue however.