Skip to content

Add special variable for task working directory #2102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jaynis opened this issue Mar 7, 2025 · 11 comments · Fixed by #2186 · May be fixed by #2103
Open

Add special variable for task working directory #2102

jaynis opened this issue Mar 7, 2025 · 11 comments · Fixed by #2186 · May be fixed by #2103
Labels
area: variables Changes related to variables.

Comments

@jaynis
Copy link
Contributor

jaynis commented Mar 7, 2025

Description

There are various special variables available but none of them reflects the working directory of a respective task. The ones that come closest are:

  • USER_WORKING_DIR which contains the directory where task has been called from, but does not honor the -d <dir> command line parameter
    and
  • TASK_DIR which merely contains what has been configured under dir: in a task of the Taskfile.yml file and does not even resolve template expressions.

I see two different solutions to this problem:

  1. Either change the behavior of USER_WORKING_DIR so that it takes the -d parameter into account, because I see only very little benefit in having a variable which contains the directory where task has been called from when a different working directory has been explicitly set with -d
  2. Introduce a new variable such as TASK_WORKING_DIR which contains the desired dir and does not break the current behavior of USER_WORKING_DIR.

The current use case which I have is as follows: I have a root directory containing a Taskfile.yml file and some subdirectories which doesnt have Taskfiles.yml files. I now want to reuse the logic of the Taskfile.yml from the root directory in the subdirectories as described here. This works well if I navigate to a subdirectory and call the respective task from there, however, when I call task from the root directory and specify the subdirectory with the -d parameter it doesnt work as USER_WORKING_DIR still contains the root directory as outlined above.

@task-bot task-bot added the state: needs triage Waiting to be triaged by a maintainer. label Mar 7, 2025
@jaynis jaynis linked a pull request Mar 7, 2025 that will close this issue
@andreynering andreynering added type: feature area: variables Changes related to variables. and removed state: needs triage Waiting to be triaged by a maintainer. labels Mar 10, 2025
@jberkenbilt
Copy link
Contributor

I was running into something similar when I came across this. Upon further study, I think -d/--dir only sets the directory in which to start the search for the taskfile. It doesn't change the working directory. This could probably be clearer in the documentation.

Observe. With this Taskfile.yml and an empty subdir:

version: '3'
tasks:
  default:
    cmds:
      - pwd
      - echo {{ .USER_WORKING_DIR }}

% task
task: [default] pwd
/Users/ejb/source/examples/task/bugs/dir
task: [default] echo /Users/ejb/source/examples/task/bugs/dir
/Users/ejb/source/examples/task/bugs/dir

% task --dir subdir
task: [default] pwd
/Users/ejb/source/examples/task/bugs/dir
task: [default] echo /Users/ejb/source/examples/task/bugs/dir
/Users/ejb/source/examples/task/bugs/dir

% (cd subdir; task)
task: [default] pwd
/Users/ejb/source/examples/task/bugs/dir
task: [default] echo /Users/ejb/source/examples/task/bugs/dir/subdir
/Users/ejb/source/examples/task/bugs/dir/subdir

Now create subdir/Task.yml:

version: '3'
tasks:
  default:
    cmds:
      - echo in subdir
      - pwd
      - echo {{ .USER_WORKING_DIR }}

Now:

% task --dir subdir
task: [default] echo in subdir
in subdir
task: [default] pwd
/Users/ejb/source/examples/task/bugs/dir/subdir
task: [default] echo /Users/ejb/source/examples/task/bugs/dir
/Users/ejb/source/examples/task/bugs/dir

So it seems that --dir is not setting the working directory, but is setting the directory from which task starts the search for Taskfile.yaml.

@jberkenbilt
Copy link
Contributor

In case I'm right, see #2123.

@jaynis
Copy link
Contributor Author

jaynis commented Mar 14, 2025

Hi @jberkenbilt . Thank you for your detailed response. I think you are indeed right, but I dont see how your observation is different from mine. Maybe it is just wording. So my understanding is was/is:

  • USER_WORKING_DIR contains the working directory in the sense of the directory where task has been called from
  • --dir sets the directory where task starts looking for Taskfile.yml files

All I wanted to achieve is to have a special variable which contains the path which has been set with --dir so that I can use this to specify the task directory with dir: in my task file. As already stated in my initial post, this can be achieved already now by navigating to that directory first and executing task from there, but I would like to have a way to do this without having to use a tiny script such as (cd subdir; task).
I called the new variable to contain that directory TASK_WORKING_DIR because it is the directory task is/starts working on, in contrast to USER_WORKING_DIR, the directory task has been called from by the user. I am also open to renaming it to something more verbose like TASK_DIR_PARAM but this could cause confusion with the already existing TASK_DIR variable.

@jberkenbilt
Copy link
Contributor

jberkenbilt commented Mar 14, 2025

Oh, @jaynis, I see. I guess there are really three different things.

Suppose you have this Taskfile:

version: 3
tasks:
  default:
    cmds:
      - echo pwd = $(pwd)
      - echo USER_WORKING_DIR = {{ .USER_WORKING_DIR }}
      - echo TASK_DIR = {{ .TASK_DIR }}

and this directory structure:

