google / zx

A tool for writing better scripts
https://google.github.io/zx/
Apache License 2.0
42.96k stars 1.09k forks source link

Idea: Self-installing runtime to run scripts anywhere #25

Closed biels closed 3 years ago

biels commented 3 years ago

Maybe it could be a good idea to include a compact line at the top of zx scripts that installs the required runtime if it is not present on the machine. Something like executing a sh that reads from curl hosted on the official github repo or similar. This would allow the scripts to be executed at any time without installing anything.

Maybe it could even be possible to install things (node, zx) locally if the user does not have enough permissions and/or the execution is unattended.

See how gradle does a similar thing with gradle wrapper: https://docs.gradle.org/current/userguide/gradle_wrapper.html#sec:using_wrapper

Artoria2e5 commented 3 years ago

I am pretty sure you can do a quick user-env install in these steps:

  1. Use n-install to install n: https://github.com/mklement0/n-install.
  2. Run exec bash -l or whatever to restart your shell and update the PATH.
  3. Get n to install node and npm: n install latest
  4. Get npm to install zx: npm install -g zx

All that can be put into a install-zx.sh script, yes. But it into a line at the top is very questionable practice, since it downloads stuff without asking you. On top of that, you will need special magic to deal with the extra arguments in shebang as it varies by system. That said, if you still want to try...

#!/usr/bin/env -S sh -c 'if ! command -v zx &>/dev/null; curl install-zx.sh | sh; PATH+=":$HOME/n/bin"; fi; exec zx "$@"'

// Usual zx stuff

(Oh, did I mention that the long line might break things too? See https://www.in-ulm.de/~mascheck/various/shebang/#solutionsforlonglines. But then you get another dependency, and that's what we've been trying to avoid all the time...)

biels commented 3 years ago

But it into a line at the top is very questionable practice, since it downloads stuff without asking you.

Gradle is doing it though. Gradle downloads a copy of its binary (gradle daemon) if it can't find it and then runs using it. It downloads a copy on the local folder by default. This makes it portable to any system without any instructions. It even creates scripts for windows and linux by default (a .sh and a .bat).

I think you should be reading any scripts before executing them so really not anything unexpected is happening.

Artoria2e5 commented 3 years ago

The gradle wrapper requires not just gradlew.bat to run -- it also needs a gradle-wrapper.jar. On top of that, the behavior of gradle is not defined using the wrapper itself, but using a bunch of other config files. If settings.gradle somehow includes the whole of gradlew that would be an okay analogue.

Still, having an install script can help with easy deployment, and shipping that with a zx script is totally cool. It's just fitting it into the shebang isn't much of a good idea. (We could also not fit it in there but instead use the run-by-shell fallback of many sh shells. That doesn't make it any better IMO.)

antonmedv commented 3 years ago

Node comes with helpful tool npx. Just use it.

npx zx scripts/my-script.mjs