Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support looping over map variables #1436

Merged
merged 2 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions docs/docs/experiments/any_variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ tasks:
```
There are many more templating functions which can be used with the new types of
variables. For a full list, see the
[slim-sprig][slim-sprig] documentation.
variables. For a full list, see the [slim-sprig][slim-sprig] documentation.
## Looping over variables
Expand All @@ -86,8 +85,8 @@ tasks:
cmd: echo {{.ITEM}}
```

Because this experiment adds support for array variables, the `for` keyword has
been updated to support looping over arrays directly:
Because this experiment adds support for "collection-type" variables, the `for`
keyword has been updated to support looping over arrays directly:

```yaml
version: 3
Expand All @@ -102,6 +101,30 @@ tasks:
cmd: echo {{.ITEM}}
```

This also works for maps. When looping over a map we also make an additional
`{{.KEY}}` variable availabe that holds the string value of the map key.
Remember that maps are unordered, so the order in which the items are looped
over is random:

```yaml
version: 3
tasks:
foo:
vars:
MAP:
KEY_1:
SUBKEY: sub_value_1
KEY_2:
SUBKEY: sub_value_2
KEY_3:
SUBKEY: sub_value_3
cmds:
- for:
var: MAP
cmd: echo {{.KEY}} {{.ITEM.SUBKEY}}
```

String splitting is still supported and remember that for simple cases, you have
always been able to loop over an array without using variables at all:

Expand Down
26 changes: 26 additions & 0 deletions testdata/vars/any/Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ tasks:
- task: string-array
- task: for-string
- task: for-int
- task: for-map
- task: for-multi-layer-map

dynamic:
vars:
Expand Down Expand Up @@ -78,3 +80,27 @@ tasks:
var: LIST
cmd: echo {{add .ITEM 100}}

for-map:
vars:
MAP:
KEY_1: value_1
KEY_2: value_2
KEY_3: value_3
cmds:
- for:
var: MAP
cmd: echo {{.KEY}} {{.ITEM}}

for-multi-layer-map:
vars:
MAP:
KEY_1:
SUBKEY: sub_value_1
KEY_2:
SUBKEY: sub_value_2
KEY_3:
SUBKEY: sub_value_3
cmds:
- for:
var: MAP
cmd: echo {{.KEY}} {{.ITEM.SUBKEY}}
12 changes: 8 additions & 4 deletions variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
continue
}
if cmd.For != nil {
var keys []string
var list []any
// Get the list from the explicit for list
if cmd.For.List != nil && len(cmd.For.List) > 0 {
Expand Down Expand Up @@ -170,9 +171,9 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
case []any:
list = value
case map[string]any:
return &taskfile.Task{}, errors.TaskfileInvalidError{
URI: origTask.Location.Taskfile,
Err: errors.New("sh is not supported with the 'Any Variables' experiment enabled.\nSee https://taskfile.dev/experiments/any-variables for more information."),
for k, v := range value {
keys = append(keys, k)
list = append(list, v)
}
default:
return nil, errors.TaskfileInvalidError{
Expand All @@ -191,10 +192,13 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
as = "ITEM"
}
// Create a new command for each item in the list
for _, loopValue := range list {
for i, loopValue := range list {
extra := map[string]any{
as: loopValue,
}
if len(keys) > 0 {
extra["KEY"] = keys[i]
}
new.Cmds = append(new.Cmds, &taskfile.Cmd{
Cmd: r.ReplaceWithExtra(cmd.Cmd, extra),
Task: r.ReplaceWithExtra(cmd.Task, extra),
Expand Down