moon icon indicating copy to clipboard operation
moon copied to clipboard

[feature] Run code block / multiple commands for a task

Open hustcer opened this issue 3 years ago • 5 comments

Is your feature request related to a problem? Please describe.

It's not convenient to run a code block in tasks currently, which is quite common if we want moon to be "language agnostic and easily pluggable in the future."

Describe the solution you'd like

Add running code block support for tasks, like

tasks:
    build:
           shell: bash    # It will be better if we can change to other shells, support syntax like `['bash', '-c']` or `bash -c`
           load-dotenv: true   # load a `.env` file automatically for the following code block
           run: |    # Writing multi-line commands for better readability
                 npm ci
                 npm run build
                 echo 'Done'

REF: https://docs.github.com/en/github-ae@latest/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun

Describe alternatives you've considered

Additional context

hustcer avatar Jul 23 '22 01:07 hustcer

@hustcer This is something that won't happen for a while, as it's quite a drastic change from how things work, for the following reasons:

  • A task is more akin to a singular unit of work, and as such, is represented by a single command and its unique arguments. Think of it like a function that accepts inputs and will always return the same output(s). Running a block of commands may produce side-effects. This leads to the next point...

  • Multiline or multiple commands are better represented with task chains through the deps option (https://moonrepo.dev/docs/config/project#deps), as this allows for incremental caching at every layer in the chain. It's a bit more verbose, but provides more out of the box functionality in the end. So in your example, you may have something like:

    tasks:
      clean:
        command: '...'
      build:
        command: 'npm'
        args: 'run build'
        deps: ['~:clean']
    

    Also, the npm ci in your example is not necessary, because in moon you never need to do that, as it will automatically install node modules when applicable.

  • Since this is written in Rust and not Node.js, we don't have access to require, require.resolve, the child_process or execa modules, or the entire Node.js module resolution algorithm. We implement it ourselves around our toolchain abstraction (https://moonrepo.dev/docs/concepts/toolchain).

    Because of this, we need to know which binary you are running (the command field) and how to find it (the type field). With this information, we traverse the file system. If type is "node", we recursively traverse upwards and look within node_modules/.bin and resolve a path to the npm binary to run. If the type is "system", we currently assume it exists in $PATH. Multi-commands make this much more difficult.

  • Also because this is Rust, there's no concept of a "shell" (excluding some processes in Windows that use cmd.exe). In Node.js, the child_process module emulates this functionality for you. With a task, you simple do it yourself:

    tasks:
      build:
        command: 'bash'
        args: '-c scripts/build.sh'
        type: 'system'
    
  • As for .env support, this will land at somepoint in the future. In the meantime, you can use the env field itself. https://moonrepo.dev/docs/config/project#env

milesj avatar Jul 23 '22 18:07 milesj

With all that being said, I'll leave this open to gauge feedback.

milesj avatar Jul 23 '22 18:07 milesj

Got it, thanks for your reply

hustcer avatar Jul 24 '22 02:07 hustcer

@hustcer It may not be apparent from my previous post, but you could always run multiple commands by encapsulating them within a runnable script. This is kind of an escape hatch.

tasks:
  build:
    command: 'node'
    args: './script.js'
  # Or bash
  build:
    command: 'bash'
    args: './script.sh'
    type: 'system'

milesj avatar Jul 24 '22 04:07 milesj

Tasks now support .env files: https://moonrepo.dev/docs/config/project#envfile

milesj avatar Aug 14 '22 06:08 milesj

System tasks now support shells in v1. I'm going to close this as we won't support multi-commands in a single task.

milesj avatar Mar 27 '23 19:03 milesj