Skip to content

Explicit environment variable is not honoured when calling another task #593

Closed

Description

@chris-garrett
  • Task version: 3.3.0
  • Operating System: Windows 10 (git bash)

Taskfile

version: '3'

vars:
  VAR_GLOBAL: IM_VAR_GLOBAL

env:
  ENV_GLOBAL: IM_ENV_GLOBAL

tasks:

  env_caller:
    cmds: 
      - { task: env_subtask, env: { ENV_CALLER_ARG: IM_ENV_CALLER_ARG }, vars: { VAR_CALLER_ARG: IM_VAR_CALLER_ARG }}
    env: { ENV_CALLER: IM_ENV_CALLER }
    vars: { VAR_CALLER: IM_VAR_CALLER }

  env_subtask:
    cmds:
      - echo ENV_GLOBAL=$ENV_GLOBAL
      - echo ENV_CALLER=$ENV_CALLER 
      - echo ENV_CALLER_ARG=$ENV_CALLER_ARG 
      - echo VAR_GLOBAL={{.VAR_GLOBAL}}
      - echo VAR_CALLER={{.VAR_CALLER}}
      - echo VAR_CALLER_ARG={{.VAR_CALLER_ARG}}

Output

$ ./task env_caller
ENV_GLOBAL=IM_ENV_GLOBAL
ENV_CALLER=
ENV_CALLER_ARG=
VAR_GLOBAL=IM_VAR_GLOBAL
VAR_CALLER=
VAR_CALLER_ARG=IM_VAR_CALLER_ARG

I expect that ENV_CALLER_ARG should be valid in env_subtask. Am I missing something?

Activity

  1. aminya commented on Nov 14, 2021

    @aminya
    Contributor

    I hit a similar situation. Although I specify CC and CXX, it still uses the global environment variable.

    # https://taskfile.dev
    version: "3"
    
    tasks:
      init_debug_mingw:
        env:
          CC: gcc
          CXX: g++
        cmds:
          - echo {{.CC}}

    clang is printed instead of GCC

    This is also related to #185

  2. kerma commented on Dec 4, 2021

    @kerma
    Contributor

    There are couple of different issues here. @chris-garrett your env_caller env and vars values are only applicable for shell commands called within that command block. If you call another task with -task: env_subtask you can only pass vars to it. env block is ignored.

    cmds:
    - task:env_subtask
      vars: 
         VAR_CALLER_ARG: IM_VAR_CALLER_ARG

    @aminya you're mixing up vars and env syntax. Both commands work here:

    # https://taskfile.dev
    version: "3"
    
    tasks:
      one:
        vars:
          CC: gcc
        cmds:
          - echo {{.CC}}
    
      two:
        env:
          CC: gcc
        cmds:
          - echo $CC
  3. chris-garrett commented on Dec 5, 2021

    @chris-garrett
    ContributorAuthor

    @kerma welcome to the collabs list!

    There are couple of different issues here. @chris-garrett your env_caller env and vars values are only applicable for shell commands called within that command block. If you call another task with -task: env_subtask you can only pass vars to it. env block is ignored.

    Can you explain why this is? Is this actually the behaviour that is desired?

    Without this we are forced to convert ENVs to VARs and carry them around until you convert back to ENV when you need it. It's very clumsy on large projects.

  4. kerma commented on Dec 6, 2021

    @kerma
    Contributor

    @chris-garrett I'm new to the project, so cannot tell the historical reasons, but atm it's how it's implemented.

    There is another issue slightly related to this: #585.

    To me it feels like task is missing a well documented context which is creating the confusion. To be honest I think it may be something I'd look into. Having a simple context and inheritance rules for dir, env and vars would probably make life easier for everyone. However it would be a major change and would need a new taskfile version.

  5. dustinlharrison commented on Jul 19, 2023

    @dustinlharrison

    @kerma and @chris-garrett I "discovered" the same behaviour as well, and the behaviour is documented:

    After much pain, testing and searching, I did finally realize that a shell command was being handled different than a task command from the task API reference:

    env map[string]Variable A set of environment variables that will be made available to shell commands.

    This was surprising since the schema suggests that it applies to all uses of env within the current task declaration. Whether this is intended, a bug or a feature request, I think there is a very strong case for it to work, and if not, then
    env should be removed from the target declaration and only be supported by individual cmd declarations.

    I think making it work for both task invocation and shell invocation encourages reusability of tasks and 12 factor apps.

    version: 3
    
    tasks:
      start:
        vars:  # Passing in config by using vars is recommended
          NAME: '{{ .NAME | default "my-service" }}'
        env:
          PGDATABASE: '{{.NAME}}-db'
        cmds:
          - echo "Works here as promised: $PGDATABASE"
          - task: start-db # PGDATABASE is not passed in even though it is at the task level.
      start-db:
        cmds:
         - psql # Invoked by `start` or directly from command line with env configured (12 factor)

    @andreynering I think this issue was opened before the labelling system was developed, can you consider applying the appropriate labels since I don't have permission?

  6. treybrisbane commented on Jul 12, 2024

    @treybrisbane

    This bit me as well, today. 😢

    Is it difficult to fix?

    If it's not practical/desirable to have the env vars implicitly apply to sub-task calls, could/should we instead perhaps give sub-task calls a dedicated env block to allow passing env vars explicitly?
    E.g.

    version: 3
    
    tasks:
      caller:
        cmds:
          - task: callee
            env:
              FOO: bar
    
      callee:
        cmds:
          - echo "${FOO}"

    This would fit nicely with sub-task calls' existing var block, and at least give us some way of passing env vars to sub-tasks.

  7. trim21 commented on Jul 12, 2024

    @trim21
    Contributor

    yes, I think we should add a env option to task call.

  8. uded commented on Feb 20, 2025

    @uded

    I would love to upvote this one. Would make my Taskfile structure much less complex...

  9. added theissue type on Feb 21, 2025
  10. added
    area: envChanges related to environment variables.
    and removed on Feb 21, 2025
  11. trulede commented on Jan 18, 2026

    @trulede
    Contributor

    In Task vars and envars are different things. Vars are used to exchange values between tasks (calls, includes, deps etc) and build command expression with template expansion based on those vars. Envars are used to inject values into the command environment for values that cannot be provided by a command expression.

    Internally, vars and envars are represented by the same type, and that sometimes tempts people with interesting ideas ...

    But actually, the existing mechanism is quite capable. Passing envars to a called task can be done with dotenv files.

    To set envars for a Task, you have (at least) these options:

    • Use envars from the calling environment.
    • Set global envars in the taskfile.
    • Set task envars in the task, and use vars passed to task to set these envars.
    • Use a dotenv file specified at the taskfile level.
    • Use a dotenv file specified at the task level, this file is read when the task is run, so you can generate it beforehand.
    • Use a YAML anchor to make the specification of vars and envars more efficient (DRY principle).
    • Use a .REF to reference vars which is sometimes useful.

    This taskfile demonstrates most of those methods:

    version: '3'
    
    silent: true
    
    vars:
      FOO_VAR: tf_var_foo
    
    env:
      FOO_ENVAR: tf_envar_foo 
    
    tasks:
      default:
        cmds:
          - task: override
          - task: parameter
            vars:
              P_FOO_VAR: tp_var_foo
              P_FOO_ENVAR: tp_envar_foo
          - cmd: echo "FOO_ENVAR=tdot_envar_foo" > tdotenv
          - task: dotenv
          - task: anchor  # Needs PR #2551.
      anchor-map:
        internal: true
        vars: &var_anchor
          FOO_VAR: map_var_foo
        env: &env_anchor
          FOO_ENVAR: map_envar_foo
      override:
        vars:
          FOO_VAR: t_var_foo
        env:
          FOO_ENVAR: t_envar_foo
        cmds: 
          - cmd: echo "{{.TASK}}"
          - cmd: echo "  var FOO_VAR = {{.FOO_VAR}}" # t_var_foo
          - cmd: echo "  var FOO_ENVAR = {{.FOO_ENVAR}}" # tf_envar_foo
          - cmd: echo "  env FOO_ENVAR = $FOO_ENVAR" # t_envar_foo
      parameter:
        vars:
          FOO_VAR: '{{.P_FOO_VAR | default "no foo var"}}'
        env:
          FOO_ENVAR: '{{.P_FOO_ENVAR | default "no foo envar"}}'
        cmds: 
          - cmd: echo "{{.TASK}}"
          - cmd: echo "  var FOO_VAR = {{.FOO_VAR}}" # tp_var_foo
          - cmd: echo "  var FOO_ENVAR = {{.FOO_ENVAR}}" # tf_envar_foo
          - cmd: echo "  env FOO_ENVAR = $FOO_ENVAR" # tp_envar_foo
      dotenv:
        dotenv: [tdotenv]
        cmds: 
          - cmd: echo "{{.TASK}}"
          - cmd: echo "  var FOO_VAR = {{.FOO_VAR}}" # tf_var_foo
          - cmd: echo "  var FOO_ENVAR = {{.FOO_ENVAR}}" # tf_envar_foo
          - cmd: echo "  env FOO_ENVAR = $FOO_ENVAR" # tdot_envar_foo
      anchor: # Needs PR #2551, build/install PR and remove following xx to enable. 
        xxvars:
          <<: *var_anchor
        xxenv:
          <<: *env_anchor
        cmds: 
          - cmd: echo "{{.TASK}}"
          - cmd: echo "  var FOO_VAR = {{.FOO_VAR}}" # map_var_foo
          - cmd: echo "  var FOO_ENVAR = {{.FOO_ENVAR}}" # tf_envar_foo
          - cmd: echo "  env FOO_ENVAR = $FOO_ENVAR" # map_envar_foo
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: envChanges related to environment variables.

    Fields

    No fields configured for feature.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions