go-task / task

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

Taskfile Scoped Variables #1030

Open ameergituser opened 1 year ago

ameergituser commented 1 year ago

I would like Taskfile scoped variables so that the behaviour of the parent taskfile or the included child taskfiles is not implicitly changed just by including a taskfile. This topic was touched on a few times with @andreynering and the latest discussion is in #1006.

You need this in use cases whereby multiple separate Taskfile projects are chained together in a parent/child relationship. And in this case, you don't own or necessarily know the inner details of these lower-layer included taskfiles.

Currently, you have to know every single variable that is globally scoped so that you don't use the same variable name in the parent or child taskfiles. It kind of defeats the purpose of taskfile inclusion to provide abstraction.

The worst is that if you don't go through every taskfile, you won't know when you are using a variable that changes the behaviour somewhere in some taskfile unintentionally.

@andreynering Thanks for the comment on #1006. I agree that for the next major version making variables scoped by Taskfile is a reasonable consideration and design decision, which would make maintaining taskfiles simpler as the behaviour would be a lot more predictable.

  1. Do you think it's feasible to add a taskfile setting to explicitly enable scoped variables in the current version?
  2. And for the future major version, this could be the default? and perhaps allow variable scope/overriding as an explicit feature?
apgrucza commented 1 year ago

I agree that variables scoped by Taskfile should be the default. Although we could add an option to explicitly allow variable sharing on particular includes, it's not ideal as the included task might still want to have a subset of its variables remain private. It's better for the included Taskfile to decide what's public and what's private. This could be achieved by introducing new public and/or private attributes.

I've noticed a lot of issues raised regarding the behaviour of variables and Taskfile inclusion. Examples are #454, #696, #778 and #996. It would be good to find a solution that addresses all of these issues. There seems to be two reasons that people use includes:

  1. to pull in tasks from the included file
  2. to pull in variables from the included file

I wonder whether it makes sense to decouple these and come up with a separate mechanism for sharing variables across Taskfiles.

As an alternative to the public/private idea, we could support a new file type (e.g. Taskvars.yml). This would basically be a cut-down Taskfile that only allows vars, env and dotenv attributes. The file would be loaded with a new attribute (e.g. var-files: ['Taskvars.yml']). Many other tools support loading variables from a file in this fashion.

If we make variables in Taskfiles always private, then var-files could become the only way of sharing variables across Taskfiles. The processing of all non-task-scoped variables could then be decoupled from the processing of Taskfile includes. This could help eliminate unexpected behaviour in this area, and may make it easier to resolve issues such as #778.

ameershira-uman commented 1 year ago

Yes it seems by default it should be private, and you have to explicitly expose or access the variables.

Could we address this by somehow accessing the variables by namespace? Similar to how tasks are accessed?

apgrucza commented 1 year ago

Could we address this by somehow accessing the variables by namespace? Similar to how tasks are accessed?

That's an interesting idea. It might be okay to do this for normal variables, but it may not be appropriate for environment variables. Environment variables are often processed by external programs, which will not handle there being a prefix on the environment variable name.

marco-m-pix4d commented 1 year ago

@aliculPix4D FYI (would address #696).

ricardogaspar2 commented 1 year ago

This would be great to have. I kinda understand the initial design of the taskfile - being composable and used like a mixin to inject variables; but on the other hand it makes more sense to have isolation and be able to build "self-contained" sub-taskfiles that one can copy and paste into other projects and just include them in the main taskfile. Clear examples are included taskfiles where the variables names are the same (e.g. DOCKER_IMAGE) which wasn't expected for the last taskfile that is included/imported to set the final value for it.

Since one can already import variables from another taskfile, i don't see a huge reason to not have such isolation.

Dom324 commented 7 months ago

I also agree that the current behavior is confusing and non intuitive. My use case:

version: '3'

vars:
  CPPFLAGS: -Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic -Wold-style-cast -Ilib/some_library/ ...

includes:
  some_library:
    // some_library, which defines it's own `CPPFLAGS`
    taskfile: ./lib/some_library/Taskfile.yml
    dir: ./lib/some_library/

tasks:
  compile_something:
    deps: some_library:default
    cmds:
      // Here are wrong `CPPFLAGS` used
      - '{{.CXX}} {{.CPPFLAGS}} -o a.out main.o predictor.o'

Including some_library overwrites outer variables and breaks everything. This makes it highly impractical to download a third party library (which also uses Taskfile, because it's great) and include it to your Taskfile and call it as a dependency. That library will break all of your tasks because it might use same names for some of the variables.

I think that the includes should be more modular and self enclosed - including a module should not have an effect on the outer world, unless you specifically touch it's internals.