go-task / task

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

`run: once` not working for a task included multiple times #1498

Open maxmzkrcensys opened 7 months ago

maxmzkrcensys commented 7 months ago

When multiple task files include the same file and then depend on the same task, the depended on task gets executed twice even when run: once is set.

./tools/input

./tools/taskfile.yml
version: "3"

tasks:
  exe:
    run: once
    sources:
      - ./input
    generates:
      - ./output
    cmds:
      - touch output

./lib/a/taskfile.yml
version: "3"

includes:
  tools:
    taskfile: ../../tools
    dir: ../../tools
    internal: true

tasks:
  lib:
    deps:
      - tools:exe
    cmds:
      - touch a

./lib/b/taskfile.yml
version: "3"

includes:
  tools:
    taskfile: ../../tools
    dir: ../../tools
    internal: true

tasks:
  lib:
    deps:
      - tools:exe
    cmds:
      - touch b

./taskfile.yml
version: "3"

tasks:
  all:
    deps:
      - a:lib
      - b:lib

includes:
  a:
    taskfile: ./lib/a
    dir: ./lib/a

  b:
    taskfile: ./lib/b
    dir: ./lib/b
task all
task: [a:tools:exe] touch output
task: [b:tools:exe] touch output
task: [b:lib] touch b
task: [a:lib] touch a

In the setup I have 4 taskfiles. tools/taskfile.yml defines building a tool that is needed to build the a and b lib. lib/a/taskfile.yml and lib/b/taskfile.yml both include tools/taskfile.yml and depend on the building of the tool. The root taskfile.yml includes lib/a and lib/b and defines an all task to build both lib/a and lib/b.

Even with run: once set in the task that builds the tool, the task gets run twice.

Note that if the taskfiles are collapsed into a single task file, this issue is not present.

version: "3"

tasks:
  tools:exe:
    run: once
    sources:
      - ./tools/input
    generates:
      - ./tools/output
    cmds:
      - touch ./tools/output

  a:lib:
    deps:
      - tools:exe
    cmds:
      - touch lib/a

  b:lib:
    deps:
      - tools:exe
    cmds:
      - touch lib/b

  all:
    deps:
      - a:lib
      - b:lib
task all
task: [tools:exe] touch ./tools/output
task: [a:lib] touch lib/a
task: [b:lib] touch lib/b
maxmzkrcensys commented 7 months ago

Would it make sense to use the hash of location instead of the Task.Task? Looking at what fields are available in Task, that looks like the quickest way to get a unique id for the task no matter how it's included.

Additionally, would it make sense to add a new value to the run enum to differentiate once per include vs once across all includes?

Happy to put up a PR if I'm going down the right track for this