go-task / task

A task runner / simpler Make alternative written in Go
https://taskfile.dev
MIT License
11.36k stars 613 forks source link

Option to ignore errors to run subsequent tasks but still fail "calling" task #987

Closed bkis closed 1 year ago

bkis commented 1 year ago

Let's say I have the following Taskfile.yml:

tasks:

  start-services:
    cmds:
      - echo Starting services...

  stop-services:
    cmds:
      - echo Stopping services...

  run-tests:
    cmds:
      - echo Running app...
      - exit 1

  test:
    cmds:
      - task: start-services
      - task: run-tests
      - task: stop-services

The test task runs three other tasks in sequence (as this is important here, I'm not using preconditions):

  1. start-services starts services needed by the (integration) test suite
  2. run-tests runs the test suite (which fails for demonstration purposes)
  3. stop-services tears down all services etc...

The result:

task: [start-services] echo Starting services...
Starting services...
task: [run-tests] echo Running app...
Running app...
task: [run-tests] exit 1
task: Failed to run task "test": task: Failed to run task "run-tests": exit status 1

Now I naturally want to always execute stop-services (which doesn't happen in the example above), even if my tests fail. To achieve that, I add ignore_error to the run-tests task:

# ...

  run-tests:
    cmds:
      - echo Running app...
      - exit 1
    ignore_error: true

#...

The result:

task: [start-services] echo Starting services...
Starting services...
task: [run-tests] echo Running app...
Running app...
task: [run-tests] exit 1
task: [stop-services] echo Stopping services...
Stopping services...

That's cool - it stops my testing services now. But the whole task (test) now exits with code 0 although my tests failed. It would be nice if I could configure it to somehow exit with a non-zero exit code if any sub-task failed even if errors are ignored.

I see two ways to do that:

  1. Add an additional option to tasks that makes them exit with a certain exit code if there was a failure, even in subtasks with ignore_error (e.g. on_error: 101 would allow to set the specific code to use, or fail_on_error: true, you get it...). But that would be not very intuitive, I think. A much better one would be this:
  2. Add an additional option to tasks that forces them to be run, even if something that ran before failed. E.g. force_run: true. Tasks with force_run: true would then always be run whenever it's their "turn" - nothing else would have to change. Task would just have to check whether there are subsequent tasks after the failing one that have this option set and run them normally. The overall ("parent"?) task should still exit with a non-zero code then.
pd93 commented 1 year ago

@bkis You should be able to use the defer keyword for your use case (or any scenario where you require some form of clean up):

version: '3'

tasks:

  start-services:
    cmds:
      - echo Starting services...

  stop-services:
    cmds:
      - echo Stopping services...

  run-tests:
    cmds:
      - echo Running app...
      - exit 1

  test:
    cmds:
      - defer: {task: stop-services}
      - task: start-services
      - task: run-tests

Please let us know if this works for you or not.

bkis commented 1 year ago

It does, thank you! I guess for me it wasn't clear from the documentation that defered commands will run no matter what:

Alternative to cmd, but schedules the command to be executed at the end of this task instead of immediately. This cannot be used together with cmd.

...is all it says.

But yes, this completely does what I need. Thank you!