Skip to content

Dynamic variables in sources cause glob expansion to hang due to unpopulated placeholders and symlink loops #2400

@junhaoliao

Description

@junhaoliao

Description

When using dynamic variables (defined via sh:) in a task's sources list, those variables such as {{.VAR}}/**/* are not properly populated during the checksum phase (FastCompiledTask()), leading to malformed glob patterns like /**/*. After PR #2075 (which replaced zglob with mvdan/sh/expand.Fields), this issue has become critical as the new globbing implementation unconventionally recursively follows symlinks, causing infinite loops when encountering symlink cycles.

This results in task hanging indefinitely while attempting to resolve these malformed globs.

Steps to Reproduce

  1. Create a directory structure:
    mkdir ./parent
    touch ./parent/test.txt
  2. Create the Taskfile.yaml as specified in "Example Taskfile"
  3. Run: task task-1
  4. Observe that the process hangs.
  5. Optionally trace with:
    strace -e openat -f task task-1 2>&1 | grep ELOOP
    
    You'll see repeated ELOOP errors indicating symlink recursion.

Expected Behavior

The dynamic variable should be resolved before glob expansion so that valid paths such as parent/**/* are used instead of /**/*.

Tasks task-2 and task-3 work correctly because they use either literal strings or static variables.

Actual Behavior

The placeholder {{.PARENT}} is not expanded in the sources field during the checksumming phase, resulting in an invalid pattern like /**/*, which leads to excessive or infinite symlink traversal under the new globbing logic.

Additional Context

This issue stems from the fact that dynamic variables are resolved only in CompiledTask(), but sources globs are evaluated earlier in FastCompiledTask() - where dynamic variables remain unresolved.

Possible Fix?

Ensure dynamic variables in sources are resolved before glob expansion. This likely involves moving variable interpolation earlier in the task compilation lifecycle or deferring glob resolution until after dynamic vars are available.

Workarounds

Avoid using dynamic variables directly in sources; prefer static values defined without shell commands.

Version

3.43.0 - latest (3.44.1)

Operating system

Ubuntu 22.04.5 LTS (Jammy Jellyfish)

Experiments Enabled

No response

Example Taskfile

version: "3"

vars:
  PARENT:
    sh: "echo parent"
  STATIC_PARENT: "parent"

tasks:
  task-1:
    sources:
      - "{{.PARENT}}/**/*"
    cmds:
      - "echo task-1 {{.PARENT}}/**/*"
  task-2:
    sources:
      - "parent/**/*"
    cmds:
      - "echo task-2 parent/**/*"
  task-3:
    sources:
      - "{{.STATIC_PARENT}}/**/*"
    cmds:
      - "echo task-3 {{.STATIC_PARENT}}/**/*"

Metadata

Metadata

Assignees

No one assigned

    Labels

    state: needs triageWaiting to be triaged by a maintainer.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions