Skip to content

Regression in v3.49.0: Global sh: variables resolve to empty string in included Taskfiles #2720

@JonZeolla

Description

@JonZeolla

Description

After upgrading from Task v3.48.0 to v3.49.0, global variables defined with sh: no longer resolve correctly when a Taskfile has includes:. The sh: variable resolves to an empty string, causing downstream variables that reference it via templating to produce incorrect values.

This regression was introduced by #2632 (commit 2cdd7d3), which shipped in v3.49.0.

Root Cause

The added line in compiler.go (line 118):

c.TaskfileVars = templater.ReplaceVars(c.TaskfileVars, &templater.Cache{Vars: result})

This mutates c.TaskfileVars after sh: dynamic variables have already been resolved by rangeFunc (lines 112-116), destroying their cached results.

Step-by-step breakdown:

  1. Lines 112-116 (rangeFunc): Iterates c.TaskfileVars. For sh: vars like DYNAMIC_VAR, it calls HandleDynamicVar() which executes the shell command and stores the resolved value in the result map. At this point, result["DYNAMIC_VAR"] = "hello"

  2. Line 118 (the bug): ReplaceVars re-processes the original, unmodified c.TaskfileVars. In ReplaceVarWithExtra (templater.go):

  3. Any subsequent reference to DYNAMIC_VAR sees Value: nil → resolves to empty string.

Suggested Fix

The ReplaceVars call should only process variables that actually have Ref values set, leaving already-resolved sh: variables untouched:

for k, v := range c.TaskfileVars.All() {
    if v.Ref != "" {
        resolved := templater.ResolveRef(v.Ref, &templater.Cache{Vars: result})
        c.TaskfileVars.Set(k, ast.Var{Value: resolved})
    }
}

Minimal Reproducer

Taskfile.yml:

version: "3"

includes:
  other:
    taskfile: ./Other.yml
    internal: true

vars:
  DYNAMIC_VAR:
    sh: echo "hello"
  DERIVED_VAR: "{{.DYNAMIC_VAR}} world"

tasks:
  default:
    cmds:
      - 'echo "DYNAMIC_VAR={{.DYNAMIC_VAR}}"'
      - 'echo "DERIVED_VAR={{.DERIVED_VAR}}"'
    silent: true

Other.yml:

version: "3"

tasks:
  noop:
    cmds:
      - "true"

v3.48.0: DYNAMIC_VAR=hello, DERIVED_VAR=hello world
v3.49.0: DYNAMIC_VAR=, DERIVED_VAR= world

Environment

  • Task version: v3.49.0 (works on v3.48.0)
  • OS: Ubuntu 24.04 (linux/arm64, GitHub Actions runner)
  • Installed via: go-task/setup-task@v1.0.0 (no version pin, so it picked up v3.49.0 automatically)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions