Skip to content

Proposal: Merge vars and env #2036

@pd93

Description

@pd93

One of the things I see a lot, is confusion about the differences between variables and environment variables. They essentially serve the same purpose (holding data), but they have a few differences:

  • Both can be parsed into Task via the CLI as strings (though they have different syntaxes)
    • TASK_VAR=foo task ... (environment variable)
    • task ... VAR=foo (variable)
  • Both can be defined in the Taskfile (using different keywords) at a global or task level.
    • vars can also be set when calling another task, but env cannot.
  • vars can be of any type. env only supports strings (though sort of works with other scalar values).
  • vars are output using templating syntax and an env is output using shell variable syntax.
    • $FOO (environment variable)
    • {{.FOO}} (variable)
  • They have slightly different inheritance/scoping rules.
    • At this point, I'm not even sure what the differences are without investigating properly.
  • Environment variables defined on the CLI/shell are available as variables, but ones defined using the env keyword are not.

I'm not convinced that any of these distinctions are necessary and I feel like they add an additional layer of confusion for both new users and people wanting to contribute to the project.

Therefore, I propose removing the env key entirely. vars would then inherit from the system environment and be overridable in Task. If a variable is not a string, it would be output using the stringer version of its value (%v). All of the features below would then apply to vars:

  • Variables are only passed into Task via the shell environment (whether that be in an .rc file of a shell command).
    • No more task ... VAR=foo syntax.
  • Variables can be defined at a global or task level and passed when calling dependant tasks.
  • Variables can be of any type, though they are still limited to strings when passed via the environment variables.
  • Variables are output using templating syntax OR shell variable syntax depending on the user's needs.
  • Variables have a consistent inheritance/scoping model as defined in Proposal: Variable scope and inheritance #2035.

Before:

version: '3'

env:
  FOO: 'foo'
vars:
  BAR: 'bar'

tasks:
  default:
    cmds:
      - echo '$FOO'
      - echo '{{.FOO}}'
      - echo '$BAR'
      - echo '{{.BAR}}'
foo


bar

After:

version: '3'

vars:
  FOO: 'foo'
  BAR: 'bar'

tasks:
  default:
    cmds:
      - echo '$FOO'
      - echo '{{.FOO}}'
      - echo '$BAR'
      - echo '{{.BAR}}'
foo
foo
bar
bar

One caveat to this proposal is that sometimes temporary variables are needed to perform operations and we don't always want to pollute the environment with these variables. To solve this, we can allow variables to be marked as internal, just like we would with tasks. This makes variables consistent with tasks and fulfills the same purpose that variables previously did.

Since most Task commands execute in a fairly specific context, this shouldn't be needed the majority of the time.

version: '3'

vars:
  FOO: 'foo'
  BAR:
    value: 'bar'
    internal: true
  BAZ:
    sh: 'echo "baz"'
    internal: true
  QUX:
    ref: 'lower .BAZ'
    internal: true

tasks:
  default:
    cmds:
      - 'echo "foo: {{.FOO}}"'
      - 'echo "bar: {{.BAR}}"'
      - 'echo "baz: {{.BAZ}}"'
      - 'echo "qux: {{.QUX}}"'
foo: foo
bar:
baz:
qux:

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: variablesChanges related to variables.breaking changeChanges that are not backward compatible.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions