Skip to content

Commit b592648

Browse files
authored
feat: support looping over map variables (#1436)
* feat: support looping over map variables * feat: add .KEY variable
1 parent 658b601 commit b592648

File tree

3 files changed

+61
-8
lines changed

3 files changed

+61
-8
lines changed

docs/docs/experiments/any_variables.md

+27-4
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ tasks:
6363
```
6464
6565
There are many more templating functions which can be used with the new types of
66-
variables. For a full list, see the
67-
[slim-sprig][slim-sprig] documentation.
66+
variables. For a full list, see the [slim-sprig][slim-sprig] documentation.
6867
6968
## Looping over variables
7069
@@ -86,8 +85,8 @@ tasks:
8685
cmd: echo {{.ITEM}}
8786
```
8887

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

9291
```yaml
9392
version: 3
@@ -102,6 +101,30 @@ tasks:
102101
cmd: echo {{.ITEM}}
103102
```
104103

104+
This also works for maps. When looping over a map we also make an additional
105+
`{{.KEY}}` variable availabe that holds the string value of the map key.
106+
Remember that maps are unordered, so the order in which the items are looped
107+
over is random:
108+
109+
```yaml
110+
version: 3
111+
112+
tasks:
113+
foo:
114+
vars:
115+
MAP:
116+
KEY_1:
117+
SUBKEY: sub_value_1
118+
KEY_2:
119+
SUBKEY: sub_value_2
120+
KEY_3:
121+
SUBKEY: sub_value_3
122+
cmds:
123+
- for:
124+
var: MAP
125+
cmd: echo {{.KEY}} {{.ITEM.SUBKEY}}
126+
```
127+
105128
String splitting is still supported and remember that for simple cases, you have
106129
always been able to loop over an array without using variables at all:
107130

testdata/vars/any/Taskfile.yml

+26
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ tasks:
99
- task: string-array
1010
- task: for-string
1111
- task: for-int
12+
- task: for-map
13+
- task: for-multi-layer-map
1214

1315
dynamic:
1416
vars:
@@ -78,3 +80,27 @@ tasks:
7880
var: LIST
7981
cmd: echo {{add .ITEM 100}}
8082

83+
for-map:
84+
vars:
85+
MAP:
86+
KEY_1: value_1
87+
KEY_2: value_2
88+
KEY_3: value_3
89+
cmds:
90+
- for:
91+
var: MAP
92+
cmd: echo {{.KEY}} {{.ITEM}}
93+
94+
for-multi-layer-map:
95+
vars:
96+
MAP:
97+
KEY_1:
98+
SUBKEY: sub_value_1
99+
KEY_2:
100+
SUBKEY: sub_value_2
101+
KEY_3:
102+
SUBKEY: sub_value_3
103+
cmds:
104+
- for:
105+
var: MAP
106+
cmd: echo {{.KEY}} {{.ITEM.SUBKEY}}

variables.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
133133
continue
134134
}
135135
if cmd.For != nil {
136+
var keys []string
136137
var list []any
137138
// Get the list from the explicit for list
138139
if cmd.For.List != nil && len(cmd.For.List) > 0 {
@@ -170,9 +171,9 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
170171
case []any:
171172
list = value
172173
case map[string]any:
173-
return &taskfile.Task{}, errors.TaskfileInvalidError{
174-
URI: origTask.Location.Taskfile,
175-
Err: errors.New("sh is not supported with the 'Any Variables' experiment enabled.\nSee https://taskfile.dev/experiments/any-variables for more information."),
174+
for k, v := range value {
175+
keys = append(keys, k)
176+
list = append(list, v)
176177
}
177178
default:
178179
return nil, errors.TaskfileInvalidError{
@@ -191,10 +192,13 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
191192
as = "ITEM"
192193
}
193194
// Create a new command for each item in the list
194-
for _, loopValue := range list {
195+
for i, loopValue := range list {
195196
extra := map[string]any{
196197
as: loopValue,
197198
}
199+
if len(keys) > 0 {
200+
extra["KEY"] = keys[i]
201+
}
198202
new.Cmds = append(new.Cmds, &taskfile.Cmd{
199203
Cmd: r.ReplaceWithExtra(cmd.Cmd, extra),
200204
Task: r.ReplaceWithExtra(cmd.Task, extra),

0 commit comments

Comments
 (0)