/tmp/z
     └── a/
         └── b/
             ├── Taskfile.yml
             ├── c/
             └── d/
  • Where you were when you ran task
  • The directory where you started the search for Taskfile (specified by --dir, currently not available)
  • The directory where the Taskfile actually was

If you are in /tmp/z/a/b/c and run task -d ../d, there's no way to know about ../d's path. You get this:

task: [default] echo pwd = $(pwd)
pwd = /tmp/z/a/b
task: [default] echo USER_WORKING_DIR = /tmp/z/a/b/c
USER_WORKING_DIR = /tmp/z/a/b/c
task: [default] echo TASK_DIR = /tmp/z/a/b
TASK_DIR = /tmp/z/a/b

Your first comment says you don't see much of a use case for knowing where task was started from when run with -d, but I think the use case is very similar to your use case. The use case is that you have a collection of utility task files, and you are running them somewhere unrelated. Like maybe you have a Taskfile somewhere to help you build docker images. You might be in /projects/something/docker/ and run task -d /projects/taskfiles/docker-util.

I still think the problem is that -d doesn't actually change the working directory. I could see that it would be useful to know the path of where -d actually pointed to it, which might be different from either the current working directory or the directory where the task was found.

Anyway, I don't think what I'm saying contradicts what you're saying; I'm just adding the nuance that I think, regardless of whether the feature you want is there, the documentation for --dir is misleading.

Anyway, I'm new here -- I just started playing with taskfile today and don't have any connection with the project. :-)

@jaynis
Copy link
Contributor Author

jaynis commented Mar 14, 2025

Well, as you must have noticed in your PR, strictly speaking the --dir parameter does not even state that it sets the working directory, but merely the directory of execution. If you interpret execution with directory where taskfile starts executing Taskfile.yaml files, then I would even say the documentation is kind of okayish even now. But you can of course very easily interpret this differently, therefore I am not saying that your PR doesnt make sense. 😃

I agree that having a variable which contains the directory from which task has been called from (USER_WORKING_DIR) makes sense in any case. Your example demonstrates this very well. When I created this issue I only had this use case in mind.

andreynering added a commit that referenced this issue Apr 19, 2025
Closes #2102
Closes #2103

Co-authored-by: jaynis <kranz.jannis@googlemail.com>
@andreynering
Copy link
Member

Hi @jaynis,

I gave this some thought, and I decided to go in a slightly different route.

The whole purpose of USER_WORKING_DIR is to provide an easy way to run tasks in a directory different than the one where the Taskfile is located. The fact that --dir wasn't accounted was a misight IMO, so on #2186 I just made USER_WORKING_DIR respect --dir, if given.

This looked much simpler to be than adding yet another special variable, which would confuse in the end.

@jaynis
Copy link
Contributor Author

jaynis commented Apr 19, 2025

Hi @andreynering and thank you for your explanation, but with the change you have made it is no longer possible to execute a task from a Taskfile.yaml located in another directory, on the current directory, is it?

Suppose you have a central Taskfile.yaml with a bunch of utility tasks that you want to be able to call from anywhere. With --dir it used to be possible to specify that central directory and run one of those tasks in the current working directory by setting dir: to USER_WORKING_DIR. This is why I suggested adding another variable.

I agree that there are already quite some special variables, but overall I in fact think it would be useful to have:

  • One variable which contains the current working directory
  • One variable which contains the directory where task looks for the Taskfile.yaml

@pd93
Copy link
Member

pd93 commented Apr 27, 2025

The whole purpose of USER_WORKING_DIR is to provide an easy way to run tasks in a directory different than the one where the Taskfile is located. The fact that --dir wasn't accounted was a misight IMO, so on #2186 I just made USER_WORKING_DIR respect --dir, if given.

@andreynering I don't think this is correct. The purpose of USER_WORKING_DIR is to contain the directory that the user is in when they execute the task command. This is so that users can write tasks that are contextually aware of where the user is at the time of invocation. This was added at the same time as searching recursively up the file tree for Taskfiles as that change meant that the directory the user is currently in can be different to the root taskfile location and the directory the task is executing in. I think this is actually a breaking change that will stop some dynamic taskfiles from working.

However, I do agree that we need to think carefully about the naming of our variables as we now have a lot of special variables to represent various directories.

I actually suggest that we revert this until we've had more time to discuss.

@pd93
Copy link
Member

pd93 commented Apr 27, 2025

Reopening this as #2186 has been reverted in 68d5095 and released in v3.43.3. The changes in #2186 caused the issues described in #2206, #2207 and #2208.

@jaynis I've also re-opened your PR for now so we can continue to discuss the best way forwards.

@pd93 pd93 reopened this Apr 27, 2025
@joeblew999

This comment has been minimized.

@pd93
Copy link
Member

pd93 commented Apr 29, 2025

@jaynis Random thought. My understanding is that you want this value to always match the value given by the --dir flag.

If this is the case, then CLI_DIR makes sense as a name to me. This matches the other CLI_* variables which are assigned the values of flags. Such as CLI_FORCE or CLI_SILENT etc. These are much easier to set as they are declared on the globals variable in task.go and do not need to be set on the Executor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: variables Changes related to variables.
Projects
None yet
6 participants