task
task copied to clipboard
TASKFILE_DIR always resolves to ROOT_DIR
- Task version: Task version: v3.15.0 (h1:k1s4CXeADCJyRt8tR67XC+gusYR0BL6d/r3AIOeE98c=)
- Operating System:Linux 5.10.102.1-microsoft-standard-WSL2
Example Taskfile showing the issue
I'm trying to use TASKFILE_DIR in an included Taskfile.yml file but it always seems to resolve to the absolute path of the root Taskfile.yml file.
/home/postlund/foo/Taskfile.yml
version: "3"
includes:
subdir: ./subdir
tasks:
default:
deps: [subdir:foobar]
/home/postlund/foo/subdir/Taskfile.yml
version: "3"
tasks:
foobar:
cmds:
- echo {{.TASKFILE_DIR}}
Running task:
$ cd /home/postlund/foo
$ task
task: [subdir:foobar] echo /home/postlund/foo
/home/postlund/foo
I might have misunderstood something, but I would have expected TASKFILE_DIR being resolved to /home/postlund/foo/subdir in this case.
Hi @postlund,
It will return the right directory if you change the execution directory to be the subdir as well:
includes:
subdir:
taskfile: ./subdir
dir: ./subdir
To me the current behavior is the expected, and we could improve the documentation to make it clearer.
But if anyone disagree, let me know.
@andreynering Ok, then I understand (I think). Is there any reason why it wouldn't always point to the directory of the Taskfile.yml it is "used" in instead? At least to me that seems way more obvious.
@andreynering Hi, I feel that the default behavior should be that the tasks are run from the location of the specific included taskfile.
This is the behavior if you run that specific taskfile on its own.
It's also the behavior if you only use one taskfile.
For me it is a secondary function to run tasks included in other taskfiles in the root of the parent taskfile.
I use task as a build tool and write many separated libraries/projects. Each of them have thier own taskfiles. So when I include these libraries in a main project where the one lib would include the other and so forth, it's natural to expect that the taskfile is run from where it was intended to run, and was probably tested that way too.
@ameergituser We could consider changing the default behavior in the future, but on v3 it would be a backwards incompatible change, so we need at least to wait for v4 (which I think will take a long time to happen).
Also, note that the expected behavior change from user to user. I've seem many people having a directory like .taskfiles/ and including them on root expecting those tasks to run on root.
Other (like me) more often setup them to run on the Taskfile directory.
So this decision is not a matter of right and wrong, but what most people would do most of the time.
@andreynering Maybe the behavior could be altered via a global setting? Just like you can change run for instance.
@andreynering I agree with you on the breaking backwards compatibility issues, and the use case aspect.
Chiming in... I found this same issue thinking I had found a bug. I expect TASKFILE_DIR to be the dir of the Taskfile for the command I've sent, not the root/including taskfile (which I'd assume was ROOT_DIR)
If taskfile1 includes taskfile2 and my command is task taskfile1:taskfile2:command, then I'd want TASKFILE_DIR to be the dir of taskfile2...
Hello, everyone! I am also found "expected" behavior a little bit unexpected. But for me that is totally ok - just add one more string. And I found another case when I specified dir parameter and it still work.
In my case I have set of 3 Taskfile.yml:
.
├── Taskfile.yml
└── api
├── Taskfile.yml
└── v1
├── Taskfile.yml
└── openapi.yml
I prefer to have a lot of Taskfile.yml over have one single big includes: section. Also I came from C++ background and I did work with cmake so this is ok for me. Anyway, if I will write next stuff:
# /Taskfile.yml
version: '3'
includes:
api:
taskfile: ./api
dir: ./api
# /api/Taskfile.yml
version: '3'
includes:
v1:
taskfile: ./v1
dir: ./v1
# /api/v1/Taskfile.yml
version: '3'
tasks:
test:
cmds:
- echo {{.TASKFILE_DIR}}
And I will run command task api:v1:test then I will get /api as output. But if I jump into /api directory and run v1:test then I will get the correct output.
Let's summarize it. I expect that I can build a tree of any deep and variable should defines correct. But it is looks like I can work only with second level of deep.
Hi all 👋 - this has confused me too with the expected behaviour.
The docs state the following under https://taskfile.dev/api/#special-variables :
ROOT_DIR | The absolute path of the root Taskfile.
TASKFILE_DIR | The absolute path of the included Taskfile.
USER_WORKING_DIR | The absolute path of the directory task was called from.
The wording does imply what people in this thread expected, and make the current implemented effect sound like a bug 😅.
The USER_WORKING_DIR and the ROOT_DIR should actually already be able cover the mentioned current use cases as they have the same outputted value as TASKFILE_DIR without the dir arg provided.
If I have a nested taskfile containing the following:
tasks:
test:
cmds:
- echo {{ .TASKFILE_DIR }}
- echo {{ .ROOT_DIR }}
- echo {{ .USER_WORKING_DIR }}
These all output the same directory when invoked, regardless of whether I execute it in the root or from the directory it is defined.
I can make it work like others in this thread by specifying the dir argument at the include level, which then changes the TASKFILE_DIR . It feels like a potentially better solution would be to have a new {{ .TASKFILE_WORKING_DIR }} that inherits that value instead and change TASKFILE_DIR to what implies? That way the same Taskfile could actually be reused with different directories too.
My use case is nested tasks wanting to send output to the same directory relative to where the file is defined, regardless of where it is run, i.e: all goes to output:
tasks:
test:
cmds:
- echo "test" > {{ .TASKFILE_DIR }}/../../task1_output
Taskfile.yaml
output/
└── task1_output
my_tasks/
├── task1/
│ └── Taskfile.yaml
└── task2/
└── Taskfile.yaml
It also seems that manually specifying the dir only works for 1 level deep, and any 3rd level or deep nested tasks return the 2nd level TASKFILE_DIR when echo'ed - looks like this has been raised before here @: https://github.com/go-task/task/issues/894
This works as expected in the latest version.